mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Fuzz Remaining Engine Objects (#11049)
* add new fuzz tests * add fixes * remove test * add more checks * remove comment
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"terminAlTotAlDiffiCultY\":\"0\"}")
|
||||
@@ -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\"}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{}")
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user