github.com/ethereum-optimism/optimism@v1.7.2/op-node/rollup/derive/payloads_queue_test.go (about)

     1  package derive
     2  
     3  import (
     4  	"container/heap"
     5  	"testing"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	"github.com/ethereum/go-ethereum/log"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/ethereum-optimism/optimism/op-service/eth"
    12  	"github.com/ethereum-optimism/optimism/op-service/testlog"
    13  )
    14  
    15  func TestPayloadsByNumber(t *testing.T) {
    16  	p := payloadsByNumber{}
    17  	mk := func(i uint64) payloadAndSize {
    18  		return payloadAndSize{
    19  			envelope: &eth.ExecutionPayloadEnvelope{
    20  				ExecutionPayload: &eth.ExecutionPayload{
    21  					BlockNumber: eth.Uint64Quantity(i),
    22  				},
    23  			},
    24  		}
    25  	}
    26  	// add payload A, check it was added
    27  	a := mk(123)
    28  	heap.Push(&p, a)
    29  	require.Equal(t, p.Len(), 1)
    30  	require.Equal(t, p[0], a)
    31  
    32  	// add payload B, check it was added in top-priority spot
    33  	b := mk(100)
    34  	heap.Push(&p, b)
    35  	require.Equal(t, p.Len(), 2)
    36  	require.Equal(t, p[0], b)
    37  
    38  	// add payload C, check it did not get first like B, since block num is higher
    39  	c := mk(150)
    40  	heap.Push(&p, c)
    41  	require.Equal(t, p.Len(), 3)
    42  	require.Equal(t, p[0], b) // still b
    43  
    44  	// pop b
    45  	heap.Pop(&p)
    46  	require.Equal(t, p.Len(), 2)
    47  	require.Equal(t, p[0], a)
    48  
    49  	// pop a
    50  	heap.Pop(&p)
    51  	require.Equal(t, p.Len(), 1)
    52  	require.Equal(t, p[0], c)
    53  
    54  	// pop c
    55  	heap.Pop(&p)
    56  	require.Equal(t, p.Len(), 0)
    57  
    58  	// duplicate entry
    59  	heap.Push(&p, b)
    60  	require.Equal(t, p.Len(), 1)
    61  	heap.Push(&p, b)
    62  	require.Equal(t, p.Len(), 2)
    63  	heap.Pop(&p)
    64  	require.Equal(t, p.Len(), 1)
    65  }
    66  
    67  func TestPayloadMemSize(t *testing.T) {
    68  	require.Equal(t, payloadMemFixedCost, payloadMemSize(nil), "nil is same fixed cost")
    69  	require.Equal(t, payloadMemFixedCost, payloadMemSize(&eth.ExecutionPayloadEnvelope{ExecutionPayload: &eth.ExecutionPayload{}}), "empty payload fixed cost")
    70  	require.Equal(t, payloadMemFixedCost+payloadTxMemOverhead, payloadMemSize(&eth.ExecutionPayloadEnvelope{ExecutionPayload: &eth.ExecutionPayload{Transactions: []eth.Data{nil}}}), "nil tx counts")
    71  	require.Equal(t, payloadMemFixedCost+payloadTxMemOverhead, payloadMemSize(&eth.ExecutionPayloadEnvelope{ExecutionPayload: &eth.ExecutionPayload{Transactions: []eth.Data{make([]byte, 0)}}}), "empty tx counts")
    72  	require.Equal(t, payloadMemFixedCost+4*payloadTxMemOverhead+42+1337+0+1,
    73  		payloadMemSize(&eth.ExecutionPayloadEnvelope{ExecutionPayload: &eth.ExecutionPayload{Transactions: []eth.Data{
    74  			make([]byte, 42),
    75  			make([]byte, 1337),
    76  			make([]byte, 0),
    77  			make([]byte, 1),
    78  		}}}), "mixed txs")
    79  }
    80  
    81  func envelope(payload *eth.ExecutionPayload) *eth.ExecutionPayloadEnvelope {
    82  	return &eth.ExecutionPayloadEnvelope{ExecutionPayload: payload}
    83  }
    84  
    85  func TestPayloadsQueue(t *testing.T) {
    86  	pq := NewPayloadsQueue(testlog.Logger(t, log.LvlInfo), payloadMemFixedCost*3, payloadMemSize)
    87  	require.Equal(t, 0, pq.Len())
    88  	require.Nil(t, pq.Peek())
    89  	require.Nil(t, pq.Pop())
    90  
    91  	a := envelope(&eth.ExecutionPayload{BlockNumber: 3, BlockHash: common.Hash{3}})
    92  	b := envelope(&eth.ExecutionPayload{BlockNumber: 4, BlockHash: common.Hash{4}})
    93  	c := envelope(&eth.ExecutionPayload{BlockNumber: 5, BlockHash: common.Hash{5}})
    94  	d := envelope(&eth.ExecutionPayload{BlockNumber: 6, BlockHash: common.Hash{6}})
    95  	bAlt := envelope(&eth.ExecutionPayload{BlockNumber: 4, BlockHash: common.Hash{0xff}})
    96  	bDup := envelope(&eth.ExecutionPayload{BlockNumber: 4, BlockHash: common.Hash{4}})
    97  
    98  	require.NoError(t, pq.Push(b))
    99  	require.Equal(t, pq.Len(), 1)
   100  	require.Equal(t, pq.Peek(), b)
   101  
   102  	require.Error(t, pq.Push(nil), "cannot add nil payloads")
   103  
   104  	require.NoError(t, pq.Push(c))
   105  	require.Equal(t, pq.Len(), 2)
   106  	require.Equal(t, pq.MemSize(), 2*payloadMemFixedCost)
   107  	require.Equal(t, pq.Peek(), b, "expecting b to still be the lowest number payload")
   108  
   109  	require.NoError(t, pq.Push(a))
   110  	require.Equal(t, pq.Len(), 3)
   111  	require.Equal(t, pq.MemSize(), 3*payloadMemFixedCost)
   112  	require.Equal(t, pq.Peek(), a, "expecting a to be new lowest number")
   113  
   114  	require.Equal(t, pq.Pop(), a)
   115  	require.Equal(t, pq.Len(), 2, "expecting to pop the lowest")
   116  
   117  	require.Equal(t, pq.Peek(), b, "expecting b to be lowest, compared to c")
   118  
   119  	require.Equal(t, pq.Pop(), b)
   120  	require.Equal(t, pq.Len(), 1)
   121  	require.Equal(t, pq.MemSize(), payloadMemFixedCost)
   122  
   123  	require.Equal(t, pq.Pop(), c)
   124  	require.Equal(t, pq.Len(), 0, "expecting no items to remain")
   125  
   126  	e := envelope(&eth.ExecutionPayload{BlockNumber: 5, Transactions: []eth.Data{make([]byte, payloadMemFixedCost*3+1)}})
   127  	require.Error(t, pq.Push(e), "cannot add payloads that are too large")
   128  
   129  	require.NoError(t, pq.Push(b))
   130  	require.Equal(t, pq.Len(), 1, "expecting b")
   131  	require.Equal(t, pq.Peek(), b)
   132  	require.NoError(t, pq.Push(c))
   133  	require.Equal(t, pq.Len(), 2, "expecting b, c")
   134  	require.Equal(t, pq.Peek(), b)
   135  	require.NoError(t, pq.Push(a))
   136  	require.Equal(t, pq.Len(), 3, "expecting a, b, c")
   137  	require.Equal(t, pq.Peek(), a)
   138  
   139  	// No duplicates allowed
   140  	require.Error(t, pq.Push(bDup))
   141  	// But reorg data allowed
   142  	require.NoError(t, pq.Push(bAlt))
   143  
   144  	require.NoError(t, pq.Push(d))
   145  	require.Equal(t, pq.Len(), 3)
   146  	require.Equal(t, pq.Peek(), b, "expecting b, c, d")
   147  	require.NotContainsf(t, pq.pq[:], a, "a should be dropped after 3 items already exist under max size constraint")
   148  }