Skip to content

Commit

Permalink
Merge pull request #6740 from onflow/janez/port-evm-fixes
Browse files Browse the repository at this point in the history
Copy slice when setting block hash list - Port
  • Loading branch information
j1010001 authored Nov 19, 2024
2 parents 4162017 + cf177b5 commit 39b6c7f
Show file tree
Hide file tree
Showing 19 changed files with 598 additions and 78 deletions.
15 changes: 8 additions & 7 deletions fvm/evm/debug/tracer_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package debug
package debug_test

import (
"encoding/json"
Expand All @@ -11,6 +11,7 @@ import (
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"

"github.com/onflow/flow-go/fvm/evm/debug"
"github.com/onflow/flow-go/fvm/evm/testutils"
"github.com/onflow/flow-go/model/flow"
)
Expand All @@ -23,13 +24,13 @@ func Test_CallTracer(t *testing.T) {

mockUpload := &testutils.MockUploader{
UploadFunc: func(id string, message json.RawMessage) error {
require.Equal(t, TraceID(txID, blockID), id)
require.Equal(t, debug.TraceID(txID, blockID), id)
require.Equal(t, res, message)
return nil
},
}

tracer, err := NewEVMCallTracer(mockUpload, zerolog.Nop())
tracer, err := debug.NewEVMCallTracer(mockUpload, zerolog.Nop())
require.NoError(t, err)
tracer.WithBlockID(blockID)

Expand Down Expand Up @@ -61,13 +62,13 @@ func Test_CallTracer(t *testing.T) {

mockUpload := &testutils.MockUploader{
UploadFunc: func(id string, message json.RawMessage) error {
require.Equal(t, TraceID(txID, blockID), id)
require.Equal(t, debug.TraceID(txID, blockID), id)
require.Equal(t, res, message)
return nil
},
}

tracer, err := NewEVMCallTracer(mockUpload, zerolog.Nop())
tracer, err := debug.NewEVMCallTracer(mockUpload, zerolog.Nop())
require.NoError(t, err)
tracer.WithBlockID(blockID)

Expand Down Expand Up @@ -107,7 +108,7 @@ func Test_CallTracer(t *testing.T) {
},
}

tracer, err := NewEVMCallTracer(mockUpload, zerolog.Nop())
tracer, err := debug.NewEVMCallTracer(mockUpload, zerolog.Nop())
require.NoError(t, err)
tracer.WithBlockID(blockID)

Expand All @@ -117,7 +118,7 @@ func Test_CallTracer(t *testing.T) {
})

t.Run("nop tracer", func(t *testing.T) {
tracer := nopTracer{}
tracer := debug.NopTracer
require.Nil(t, tracer.TxTracer())
})
}
9 changes: 5 additions & 4 deletions fvm/evm/debug/uploader_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package debug
package debug_test

import (
"context"
Expand All @@ -16,6 +16,7 @@ import (
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"

"github.com/onflow/flow-go/fvm/evm/debug"
"github.com/onflow/flow-go/model/flow"
testutils "github.com/onflow/flow-go/utils/unittest"
)
Expand All @@ -27,7 +28,7 @@ func Test_Uploader(t *testing.T) {
testutils.SkipUnless(t, testutils.TEST_REQUIRES_GCP_ACCESS, "requires GCP Bucket setup")

t.Run("successfuly upload traces", func(t *testing.T) {
uploader, err := NewGCPUploader(bucket)
uploader, err := debug.NewGCPUploader(bucket)
require.NoError(t, err)

const testID = "test_p"
Expand Down Expand Up @@ -56,10 +57,10 @@ func Test_TracerUploaderIntegration(t *testing.T) {
testutils.SkipUnless(t, testutils.TEST_REQUIRES_GCP_ACCESS, "requires GCP Bucket setup")

t.Run("successfuly uploads traces", func(t *testing.T) {
uploader, err := NewGCPUploader(bucket)
uploader, err := debug.NewGCPUploader(bucket)
require.NoError(t, err)

tracer, err := NewEVMCallTracer(uploader, zerolog.Nop())
tracer, err := debug.NewEVMCallTracer(uploader, zerolog.Nop())
require.NoError(t, err)

tr := tracer.TxTracer()
Expand Down
2 changes: 1 addition & 1 deletion fvm/evm/emulator/emulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ func TestTransactionTracing(t *testing.T) {
testAccount.Address(),
types.Address{0x01, 0x02},
testContract.ByteCode,
1_000_000,
2_000_000,
big.NewInt(0),
testAccount.Nonce(),
),
Expand Down
63 changes: 19 additions & 44 deletions fvm/evm/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/onflow/cadence"
"github.com/onflow/cadence/encoding/ccf"
gethCommon "github.com/onflow/go-ethereum/common"
"github.com/onflow/go-ethereum/rlp"

"github.com/onflow/flow-go/fvm/evm/stdlib"
"github.com/onflow/flow-go/fvm/evm/types"
Expand Down Expand Up @@ -56,51 +55,27 @@ func NewTransactionEvent(
}

func (p *transactionEvent) ToCadence(chainID flow.ChainID) (cadence.Event, error) {
var encodedLogs []byte
var err error
if len(p.Result.Logs) > 0 {
encodedLogs, err = rlp.EncodeToBytes(p.Result.Logs)
if err != nil {
return cadence.Event{}, err
}
}

deployedAddress := cadence.String("")
if p.Result.DeployedContractAddress != nil {
deployedAddress = cadence.String(p.Result.DeployedContractAddress.String())
}

errorMsg := ""
if p.Result.VMError != nil {
errorMsg = p.Result.VMError.Error()
}
// both error would never happen at the same time
// but in case the priority is by validation error
if p.Result.ValidationError != nil {
errorMsg = p.Result.ValidationError.Error()
encodedLogs, err := p.Result.RLPEncodedLogs()
if err != nil {
return cadence.Event{}, err
}

eventType := stdlib.CadenceTypesForChain(chainID).TransactionExecuted

// the first 4 bytes of StateChangeCommitment is used as checksum
var checksum [ChecksumLength]byte
if len(p.Result.StateChangeCommitment) >= ChecksumLength {
copy(checksum[:ChecksumLength], p.Result.StateChangeCommitment[:ChecksumLength])
}
return cadence.NewEvent([]cadence.Value{
hashToCadenceArrayValue(p.Result.TxHash),
cadence.NewUInt16(p.Result.Index),
cadence.NewUInt8(p.Result.TxType),
bytesToCadenceUInt8ArrayValue(p.Payload),
cadence.NewUInt16(uint16(p.Result.ResultSummary().ErrorCode)),
cadence.String(errorMsg),
cadence.String(p.Result.ErrorMsg()),
cadence.NewUInt64(p.Result.GasConsumed),
deployedAddress,
cadence.String(p.Result.DeployedContractAddressString()),
bytesToCadenceUInt8ArrayValue(encodedLogs),
cadence.NewUInt64(p.BlockHeight),
bytesToCadenceUInt8ArrayValue(p.Result.ReturnedData),
bytesToCadenceUInt8ArrayValue(p.Result.PrecompiledCalls),
checksumToCadenceArrayValue(checksum),
checksumToCadenceArrayValue(p.Result.StateChangeChecksum()),
}).WithType(eventType), nil
}

Expand Down Expand Up @@ -194,19 +169,19 @@ func DecodeBlockEventPayload(event cadence.Event) (*BlockEventPayload, error) {
}

type TransactionEventPayload struct {
Hash gethCommon.Hash `cadence:"hash"`
Index uint16 `cadence:"index"`
TransactionType uint8 `cadence:"type"`
Payload []byte `cadence:"payload"`
ErrorCode uint16 `cadence:"errorCode"`
GasConsumed uint64 `cadence:"gasConsumed"`
ContractAddress string `cadence:"contractAddress"`
Logs []byte `cadence:"logs"`
BlockHeight uint64 `cadence:"blockHeight"`
ErrorMessage string `cadence:"errorMessage"`
ReturnedData []byte `cadence:"returnedData"`
PrecompiledCalls []byte `cadence:"precompiledCalls"`
StateUpdateChecksum [ChecksumLength]byte `cadence:"stateUpdateChecksum"`
Hash gethCommon.Hash `cadence:"hash"`
Index uint16 `cadence:"index"`
TransactionType uint8 `cadence:"type"`
Payload []byte `cadence:"payload"`
ErrorCode uint16 `cadence:"errorCode"`
GasConsumed uint64 `cadence:"gasConsumed"`
ContractAddress string `cadence:"contractAddress"`
Logs []byte `cadence:"logs"`
BlockHeight uint64 `cadence:"blockHeight"`
ErrorMessage string `cadence:"errorMessage"`
ReturnedData []byte `cadence:"returnedData"`
PrecompiledCalls []byte `cadence:"precompiledCalls"`
StateUpdateChecksum [types.ChecksumLength]byte `cadence:"stateUpdateChecksum"`
}

// transactionEventPayloadV0 legacy format of the transaction event without stateUpdateChecksum field
Expand Down
2 changes: 1 addition & 1 deletion fvm/evm/events/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func TestEVMTransactionExecutedEventCCFEncodingDecoding(t *testing.T) {
assert.Equal(t, tep.GasConsumed, txResult.GasConsumed)
assert.Equal(t, tep.ErrorMessage, txResult.VMError.Error())
assert.Equal(t, tep.ReturnedData, txResult.ReturnedData)
assert.Equal(t, tep.StateUpdateChecksum[:], stateUpdateCommit[:events.ChecksumLength])
assert.Equal(t, tep.StateUpdateChecksum[:], stateUpdateCommit[:types.ChecksumLength])
assert.Equal(
t,
tep.ContractAddress,
Expand Down
13 changes: 6 additions & 7 deletions fvm/evm/events/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package events
import (
"github.com/onflow/cadence"
gethCommon "github.com/onflow/go-ethereum/common"

"github.com/onflow/flow-go/fvm/evm/types"
)

// cadenceArrayTypeOfUInt8 is the Cadence type [UInt8]
Expand Down Expand Up @@ -31,16 +33,13 @@ func hashToCadenceArrayValue(hash gethCommon.Hash) cadence.Array {
WithType(cadenceHashType)
}

// ChecksumLength captures number of bytes a checksum uses
const ChecksumLength = 4

// checksumType is the Cadence type [UInt8;4]
var checksumType = cadence.NewConstantSizedArrayType(ChecksumLength, cadence.UInt8Type)
var checksumType = cadence.NewConstantSizedArrayType(types.ChecksumLength, cadence.UInt8Type)

// checksumToCadenceArrayValue converts a checksum ([4]byte) into a Cadence array of type [UInt8;4]
func checksumToCadenceArrayValue(checksum [ChecksumLength]byte) cadence.Array {
values := make([]cadence.Value, ChecksumLength)
for i := 0; i < ChecksumLength; i++ {
func checksumToCadenceArrayValue(checksum [types.ChecksumLength]byte) cadence.Array {
values := make([]cadence.Value, types.ChecksumLength)
for i := 0; i < types.ChecksumLength; i++ {
values[i] = cadence.NewUInt8(checksum[i])
}
return cadence.NewArray(values).
Expand Down
13 changes: 9 additions & 4 deletions fvm/evm/handler/blockHashList.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const (
// smaller fixed size buckets to minimize the
// number of bytes read and written during set/get operations.
type BlockHashList struct {
backend types.Backend
backend types.BackendStorage
rootAddress flow.Address

// cached meta data
Expand All @@ -46,7 +46,7 @@ type BlockHashList struct {
// It tries to load the metadata from the backend
// and if not exist it creates one
func NewBlockHashList(
backend types.Backend,
backend types.BackendStorage,
rootAddress flow.Address,
capacity int,
) (*BlockHashList, error) {
Expand Down Expand Up @@ -84,6 +84,7 @@ func (bhl *BlockHashList) Push(height uint64, bh gethCommon.Hash) error {
if !bhl.IsEmpty() && height != bhl.height+1 {
return fmt.Errorf("out of the order block hash, expected: %d, got: %d", bhl.height+1, height)
}

// updates the block hash stored at index
err := bhl.updateBlockHashAt(bhl.tail, bh)
if err != nil {
Expand Down Expand Up @@ -150,16 +151,20 @@ func (bhl *BlockHashList) updateBlockHashAt(idx int, bh gethCommon.Hash) error {
if err != nil {
return err
}

cpy := make([]byte, len(bucket))
copy(cpy, bucket)

// update the block hash
start := (idx % hashCountPerBucket) * hashEncodingSize
end := start + hashEncodingSize
copy(bucket[start:end], bh.Bytes())
copy(cpy[start:end], bh.Bytes())

// store bucket
return bhl.backend.SetValue(
bhl.rootAddress[:],
[]byte(fmt.Sprintf(blockHashListBucketKeyFormat, bucketNumber)),
bucket,
cpy,
)
}

Expand Down
Loading

0 comments on commit 39b6c7f

Please sign in to comment.