diff --git a/core/blockchain.go b/core/blockchain.go index 4533fe625..e45987b97 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2166,39 +2166,38 @@ func (bc *BlockChain) NextCXReceiptsCheckpoint(currentNum uint64, shardID uint32 // the new checkpoint will not exceed currentNum+1 for num := lastCheckpoint; num <= currentNum+1; num++ { + newCheckpoint = num by, _ := rawdb.ReadCXReceiptsProofSpent(bc.db, shardID, num) if by == rawdb.NAByte { // TODO chao: check if there is IncompingReceiptsHash in crosslink header // if the rootHash is non-empty, it means incomingReceipts are not delivered // otherwise, it means there is no cross-shard transactions for this block - newCheckpoint = num continue } if by == rawdb.SpentByte { - newCheckpoint = num continue } // the first unspent blockHash found, break the loop - newCheckpoint = num break } return newCheckpoint } -// cleanCXReceiptsCheckpoints will update the checkpoint and clean spent receipts upto checkpoint -func (bc *BlockChain) cleanCXReceiptsCheckpoints(shardID uint32, currentNum uint64) { +// updateCXReceiptsCheckpoints will update the checkpoint and clean spent receipts upto checkpoint +func (bc *BlockChain) updateCXReceiptsCheckpoints(shardID uint32, currentNum uint64) { lastCheckpoint, err := rawdb.ReadCXReceiptsProofUnspentCheckpoint(bc.db, shardID) if err != nil { - utils.Logger().Warn().Msg("[cleanCXReceiptsCheckpoints] Cannot get lastCheckpoint") + utils.Logger().Warn().Msg("[updateCXReceiptsCheckpoints] Cannot get lastCheckpoint") } newCheckpoint := bc.NextCXReceiptsCheckpoint(currentNum, shardID) if lastCheckpoint == newCheckpoint { return } - utils.Logger().Debug().Uint64("lastCheckpoint", lastCheckpoint).Uint64("newCheckpont", newCheckpoint).Msg("[CleanCXReceiptsCheckpoints]") + utils.Logger().Debug().Uint64("lastCheckpoint", lastCheckpoint).Uint64("newCheckpont", newCheckpoint).Msg("[updateCXReceiptsCheckpoints]") for num := lastCheckpoint; num < newCheckpoint; num++ { rawdb.DeleteCXReceiptsProofSpent(bc.db, shardID, num) } + rawdb.WriteCXReceiptsProofUnspentCheckpoint(bc.db, shardID, newCheckpoint) } // WriteCXReceiptsProofSpent mark the CXReceiptsProof list with given unspent status @@ -2220,8 +2219,8 @@ func (bc *BlockChain) IsSpent(cxp *types.CXReceiptsProof) bool { return false } -// CleanCXReceiptsCheckpointsByBlock cleans checkpoints based on incomingReceipts of the given block -func (bc *BlockChain) CleanCXReceiptsCheckpointsByBlock(block *types.Block) { +// UpdateCXReceiptsCheckpointsByBlock cleans checkpoints and update latest checkpoint based on incomingReceipts of the given block +func (bc *BlockChain) UpdateCXReceiptsCheckpointsByBlock(block *types.Block) { m := make(map[uint32]uint64) for _, cxp := range block.IncomingReceipts() { shardID := cxp.MerkleProof.ShardID @@ -2235,6 +2234,6 @@ func (bc *BlockChain) CleanCXReceiptsCheckpointsByBlock(block *types.Block) { for k, v := range m { utils.Logger().Debug().Uint32("shardID", k).Uint64("blockNum", v).Msg("[CleanCXReceiptsCheckpoints] Cleaning CXReceiptsProof upto") - bc.cleanCXReceiptsCheckpoints(k, v) + bc.updateCXReceiptsCheckpoints(k, v) } } diff --git a/node/node_cross_shard.go b/node/node_cross_shard.go index ee7582b89..e677eeaf8 100644 --- a/node/node_cross_shard.go +++ b/node/node_cross_shard.go @@ -99,21 +99,19 @@ func (node *Node) verifyIncomingReceipts(block *types.Block) error { m := make(map[common.Hash]bool) cxps := block.IncomingReceipts() for _, cxp := range cxps { - if err := core.IsValidCXReceiptsProof(cxp); err != nil { - return ctxerror.New("[verifyIncomingReceipts] verification failed").WithCause(err) - } + // double spent if node.Blockchain().IsSpent(cxp) { return ctxerror.New("[verifyIncomingReceipts] Double Spent!") } hash := cxp.MerkleProof.BlockHash - // ignore duplicated receipts + // duplicated receipts if _, ok := m[hash]; ok { return ctxerror.New("[verifyIncomingReceipts] Double Spent!") } m[hash] = true - if err := node.compareCrosslinkWithReceipts(cxp); err != nil { - return err + if err := core.IsValidCXReceiptsProof(cxp); err != nil { + return ctxerror.New("[verifyIncomingReceipts] verification failed").WithCause(err) } } @@ -128,34 +126,6 @@ func (node *Node) verifyIncomingReceipts(block *types.Block) error { return nil } -func (node *Node) compareCrosslinkWithReceipts(cxp *types.CXReceiptsProof) error { - var hash, outgoingReceiptHash common.Hash - - shardID := cxp.MerkleProof.ShardID - blockNum := cxp.MerkleProof.BlockNum.Uint64() - beaconChain := node.Beaconchain() - if shardID == 0 { - block := beaconChain.GetBlockByNumber(blockNum) - if block == nil { - return ctxerror.New("[compareCrosslinkWithReceipts] Cannot get beaconchain header", "blockNum", blockNum, "shardID", shardID) - } - hash = block.Hash() - outgoingReceiptHash = block.OutgoingReceiptHash() - } else { - crossLink, err := beaconChain.ReadCrossLink(shardID, blockNum, false) - if err != nil { - return ctxerror.New("[compareCrosslinkWithReceipts] Cannot get crosslink", "blockNum", blockNum, "shardID", shardID).WithCause(err) - } - hash = crossLink.ChainHeader.Hash() - outgoingReceiptHash = crossLink.ChainHeader.OutgoingReceiptHash() - } - // verify the source block hash is from a finalized block - if hash == cxp.MerkleProof.BlockHash && outgoingReceiptHash == cxp.MerkleProof.CXReceiptHash { - return nil - } - return ErrCrosslinkVerificationFail -} - // VerifyCrosslinkHeader verifies the header is valid against the prevHeader. func (node *Node) VerifyCrosslinkHeader(prevHeader, header *block.Header) error { diff --git a/node/node_handler.go b/node/node_handler.go index 6158d2f18..aba9a110d 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -598,8 +598,8 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block, commitSigAndBit Msg("BINGO !!! Reached Consensus") } - // TODO chao: Write New checkpoint after clean - node.Blockchain().CleanCXReceiptsCheckpointsByBlock(newBlock) + // TODO chao: uncomment this after beacon syncing is stable + // node.Blockchain().UpdateCXReceiptsCheckpointsByBlock(newBlock) if node.NodeConfig.GetNetworkType() != nodeconfig.Mainnet { // Update contract deployer's nonce so default contract like faucet can issue transaction with current nonce diff --git a/node/node_newblock.go b/node/node_newblock.go index 56a9afb28..1b3ece6f2 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -195,7 +195,6 @@ func (node *Node) proposeLocalShardState(block *types.Block) { func (node *Node) proposeReceiptsProof() []*types.CXReceiptsProof { validReceiptsList := []*types.CXReceiptsProof{} - pendingReceiptsList := []*types.CXReceiptsProof{} node.pendingCXMutex.Lock() sort.Slice(node.pendingCXReceipts, func(i, j int) bool { @@ -218,18 +217,13 @@ func (node *Node) proposeReceiptsProof() []*types.CXReceiptsProof { m[hash] = true } - if err := node.compareCrosslinkWithReceipts(cxp); err != nil { - utils.Logger().Debug().Err(err).Interface("cxp", cxp).Msg("[proposeReceiptsProof] CrossLink Verify Fail") - if err != ErrCrosslinkVerificationFail { - pendingReceiptsList = append(pendingReceiptsList, cxp) - } - } else { - utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipts Added") - validReceiptsList = append(validReceiptsList, cxp) - } + utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipts Added") + validReceiptsList = append(validReceiptsList, cxp) } - node.pendingCXReceipts = pendingReceiptsList + + node.pendingCXReceipts = nil node.pendingCXMutex.Unlock() - utils.Logger().Debug().Msgf("[proposeReceiptsProof] number of validReceipts %d, pendingReceipts %d", len(validReceiptsList), len(pendingReceiptsList)) + + utils.Logger().Debug().Msgf("[proposeReceiptsProof] number of validReceipts %d", len(validReceiptsList)) return validReceiptsList }