diff --git a/beacon/blsync/block_sync.go b/beacon/blsync/block_sync.go index faae9e25bf..4b1b9de8e1 100755 --- a/beacon/blsync/block_sync.go +++ b/beacon/blsync/block_sync.go @@ -17,31 +17,20 @@ package blsync import ( - "fmt" - "math/big" - "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/beacon/light/request" "github.com/ethereum/go-ethereum/beacon/light/sync" "github.com/ethereum/go-ethereum/beacon/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" - ctypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" - "github.com/protolambda/zrnt/eth2/beacon/deneb" - "github.com/protolambda/zrnt/eth2/configs" - "github.com/protolambda/ztyp/tree" ) -type beaconBlockType = deneb.BeaconBlock - // beaconBlockSync implements request.Module; it fetches the beacon blocks belonging // to the validated and prefetch heads. type beaconBlockSync struct { - recentBlocks *lru.Cache[common.Hash, *beaconBlockType] + recentBlocks *lru.Cache[common.Hash, *types.BeaconBlock] locked map[common.Hash]request.ServerAndID serverHeads map[request.Server]common.Hash headTracker headTracker @@ -61,7 +50,7 @@ func newBeaconBlockSync(headTracker headTracker, chainHeadFeed *event.Feed) *bea return &beaconBlockSync{ headTracker: headTracker, chainHeadFeed: chainHeadFeed, - recentBlocks: lru.NewCache[common.Hash, *beaconBlockType](10), + recentBlocks: lru.NewCache[common.Hash, *types.BeaconBlock](10), locked: make(map[common.Hash]request.ServerAndID), serverHeads: make(map[request.Server]common.Hash), } @@ -75,7 +64,7 @@ func (s *beaconBlockSync) Process(requester request.Requester, events []request. sid, req, resp := event.RequestInfo() blockRoot := common.Hash(req.(sync.ReqBeaconBlock)) if resp != nil { - s.recentBlocks.Add(blockRoot, resp.(*beaconBlockType)) + s.recentBlocks.Add(blockRoot, resp.(*types.BeaconBlock)) } if s.locked[blockRoot] == sid { delete(s.locked, blockRoot) @@ -114,63 +103,11 @@ func (s *beaconBlockSync) tryRequestBlock(requester request.Requester, blockRoot } } -func blockHeadInfo(block *beaconBlockType) types.HeadInfo { +func blockHeadInfo(block *types.BeaconBlock) types.HeadInfo { if block == nil { return types.HeadInfo{} } - return types.HeadInfo{Slot: uint64(block.Slot), BlockRoot: beaconBlockHash(block)} -} - -// beaconBlockHash calculates the hash of a beacon block. -func beaconBlockHash(beaconBlock *beaconBlockType) common.Hash { - return common.Hash(beaconBlock.HashTreeRoot(configs.Mainnet, tree.GetHashFn())) -} - -// getExecBlock extracts the execution block from the beacon block's payload. -func getExecBlock(beaconBlock *beaconBlockType) (*ctypes.Block, error) { - payload := &beaconBlock.Body.ExecutionPayload - txs := make([]*ctypes.Transaction, len(payload.Transactions)) - for i, opaqueTx := range payload.Transactions { - var tx ctypes.Transaction - if err := tx.UnmarshalBinary(opaqueTx); err != nil { - return nil, fmt.Errorf("failed to parse tx %d: %v", i, err) - } - txs[i] = &tx - } - withdrawals := make([]*ctypes.Withdrawal, len(payload.Withdrawals)) - for i, w := range payload.Withdrawals { - withdrawals[i] = &ctypes.Withdrawal{ - Index: uint64(w.Index), - Validator: uint64(w.ValidatorIndex), - Address: common.Address(w.Address), - Amount: uint64(w.Amount), - } - } - wroot := ctypes.DeriveSha(ctypes.Withdrawals(withdrawals), trie.NewStackTrie(nil)) - execHeader := &ctypes.Header{ - ParentHash: common.Hash(payload.ParentHash), - UncleHash: ctypes.EmptyUncleHash, - Coinbase: common.Address(payload.FeeRecipient), - Root: common.Hash(payload.StateRoot), - TxHash: ctypes.DeriveSha(ctypes.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: common.Hash(payload.ReceiptsRoot), - Bloom: ctypes.Bloom(payload.LogsBloom), - Difficulty: common.Big0, - Number: new(big.Int).SetUint64(uint64(payload.BlockNumber)), - GasLimit: uint64(payload.GasLimit), - GasUsed: uint64(payload.GasUsed), - Time: uint64(payload.Timestamp), - Extra: []byte(payload.ExtraData), - MixDigest: common.Hash(payload.PrevRandao), // reused in merge - Nonce: ctypes.BlockNonce{}, // zero - BaseFee: (*uint256.Int)(&payload.BaseFeePerGas).ToBig(), - WithdrawalsHash: &wroot, - } - execBlock := ctypes.NewBlockWithHeader(execHeader).WithBody(txs, nil).WithWithdrawals(withdrawals) - if execBlockHash := execBlock.Hash(); execBlockHash != common.Hash(payload.BlockHash) { - return execBlock, fmt.Errorf("Sanity check failed, payload hash does not match (expected %x, got %x)", common.Hash(payload.BlockHash), execBlockHash) - } - return execBlock, nil + return types.HeadInfo{Slot: block.Slot(), BlockRoot: block.Hash()} } func (s *beaconBlockSync) updateEventFeed() { @@ -192,8 +129,9 @@ func (s *beaconBlockSync) updateEventFeed() { return } s.lastHeadInfo = headInfo + // new head block and finality info available; extract executable data and send event to feed - execBlock, err := getExecBlock(headBlock) + execBlock, err := headBlock.ExecutionPayload() if err != nil { log.Error("Error extracting execution block from validated beacon block", "error", err) return diff --git a/beacon/blsync/block_sync_test.go b/beacon/blsync/block_sync_test.go index 775fd8b32f..cd5c24ebf7 100644 --- a/beacon/blsync/block_sync_test.go +++ b/beacon/blsync/block_sync_test.go @@ -22,39 +22,29 @@ import ( "github.com/ethereum/go-ethereum/beacon/light/request" "github.com/ethereum/go-ethereum/beacon/light/sync" "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" "github.com/protolambda/zrnt/eth2/beacon/capella" "github.com/protolambda/zrnt/eth2/beacon/deneb" - "github.com/protolambda/zrnt/eth2/configs" - "github.com/protolambda/ztyp/tree" ) var ( testServer1 = "testServer1" testServer2 = "testServer2" - testBlock1 = &beaconBlockType{ + testBlock1 = types.NewBeaconBlock(&deneb.BeaconBlock{ Slot: 123, Body: deneb.BeaconBlockBody{ ExecutionPayload: deneb.ExecutionPayload{BlockNumber: 456}, }, - } - testBlock2 = &beaconBlockType{ + }) + testBlock2 = types.NewBeaconBlock(&deneb.BeaconBlock{ Slot: 124, Body: deneb.BeaconBlockBody{ ExecutionPayload: deneb.ExecutionPayload{BlockNumber: 457}, }, - } + }) ) -func init() { - eb1, _ := getExecBlock(testBlock1) - testBlock1.Body.ExecutionPayload.BlockHash = tree.Root(eb1.Hash()) - eb2, _ := getExecBlock(testBlock2) - testBlock2.Body.ExecutionPayload.BlockHash = tree.Root(eb2.Hash()) -} - func TestBlockSync(t *testing.T) { ht := &testHeadTracker{} eventFeed := new(event.Feed) @@ -65,10 +55,11 @@ func TestBlockSync(t *testing.T) { ts.AddServer(testServer1, 1) ts.AddServer(testServer2, 1) - expHeadBlock := func(tci int, expHead *beaconBlockType) { + expHeadBlock := func(tci int, expHead *types.BeaconBlock) { var expNumber, headNumber uint64 if expHead != nil { - expNumber = uint64(expHead.Body.ExecutionPayload.BlockNumber) + p, _ := expHead.ExecutionPayload() + expNumber = uint64(p.NumberU64()) } select { case event := <-headCh: @@ -99,7 +90,7 @@ func TestBlockSync(t *testing.T) { expHeadBlock(3, nil) // set as validated head, expect no further requests but block 1 set as head block - ht.validated.Header = blockHeader(testBlock1) + ht.validated.Header = testBlock1.Header() ts.Run(4) expHeadBlock(4, testBlock1) @@ -115,7 +106,7 @@ func TestBlockSync(t *testing.T) { ts.Run(6) // set as validated head before retrieving block; now it's assumed to be available from server 2 too - ht.validated.Header = blockHeader(testBlock2) + ht.validated.Header = testBlock2.Header() // expect req2 retry to server 2 ts.Run(7, testServer2, sync.ReqBeaconBlock(head2.BlockRoot)) // now head block should be unavailable again @@ -127,16 +118,6 @@ func TestBlockSync(t *testing.T) { expHeadBlock(5, testBlock2) } -func blockHeader(block *beaconBlockType) types.Header { - return types.Header{ - Slot: uint64(block.Slot), - ProposerIndex: uint64(block.ProposerIndex), - ParentRoot: common.Hash(block.ParentRoot), - StateRoot: common.Hash(block.StateRoot), - BodyRoot: common.Hash(block.Body.HashTreeRoot(configs.Mainnet, tree.GetHashFn())), - } -} - type testHeadTracker struct { prefetch types.HeadInfo validated types.SignedHeader