diff --git a/statediff/indexer/database/dump/indexer.go b/statediff/indexer/database/dump/indexer.go index 2cc7e2e0a..723a13350 100644 --- a/statediff/indexer/database/dump/indexer.go +++ b/statediff/indexer/database/dump/indexer.go @@ -17,11 +17,15 @@ package dump import ( + "bytes" "fmt" "io" "math/big" "time" + blockstore "github.com/ipfs/go-ipfs-blockstore" + dshelp "github.com/ipfs/go-ipfs-ds-help" + ipld2 "github.com/ethereum/go-ethereum/statediff/indexer/ipld" "github.com/ipfs/go-cid" @@ -79,7 +83,7 @@ func (sdi *StateDiffIndexer) PushBlock(block *types.Block, receipts types.Receip } // Generate the block iplds - headerNode, uncleNodes, txNodes, txTrieNodes, rctNodes, rctTrieNodes, logTrieNodes, logLeafNodeCIDs, rctLeafNodeCIDs, err := ipld2.FromBlockAndReceipts(block, receipts) + headerNode, txNodes, txTrieNodes, rctNodes, rctTrieNodes, logTrieNodes, logLeafNodeCIDs, rctLeafNodeCIDs, err := ipld2.FromBlockAndReceipts(block, receipts) if err != nil { return nil, fmt.Errorf("error creating IPLD nodes from block and receipts: %v", err) } @@ -146,7 +150,7 @@ func (sdi *StateDiffIndexer) PushBlock(block *types.Block, receipts types.Receip traceMsg += fmt.Sprintf("header processing time: %s\r\n", tDiff.String()) t = time.Now() // Publish and index uncles - err = sdi.processUncles(blockTx, headerID, block.Number(), uncleNodes) + err = sdi.processUncles(blockTx, headerID, block.Number(), block.UncleHash(), block.Uncles()) if err != nil { return nil, err } @@ -197,7 +201,7 @@ func (sdi *StateDiffIndexer) processHeader(tx *BatchTx, header *types.Header, he StateRoot: header.Root.String(), RctRoot: header.ReceiptHash.String(), TxRoot: header.TxHash.String(), - UncleRoot: header.UncleHash.String(), + UnclesHash: header.UncleHash.String(), Timestamp: header.Time, Coinbase: header.Coinbase.String(), } @@ -206,25 +210,39 @@ func (sdi *StateDiffIndexer) processHeader(tx *BatchTx, header *types.Header, he } // processUncles publishes and indexes uncle IPLDs in Postgres -func (sdi *StateDiffIndexer) processUncles(tx *BatchTx, headerID string, blockNumber *big.Int, uncleNodes []*ipld2.EthHeader) error { +func (sdi *StateDiffIndexer) processUncles(tx *BatchTx, headerID string, blockNumber *big.Int, unclesHash common.Hash, uncles []*types.Header) error { // publish and index uncles - for _, uncleNode := range uncleNodes { - tx.cacheIPLD(uncleNode) + uncleEncoding, err := rlp.EncodeToBytes(uncles) + if err != nil { + return err + } + preparedHash := crypto.Keccak256Hash(uncleEncoding) + if !bytes.Equal(preparedHash.Bytes(), unclesHash.Bytes()) { + return fmt.Errorf("derived uncles hash (%s) does not match the hash in the header (%s)", preparedHash.Hex(), unclesHash.Hex()) + } + unclesCID, err := ipld2.RawdataToCid(ipld2.MEthHeaderList, uncleEncoding, multihash.KECCAK_256) + if err != nil { + return err + } + prefixedKey := blockstore.BlockPrefix.String() + dshelp.MultihashToDsKey(unclesCID.Hash()).String() + tx.cacheDirect(prefixedKey, uncleEncoding) + for i, uncle := range uncles { var uncleReward *big.Int // in PoA networks uncle reward is 0 if sdi.chainConfig.Clique != nil { uncleReward = big.NewInt(0) } else { - uncleReward = shared.CalcUncleMinerReward(blockNumber.Uint64(), uncleNode.Number.Uint64()) + uncleReward = shared.CalcUncleMinerReward(blockNumber.Uint64(), uncle.Number.Uint64()) } uncle := models.UncleModel{ BlockNumber: blockNumber.String(), HeaderID: headerID, - CID: uncleNode.Cid().String(), - MhKey: shared.MultihashKeyFromCID(uncleNode.Cid()), - ParentHash: uncleNode.ParentHash.String(), - BlockHash: uncleNode.Hash().String(), + CID: unclesCID.String(), + MhKey: shared.MultihashKeyFromCID(unclesCID), + ParentHash: uncle.ParentHash.String(), + BlockHash: uncle.Hash().String(), Reward: uncleReward.String(), + Index: int64(i), } if _, err := fmt.Fprintf(sdi.dump, "%+v\r\n", uncle); err != nil { return err diff --git a/statediff/indexer/ipld/eth_parser.go b/statediff/indexer/ipld/eth_parser.go index 03061f828..d3847d648 100644 --- a/statediff/indexer/ipld/eth_parser.go +++ b/statediff/indexer/ipld/eth_parser.go @@ -125,35 +125,25 @@ func FromBlockJSON(r io.Reader) (*EthHeader, []*EthTx, []*EthTxTrie, error) { // FromBlockAndReceipts takes a block and processes it // to return it a set of IPLD nodes for further processing. -func FromBlockAndReceipts(block *types.Block, receipts []*types.Receipt) (*EthHeader, []*EthHeader, []*EthTx, []*EthTxTrie, []*EthReceipt, []*EthRctTrie, [][]node.Node, [][]cid.Cid, []cid.Cid, error) { +func FromBlockAndReceipts(block *types.Block, receipts []*types.Receipt) (*EthHeader, []*EthTx, []*EthTxTrie, []*EthReceipt, []*EthRctTrie, [][]node.Node, [][]cid.Cid, []cid.Cid, error) { // Process the header headerNode, err := NewEthHeader(block.Header()) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, err - } - - // Process the uncles - uncleNodes := make([]*EthHeader, len(block.Uncles())) - for i, uncle := range block.Uncles() { - uncleNode, err := NewEthHeader(uncle) - if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, err - } - uncleNodes[i] = uncleNode + return nil, nil, nil, nil, nil, nil, nil, nil, err } // Process the txs txNodes, txTrieNodes, err := processTransactions(block.Transactions(), block.Header().TxHash[:]) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, err } // Process the receipts and logs rctNodes, tctTrieNodes, logTrieAndLogNodes, logLeafNodeCIDs, rctLeafNodeCIDs, err := processReceiptsAndLogs(receipts, block.Header().ReceiptHash[:]) - return headerNode, uncleNodes, txNodes, txTrieNodes, rctNodes, tctTrieNodes, logTrieAndLogNodes, logLeafNodeCIDs, rctLeafNodeCIDs, err + return headerNode, txNodes, txTrieNodes, rctNodes, tctTrieNodes, logTrieAndLogNodes, logLeafNodeCIDs, rctLeafNodeCIDs, err } // processTransactions will take the found transactions in a parsed block body