@@ -3,6 +3,7 @@ package fvm_test
33import (
44 "context"
55 "crypto/rand"
6+ "encoding/binary"
67 "encoding/hex"
78 "fmt"
89 "math"
@@ -38,6 +39,7 @@ import (
3839 envMock "github.com/onflow/flow-go/fvm/environment/mock"
3940 "github.com/onflow/flow-go/fvm/errors"
4041 "github.com/onflow/flow-go/fvm/evm/events"
42+ "github.com/onflow/flow-go/fvm/evm/handler"
4143 "github.com/onflow/flow-go/fvm/evm/stdlib"
4244 "github.com/onflow/flow-go/fvm/evm/types"
4345 "github.com/onflow/flow-go/fvm/meter"
@@ -3587,3 +3589,106 @@ func Test_MinimumRequiredVersion(t *testing.T) {
35873589 require .Equal (t , cadenceVersion1 .String (), getVersion (ctx , snapshotTree ))
35883590 }))
35893591}
3592+
3593+ func Test_BlockHashListShouldWriteOnPush (t * testing.T ) {
3594+
3595+ chain := flow .Emulator .Chain ()
3596+ sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
3597+
3598+ push := func (bhl * handler.BlockHashList , height uint64 ) {
3599+ buffer := make ([]byte , 32 )
3600+ pos := 0
3601+
3602+ // encode height as block hash
3603+ binary .BigEndian .PutUint64 (buffer [pos :], height )
3604+ err := bhl .Push (height , [32 ]byte (buffer ))
3605+ require .NoError (t , err )
3606+ }
3607+
3608+ t .Run ("block hash list write on push" , newVMTest ().
3609+ withContextOptions (
3610+ fvm .WithChain (chain ),
3611+ fvm .WithEVMEnabled (true ),
3612+ ).
3613+ run (func (
3614+ t * testing.T ,
3615+ vm fvm.VM ,
3616+ chain flow.Chain ,
3617+ ctx fvm.Context ,
3618+ snapshotTree snapshot.SnapshotTree ,
3619+ ) {
3620+ capacity := 256
3621+
3622+ // for the setup we make sure all the block hash list buckets exist
3623+
3624+ ts := state .NewTransactionState (snapshotTree , state .DefaultParameters ())
3625+ accounts := environment .NewAccounts (ts )
3626+ envMeter := environment .NewMeter (ts )
3627+
3628+ valueStore := environment .NewValueStore (
3629+ tracing .NewMockTracerSpan (),
3630+ envMeter ,
3631+ accounts ,
3632+ )
3633+
3634+ bhl , err := handler .NewBlockHashList (valueStore , sc .EVMStorage .Address , capacity )
3635+ require .NoError (t , err )
3636+
3637+ // fill the block hash list
3638+ height := uint64 (0 )
3639+ for ; height < uint64 (capacity ); height ++ {
3640+ push (bhl , height )
3641+ }
3642+
3643+ es , err := ts .FinalizeMainTransaction ()
3644+ require .NoError (t , err )
3645+ snapshotTree = snapshotTree .Append (es )
3646+
3647+ // end of test setup
3648+
3649+ ts = state .NewTransactionState (snapshotTree , state .DefaultParameters ())
3650+ accounts = environment .NewAccounts (ts )
3651+ envMeter = environment .NewMeter (ts )
3652+
3653+ valueStore = environment .NewValueStore (
3654+ tracing .NewMockTracerSpan (),
3655+ envMeter ,
3656+ accounts ,
3657+ )
3658+
3659+ bhl , err = handler .NewBlockHashList (valueStore , sc .EVMStorage .Address , capacity )
3660+ require .NoError (t , err )
3661+
3662+ // after we push the changes should be applied and the first block hash in the bucket should be capacity+1 instead of 0
3663+ push (bhl , height )
3664+
3665+ es , err = ts .FinalizeMainTransaction ()
3666+ require .NoError (t , err )
3667+
3668+ // the write set should have both block metadata and block hash list bucket
3669+ require .Len (t , es .WriteSet , 2 )
3670+ newBlockHashListBucket , ok := es .WriteSet [flow .NewRegisterID (sc .EVMStorage .Address , "BlockHashListBucket0" )]
3671+ require .True (t , ok )
3672+ // full expected block hash list bucket split by individual block hashes
3673+ // first block hash is the capacity+1 instead of 0 (00 00 00 00 00 00 01 00)
3674+ expectedBlockHashListBucket , err := hex .DecodeString (
3675+ "0000000000000100000000000000000000000000000000000000000000000000" +
3676+ "0000000000000001000000000000000000000000000000000000000000000000" +
3677+ "0000000000000002000000000000000000000000000000000000000000000000" +
3678+ "0000000000000003000000000000000000000000000000000000000000000000" +
3679+ "0000000000000004000000000000000000000000000000000000000000000000" +
3680+ "0000000000000005000000000000000000000000000000000000000000000000" +
3681+ "0000000000000006000000000000000000000000000000000000000000000000" +
3682+ "0000000000000007000000000000000000000000000000000000000000000000" +
3683+ "0000000000000008000000000000000000000000000000000000000000000000" +
3684+ "0000000000000009000000000000000000000000000000000000000000000000" +
3685+ "000000000000000a000000000000000000000000000000000000000000000000" +
3686+ "000000000000000b000000000000000000000000000000000000000000000000" +
3687+ "000000000000000c000000000000000000000000000000000000000000000000" +
3688+ "000000000000000d000000000000000000000000000000000000000000000000" +
3689+ "000000000000000e000000000000000000000000000000000000000000000000" +
3690+ "000000000000000f000000000000000000000000000000000000000000000000" )
3691+ require .NoError (t , err )
3692+ require .Equal (t , expectedBlockHashListBucket , newBlockHashListBucket )
3693+ }))
3694+ }
0 commit comments