remove crosslink checking in cross tx receipt verification

fix double spent bug
pull/1526/head
chao 5 years ago
parent 39214def83
commit d624e3c46a
  1. 19
      core/blockchain.go
  2. 38
      node/node_cross_shard.go
  3. 4
      node/node_handler.go
  4. 18
      node/node_newblock.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)
}
}

@ -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 {

@ -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

@ -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
}

Loading…
Cancel
Save