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

     1  package derive
     2  
     3  import (
     4  	"math/rand"
     5  	"testing"
     6  
     7  	"github.com/ethereum-optimism/optimism/op-node/rollup"
     8  	"github.com/ethereum-optimism/optimism/op-service/eth"
     9  
    10  	"github.com/ethereum-optimism/optimism/op-service/testlog"
    11  	"github.com/ethereum-optimism/optimism/op-service/testutils"
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/common/hexutil"
    14  	"github.com/ethereum/go-ethereum/core/types"
    15  	"github.com/ethereum/go-ethereum/log"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  var (
    20  	validParentHash       = common.HexToHash("0x123")
    21  	validTimestamp        = eth.Uint64Quantity(123)
    22  	validParentBeaconRoot = common.HexToHash("0x456")
    23  	validPrevRandao       = eth.Bytes32(common.HexToHash("0x789"))
    24  	validGasLimit         = eth.Uint64Quantity(1000)
    25  	validWithdrawals      = types.Withdrawals{}
    26  )
    27  
    28  type args struct {
    29  	envelope   *eth.ExecutionPayloadEnvelope
    30  	attrs      *eth.PayloadAttributes
    31  	parentHash common.Hash
    32  }
    33  
    34  func ecotoneArgs() args {
    35  	return args{
    36  		envelope: &eth.ExecutionPayloadEnvelope{
    37  			ParentBeaconBlockRoot: &validParentBeaconRoot,
    38  			ExecutionPayload: &eth.ExecutionPayload{
    39  				ParentHash:  validParentHash,
    40  				Timestamp:   validTimestamp,
    41  				PrevRandao:  validPrevRandao,
    42  				GasLimit:    validGasLimit,
    43  				Withdrawals: &validWithdrawals,
    44  			},
    45  		},
    46  		attrs: &eth.PayloadAttributes{
    47  			Timestamp:             validTimestamp,
    48  			PrevRandao:            validPrevRandao,
    49  			GasLimit:              &validGasLimit,
    50  			ParentBeaconBlockRoot: &validParentBeaconRoot,
    51  			Withdrawals:           &validWithdrawals,
    52  		},
    53  		parentHash: validParentHash,
    54  	}
    55  }
    56  
    57  func canyonArgs() args {
    58  	args := ecotoneArgs()
    59  	args.attrs.ParentBeaconBlockRoot = nil
    60  	args.envelope.ParentBeaconBlockRoot = nil
    61  	return args
    62  }
    63  
    64  func bedrockArgs() args {
    65  	args := ecotoneArgs()
    66  	args.attrs.Withdrawals = nil
    67  	args.envelope.ExecutionPayload.Withdrawals = nil
    68  	return args
    69  }
    70  
    71  func ecotoneNoParentBeaconBlockRoot() args {
    72  	args := ecotoneArgs()
    73  	args.envelope.ParentBeaconBlockRoot = nil
    74  	return args
    75  }
    76  
    77  func ecotoneUnexpectedParentBeaconBlockRoot() args {
    78  	args := ecotoneArgs()
    79  	args.attrs.ParentBeaconBlockRoot = nil
    80  	return args
    81  }
    82  
    83  func ecotoneMismatchParentBeaconBlockRoot() args {
    84  	args := ecotoneArgs()
    85  	h := common.HexToHash("0xabc")
    86  	args.attrs.ParentBeaconBlockRoot = &h
    87  	return args
    88  }
    89  
    90  func ecotoneMismatchParentBeaconBlockRootPtr() args {
    91  	args := ecotoneArgs()
    92  	cpy := *args.attrs.ParentBeaconBlockRoot
    93  	args.attrs.ParentBeaconBlockRoot = &cpy
    94  	return args
    95  }
    96  
    97  func ecotoneNilParentBeaconBlockRoots() args {
    98  	args := ecotoneArgs()
    99  	args.attrs.ParentBeaconBlockRoot = nil
   100  	args.envelope.ParentBeaconBlockRoot = nil
   101  	return args
   102  }
   103  
   104  func mismatchedParentHashArgs() args {
   105  	args := ecotoneArgs()
   106  	args.parentHash = common.HexToHash("0xabc")
   107  	return args
   108  }
   109  
   110  func createMistmatchedPrevRandao() args {
   111  	args := ecotoneArgs()
   112  	args.attrs.PrevRandao = eth.Bytes32(common.HexToHash("0xabc"))
   113  	return args
   114  }
   115  
   116  func createMismatchedGasLimit() args {
   117  	args := ecotoneArgs()
   118  	val := eth.Uint64Quantity(2000)
   119  	args.attrs.GasLimit = &val
   120  	return args
   121  }
   122  
   123  func createNilGasLimit() args {
   124  	args := ecotoneArgs()
   125  	args.attrs.GasLimit = nil
   126  	return args
   127  }
   128  
   129  func createMistmatchedTimestamp() args {
   130  	args := ecotoneArgs()
   131  	val := eth.Uint64Quantity(2000)
   132  	args.attrs.Timestamp = val
   133  	return args
   134  }
   135  
   136  func TestAttributesMatch(t *testing.T) {
   137  	rollupCfg := &rollup.Config{}
   138  
   139  	tests := []struct {
   140  		shouldMatch bool
   141  		args        args
   142  	}{
   143  		{
   144  			shouldMatch: true,
   145  			args:        ecotoneArgs(),
   146  		},
   147  		{
   148  			shouldMatch: true,
   149  			args:        canyonArgs(),
   150  		},
   151  		{
   152  			shouldMatch: true,
   153  			args:        bedrockArgs(),
   154  		},
   155  		{
   156  			shouldMatch: false,
   157  			args:        mismatchedParentHashArgs(),
   158  		},
   159  		{
   160  			shouldMatch: false,
   161  			args:        ecotoneNoParentBeaconBlockRoot(),
   162  		},
   163  		{
   164  			shouldMatch: false,
   165  			args:        ecotoneUnexpectedParentBeaconBlockRoot(),
   166  		},
   167  		{
   168  			shouldMatch: false,
   169  			args:        ecotoneMismatchParentBeaconBlockRoot(),
   170  		},
   171  		{
   172  			shouldMatch: true,
   173  			args:        ecotoneMismatchParentBeaconBlockRootPtr(),
   174  		},
   175  		{
   176  			shouldMatch: true,
   177  			args:        ecotoneNilParentBeaconBlockRoots(),
   178  		},
   179  		{
   180  			shouldMatch: false,
   181  			args:        createMistmatchedPrevRandao(),
   182  		},
   183  		{
   184  			shouldMatch: false,
   185  			args:        createMismatchedGasLimit(),
   186  		},
   187  		{
   188  			shouldMatch: false,
   189  			args:        createNilGasLimit(),
   190  		},
   191  		{
   192  			shouldMatch: false,
   193  			args:        createMistmatchedTimestamp(),
   194  		},
   195  	}
   196  
   197  	for _, test := range tests {
   198  		err := AttributesMatchBlock(rollupCfg, test.args.attrs, test.args.parentHash, test.args.envelope, testlog.Logger(t, log.LevelInfo))
   199  		if test.shouldMatch {
   200  			require.NoError(t, err)
   201  		} else {
   202  			require.Error(t, err)
   203  		}
   204  	}
   205  }
   206  
   207  func TestWithdrawalsMatch(t *testing.T) {
   208  	tests := []struct {
   209  		attrs       *types.Withdrawals
   210  		block       *types.Withdrawals
   211  		shouldMatch bool
   212  	}{
   213  		{
   214  			attrs:       nil,
   215  			block:       nil,
   216  			shouldMatch: true,
   217  		},
   218  		{
   219  			attrs:       &types.Withdrawals{},
   220  			block:       nil,
   221  			shouldMatch: false,
   222  		},
   223  		{
   224  			attrs:       nil,
   225  			block:       &types.Withdrawals{},
   226  			shouldMatch: false,
   227  		},
   228  		{
   229  			attrs:       &types.Withdrawals{},
   230  			block:       &types.Withdrawals{},
   231  			shouldMatch: true,
   232  		},
   233  		{
   234  			attrs: &types.Withdrawals{
   235  				{
   236  					Index: 1,
   237  				},
   238  			},
   239  			block:       &types.Withdrawals{},
   240  			shouldMatch: false,
   241  		},
   242  		{
   243  			attrs: &types.Withdrawals{
   244  				{
   245  					Index: 1,
   246  				},
   247  			},
   248  			block: &types.Withdrawals{
   249  				{
   250  					Index: 2,
   251  				},
   252  			},
   253  			shouldMatch: false,
   254  		},
   255  	}
   256  
   257  	for _, test := range tests {
   258  		err := checkWithdrawalsMatch(test.attrs, test.block)
   259  
   260  		if test.shouldMatch {
   261  			require.NoError(t, err)
   262  		} else {
   263  			require.Error(t, err)
   264  		}
   265  	}
   266  }
   267  
   268  func TestGetMissingTxnHashes(t *testing.T) {
   269  	depositTxs := make([]*types.Transaction, 5)
   270  
   271  	for i := 0; i < len(depositTxs); i++ {
   272  		rng := rand.New(rand.NewSource(1234 + int64(i)))
   273  		safeDeposit := testutils.GenerateDeposit(testutils.RandomHash(rng), rng)
   274  		depositTxs[i] = types.NewTx(safeDeposit)
   275  	}
   276  
   277  	tests := []struct {
   278  		safeTransactions            []hexutil.Bytes
   279  		unsafeTransactions          []hexutil.Bytes
   280  		expectedSafeMissingHashes   []common.Hash
   281  		expectedUnsafeMissingHashes []common.Hash
   282  		expectErr                   bool
   283  	}{
   284  		{
   285  			safeTransactions:            []hexutil.Bytes{},
   286  			unsafeTransactions:          []hexutil.Bytes{depositTxToBytes(t, depositTxs[0])},
   287  			expectedSafeMissingHashes:   []common.Hash{depositTxs[0].Hash()},
   288  			expectedUnsafeMissingHashes: []common.Hash{},
   289  			expectErr:                   false,
   290  		},
   291  		{
   292  			safeTransactions:            []hexutil.Bytes{depositTxToBytes(t, depositTxs[0])},
   293  			unsafeTransactions:          []hexutil.Bytes{},
   294  			expectedSafeMissingHashes:   []common.Hash{},
   295  			expectedUnsafeMissingHashes: []common.Hash{depositTxs[0].Hash()},
   296  			expectErr:                   false,
   297  		},
   298  		{
   299  			safeTransactions: []hexutil.Bytes{
   300  				depositTxToBytes(t, depositTxs[0]),
   301  			},
   302  			unsafeTransactions: []hexutil.Bytes{
   303  				depositTxToBytes(t, depositTxs[0]),
   304  				depositTxToBytes(t, depositTxs[1]),
   305  				depositTxToBytes(t, depositTxs[2]),
   306  			},
   307  			expectedSafeMissingHashes: []common.Hash{
   308  				depositTxs[1].Hash(),
   309  				depositTxs[2].Hash(),
   310  			},
   311  			expectedUnsafeMissingHashes: []common.Hash{},
   312  			expectErr:                   false,
   313  		},
   314  		{
   315  			safeTransactions: []hexutil.Bytes{
   316  				depositTxToBytes(t, depositTxs[0]),
   317  				depositTxToBytes(t, depositTxs[1]),
   318  				depositTxToBytes(t, depositTxs[2]),
   319  			},
   320  			unsafeTransactions: []hexutil.Bytes{
   321  				depositTxToBytes(t, depositTxs[0]),
   322  			},
   323  			expectedSafeMissingHashes: []common.Hash{},
   324  			expectedUnsafeMissingHashes: []common.Hash{
   325  				depositTxs[1].Hash(),
   326  				depositTxs[2].Hash(),
   327  			},
   328  			expectErr: false,
   329  		},
   330  		{
   331  			safeTransactions: []hexutil.Bytes{
   332  				depositTxToBytes(t, depositTxs[0]),
   333  				depositTxToBytes(t, depositTxs[1]),
   334  				depositTxToBytes(t, depositTxs[2]),
   335  			},
   336  			unsafeTransactions: []hexutil.Bytes{
   337  				depositTxToBytes(t, depositTxs[2]),
   338  				depositTxToBytes(t, depositTxs[3]),
   339  				depositTxToBytes(t, depositTxs[4]),
   340  			},
   341  			expectedSafeMissingHashes: []common.Hash{
   342  				depositTxs[3].Hash(),
   343  				depositTxs[4].Hash(),
   344  			},
   345  			expectedUnsafeMissingHashes: []common.Hash{
   346  				depositTxs[0].Hash(),
   347  				depositTxs[1].Hash(),
   348  			},
   349  			expectErr: false,
   350  		},
   351  		{
   352  			safeTransactions:            []hexutil.Bytes{{1, 2, 3}},
   353  			unsafeTransactions:          []hexutil.Bytes{},
   354  			expectedSafeMissingHashes:   []common.Hash{},
   355  			expectedUnsafeMissingHashes: []common.Hash{},
   356  			expectErr:                   true,
   357  		},
   358  		{
   359  			safeTransactions:            []hexutil.Bytes{},
   360  			unsafeTransactions:          []hexutil.Bytes{{1, 2, 3}},
   361  			expectedSafeMissingHashes:   []common.Hash{},
   362  			expectedUnsafeMissingHashes: []common.Hash{},
   363  			expectErr:                   true,
   364  		},
   365  	}
   366  
   367  	for _, test := range tests {
   368  		missingSafeHashes, missingUnsafeHashes, err := getMissingTxnHashes(
   369  			testlog.Logger(t, log.LevelError),
   370  			test.safeTransactions,
   371  			test.unsafeTransactions,
   372  		)
   373  
   374  		if test.expectErr {
   375  			require.Error(t, err)
   376  		} else {
   377  			require.NoError(t, err)
   378  			require.ElementsMatch(t, test.expectedSafeMissingHashes, missingSafeHashes)
   379  			require.ElementsMatch(t, test.expectedUnsafeMissingHashes, missingUnsafeHashes)
   380  		}
   381  	}
   382  }
   383  
   384  func depositTxToBytes(t *testing.T, tx *types.Transaction) hexutil.Bytes {
   385  	txBytes, err := tx.MarshalBinary()
   386  	require.NoError(t, err)
   387  
   388  	return txBytes
   389  }