Fuzz Remaining Engine Objects (#11049)

* add new fuzz tests

* add fixes

* remove test

* add more checks

* remove comment
This commit is contained in:
Nishant Das
2022-07-14 23:33:32 +08:00
committed by GitHub
parent 819632dfc5
commit d41805a39c
8 changed files with 248 additions and 30 deletions

View File

@@ -8,10 +8,14 @@ import (
"fmt"
"math"
"math/big"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
"github.com/prysmaticlabs/prysm/testing/assert"
@@ -68,6 +72,47 @@ func FuzzForkChoiceResponse(f *testing.F) {
})
}
func FuzzExchangeTransitionConfiguration(f *testing.F) {
valHash := common.Hash([32]byte{0xFF, 0x01})
ttd := hexutil.Big(*big.NewInt(math.MaxInt))
seed := &beacon.TransitionConfigurationV1{
TerminalTotalDifficulty: &ttd,
TerminalBlockHash: valHash,
TerminalBlockNumber: hexutil.Uint64(math.MaxUint64),
}
output, err := json.Marshal(seed)
assert.NoError(f, err)
f.Add(output)
f.Fuzz(func(t *testing.T, jsonBlob []byte) {
gethResp := &beacon.TransitionConfigurationV1{}
prysmResp := &pb.TransitionConfiguration{}
gethErr := json.Unmarshal(jsonBlob, gethResp)
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
// Nothing to marshal if we have an error.
if gethErr != nil {
return
}
gethBlob, gethErr := json.Marshal(gethResp)
prysmBlob, prysmErr := json.Marshal(prysmResp)
if gethErr != nil {
t.Errorf("%s %s", gethResp.TerminalTotalDifficulty.String(), prysmResp.TerminalTotalDifficulty)
}
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
if gethErr != nil {
t.Errorf("%s %s", gethResp.TerminalTotalDifficulty.String(), prysmResp.TerminalTotalDifficulty)
}
newGethResp := &beacon.TransitionConfigurationV1{}
newGethErr := json.Unmarshal(prysmBlob, newGethResp)
assert.NoError(t, newGethErr)
newGethResp2 := &beacon.TransitionConfigurationV1{}
newGethErr = json.Unmarshal(gethBlob, newGethResp2)
assert.NoError(t, newGethErr)
})
}
func FuzzExecutionPayload(f *testing.F) {
logsBloom := [256]byte{'j', 'u', 'n', 'k'}
execData := &beacon.ExecutableDataV1{
@@ -109,6 +154,133 @@ func FuzzExecutionPayload(f *testing.F) {
newGethErr = json.Unmarshal(gethBlob, newGethResp2)
assert.NoError(t, newGethErr)
assert.DeepEqual(t, newGethResp.LogsBloom, newGethResp2.LogsBloom)
assert.DeepEqual(t, newGethResp, newGethResp2)
})
}
func FuzzExecutionBlock(f *testing.F) {
logsBloom := [256]byte{'j', 'u', 'n', 'k'}
addr := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
innerData := &types.DynamicFeeTx{
ChainID: big.NewInt(math.MaxInt),
Nonce: math.MaxUint64,
GasTipCap: big.NewInt(math.MaxInt),
GasFeeCap: big.NewInt(math.MaxInt),
Gas: math.MaxUint64,
To: &addr,
Value: big.NewInt(math.MaxInt),
Data: []byte{'r', 'a', 'n', 'd', 'o', 'm'},
// Signature values
V: big.NewInt(0),
R: big.NewInt(math.MaxInt),
S: big.NewInt(math.MaxInt),
}
tx := types.NewTx(innerData)
execBlock := &pb.ExecutionBlock{
Header: types.Header{
ParentHash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
Root: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
ReceiptHash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
Bloom: types.Bloom(logsBloom),
Number: big.NewInt(math.MaxInt),
GasLimit: math.MaxUint64,
GasUsed: math.MaxUint64,
Time: 100,
Extra: nil,
BaseFee: big.NewInt(math.MaxInt),
Difficulty: big.NewInt(math.MaxInt),
},
Hash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
TotalDifficulty: "999999999999999999999999999999999999999",
Transactions: []*types.Transaction{tx, tx},
}
output, err := json.Marshal(execBlock)
assert.NoError(f, err)
f.Add(output)
f.Fuzz(func(t *testing.T, jsonBlob []byte) {
gethResp := make(map[string]interface{})
prysmResp := &pb.ExecutionBlock{}
gethErr := json.Unmarshal(jsonBlob, &gethResp)
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
// Nothing to marshal if we have an error.
if gethErr != nil || prysmErr != nil {
return
}
assert.NoError(t, validateBlockConsistency(prysmResp, gethResp))
gethBlob, gethErr := json.Marshal(gethResp)
prysmBlob, prysmErr := json.Marshal(prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, "geth and prysm unmarshaller return inconsistent errors")
newGethResp := make(map[string]interface{})
newGethErr := json.Unmarshal(prysmBlob, &newGethResp)
assert.NoError(t, newGethErr)
newGethResp2 := make(map[string]interface{})
newGethErr = json.Unmarshal(gethBlob, &newGethResp2)
assert.NoError(t, newGethErr)
assert.DeepEqual(t, newGethResp, newGethResp2)
compareHeaders(t, jsonBlob)
})
}
func compareHeaders(t *testing.T, jsonBlob []byte) {
gethResp := &types.Header{}
prysmResp := &pb.ExecutionBlock{}
gethErr := json.Unmarshal(jsonBlob, gethResp)
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
// Nothing to marshal if we have an error.
if gethErr != nil {
return
}
gethBlob, gethErr := json.Marshal(gethResp)
prysmBlob, prysmErr := json.Marshal(prysmResp.Header)
assert.Equal(t, gethErr != nil, prysmErr != nil, "geth and prysm unmarshaller return inconsistent errors")
newGethResp := &types.Header{}
newGethErr := json.Unmarshal(prysmBlob, newGethResp)
assert.NoError(t, newGethErr)
newGethResp2 := &types.Header{}
newGethErr = json.Unmarshal(gethBlob, newGethResp2)
assert.NoError(t, newGethErr)
assert.DeepEqual(t, newGethResp, newGethResp2)
}
func validateBlockConsistency(execBlock *pb.ExecutionBlock, jsonMap map[string]interface{}) error {
blockVal := reflect.ValueOf(execBlock).Elem()
bType := reflect.TypeOf(execBlock).Elem()
fieldnum := bType.NumField()
for i := 0; i < fieldnum; i++ {
field := bType.Field(i)
fName := field.Tag.Get("json")
if field.Name == "Header" {
continue
}
if fName == "" {
return errors.Errorf("Field %s had no json tag", field.Name)
}
fVal, ok := jsonMap[fName]
if !ok {
return errors.Errorf("%s doesn't exist in json map for field %s", fName, field.Name)
}
jsonVal := fVal
bVal := blockVal.Field(i).Interface()
if field.Name == "Hash" {
jsonVal = common.HexToHash(jsonVal.(string))
}
if field.Name == "Transactions" {
continue
}
if !reflect.DeepEqual(jsonVal, bVal) {
return errors.Errorf("fields dont match, %v and %v are not equal for field %s", jsonVal, bVal, field.Name)
}
}
return nil
}

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"terminAlTotAlDiffiCultY\":\"0\"}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"baseFeePerGas\":\"0x7fffffffffffffff\",\"difficulty\":\"0x7fffffffffffffff\",\"extraData\":\"0x\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"hash\":\"0xff01ff01ff01ff01ff01ff01ff01ff01000000000000000000000g0000000000\",\"logsBloom\":\"0x6a756e6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x7fffffffffffffff\",\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"sha3Uncles\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"timestamp\":\"0x64\",\"totalDifficulty\":\"999999999999999999999999999999999999999\",\"transactions\":[{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"},{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"}],\"transactionsRoot\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{}")

View File

@@ -72,15 +72,15 @@ go_library(
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/ext:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@go_googleapis//google/api:annotations_go_proto",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@go_googleapis//google/api:annotations_go_proto",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
@@ -98,8 +98,9 @@ go_test(
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//testing/require:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_holiman_uint256//:go_default_library",
],
)

View File

@@ -41,12 +41,8 @@ func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
if err := json.Unmarshal(encodedHeader, &decoded); err != nil {
return nil, err
}
encodedTxs, err := json.Marshal(e.Transactions)
if err != nil {
return nil, err
}
decoded["hash"] = e.Hash.String()
decoded["transactions"] = string(encodedTxs)
decoded["transactions"] = e.Transactions
decoded["totalDifficulty"] = e.TotalDifficulty
return json.Marshal(decoded)
}
@@ -63,15 +59,25 @@ func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
if !ok {
return errors.New("expected `hash` field in JSON response")
}
e.Hash = common.HexToHash(blockHashStr)
decodedHash, err := hexutil.Decode(blockHashStr)
if err != nil {
return err
}
e.Hash = common.BytesToHash(decodedHash)
e.TotalDifficulty, ok = decoded["totalDifficulty"].(string)
if !ok {
return errors.New("expected `totalDifficulty` field in JSON response")
}
txsList, ok := decoded["transactions"].([]interface{})
if !ok {
rawTxList, ok := decoded["transactions"]
if !ok || rawTxList == nil {
// Exit early if there are no transactions stored in the json payload.
return nil
}
txsList, ok := rawTxList.([]interface{})
if !ok {
return errors.Errorf("expected transaction list to be of a slice interface type.")
}
// If the block contains a list of transactions, we JSON unmarshal
// them into a list of geth transaction objects.
txs := make([]*gethtypes.Transaction, len(txsList))
@@ -298,19 +304,30 @@ func (p *PayloadStatus) UnmarshalJSON(enc []byte) error {
}
type transitionConfigurationJSON struct {
TerminalTotalDifficulty string `json:"terminalTotalDifficulty"`
TerminalBlockHash hexutil.Bytes `json:"terminalBlockHash"`
TerminalBlockNumber string `json:"terminalBlockNumber"`
TerminalTotalDifficulty *hexutil.Big `json:"terminalTotalDifficulty"`
TerminalBlockHash common.Hash `json:"terminalBlockHash"`
TerminalBlockNumber hexutil.Uint64 `json:"terminalBlockNumber"`
}
// MarshalJSON --
func (t *TransitionConfiguration) MarshalJSON() ([]byte, error) {
num := new(big.Int).SetBytes(t.TerminalBlockNumber)
numHex := hexutil.EncodeBig(num)
var hexNum *hexutil.Big
if t.TerminalTotalDifficulty != "" {
ttdNum, err := hexutil.DecodeBig(t.TerminalTotalDifficulty)
if err != nil {
return nil, err
}
bHex := hexutil.Big(*ttdNum)
hexNum = &bHex
}
if len(t.TerminalBlockHash) != fieldparams.RootLength {
return nil, errors.Errorf("terminal block hash is of the wrong length: %d", len(t.TerminalBlockHash))
}
return json.Marshal(transitionConfigurationJSON{
TerminalTotalDifficulty: t.TerminalTotalDifficulty,
TerminalBlockHash: t.TerminalBlockHash,
TerminalBlockNumber: numHex,
TerminalTotalDifficulty: hexNum,
TerminalBlockHash: common.Hash(*(*[32]byte)(t.TerminalBlockHash)),
TerminalBlockNumber: hexutil.Uint64(num.Uint64()),
})
}
@@ -321,12 +338,11 @@ func (t *TransitionConfiguration) UnmarshalJSON(enc []byte) error {
return err
}
*t = TransitionConfiguration{}
num, err := hexutil.DecodeBig(dec.TerminalBlockNumber)
if err != nil {
return err
num := big.NewInt(int64(dec.TerminalBlockNumber))
if dec.TerminalTotalDifficulty != nil {
t.TerminalTotalDifficulty = dec.TerminalTotalDifficulty.String()
}
t.TerminalTotalDifficulty = dec.TerminalTotalDifficulty
t.TerminalBlockHash = dec.TerminalBlockHash
t.TerminalBlockHash = dec.TerminalBlockHash[:]
t.TerminalBlockNumber = num.Bytes()
return nil
}

File diff suppressed because one or more lines are too long