diff --git a/blockchain/chain.go b/blockchain/chain.go index 5287ca0c..8321b0c4 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1068,9 +1068,16 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return err } } else { - // Check that the block txOuts are valid by checking the utreexo proof and - // extra data and then update the accumulator. - err := b.utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + err := b.utreexoView.VerifyUData(block, b.bestChain, block.MsgBlock().UData) + if err != nil { + return fmt.Errorf("reorganizeChain fail while attaching "+ + "block %s. Error: %v", block.Hash().String(), err) + } + err = b.utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + if err != nil { + return fmt.Errorf("reorganizeChain fail while attaching "+ + "block %s. Error: %v", block.Hash().String(), err) + } if err != nil { return fmt.Errorf("reorganizeChain fail while attaching "+ "block %s. Error: %v", block.Hash().String(), err) @@ -1329,7 +1336,14 @@ func (b *BlockChain) verifyReorganizationValidity(detachNodes, attachNodes *list } else { // Check that the block txOuts are valid by checking the utreexo proof and // extra data and then update the accumulator. - err := utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + err := utreexoView.VerifyUData(block, b.bestChain, block.MsgBlock().UData) + if err != nil { + return nil, nil, nil, + fmt.Errorf("verifyReorganizationValidity fail "+ + "while attaching block %s. Error %v", + block.Hash().String(), err) + } + err = utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) if err != nil { return nil, nil, nil, fmt.Errorf("verifyReorganizationValidity fail "+ @@ -1369,6 +1383,15 @@ func (b *BlockChain) verifyReorganizationValidity(detachNodes, attachNodes *list } return nil, nil, nil, err } + if utreexoView != nil { + err = utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + if err != nil { + return nil, nil, nil, + fmt.Errorf("verifyReorganizationValidity fail "+ + "while attaching block %s. Error %v", + block.Hash().String(), err) + } + } b.index.SetStatusFlags(n, statusValid) } @@ -1445,16 +1468,22 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla if b.utreexoView != nil { if fastAdd { // Check that the block txOuts are valid by checking the utreexo proof and - // extra data and then update the accumulator. - err := b.utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + // the leaf data. + err := b.utreexoView.VerifyUData(block, b.bestChain, block.MsgBlock().UData) if err != nil { return false, fmt.Errorf("connectBestChain fail on block %s. "+ "Error: %v", block.Hash().String(), err) } } + // Update the accumulator. + err := b.utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + if err != nil { + return false, fmt.Errorf("connectBestChain fail on block %s. "+ + "Error: %v", block.Hash().String(), err) + } view := NewUtxoViewpoint() view.SetBestHash(parentHash) - err := view.BlockToUtxoView(block) + err = view.BlockToUtxoView(block) if err != nil { return false, err } diff --git a/blockchain/utreexoviewpoint.go b/blockchain/utreexoviewpoint.go index 9c3596aa..1b4bdfb2 100644 --- a/blockchain/utreexoviewpoint.go +++ b/blockchain/utreexoviewpoint.go @@ -46,8 +46,7 @@ func (uview *UtreexoViewpoint) CopyWithRoots() *UtreexoViewpoint { return newUview } -// ProcessUData checks that the accumulator proof and the utxo data included in the UData -// passes consensus and then it updates the underlying accumulator. +// ProcessUData updates the underlying accumulator. It does NOT check if the verification passes. func (uview *UtreexoViewpoint) ProcessUData(block *btcutil.Block, bestChain *chainView, ud *wire.UData) error { @@ -57,6 +56,32 @@ func (uview *UtreexoViewpoint) ProcessUData(block *btcutil.Block, if err != nil { return err } + + dels, err := ExtractAccumulatorDels(block, bestChain, ud.RememberIdx) + if err != nil { + return err + } + + // Update the underlying accumulator. + updateData, err := uview.Modify(ud, adds, dels) + if err != nil { + return fmt.Errorf("ProcessUData fail. Error: %v", err) + } + + // Add the utreexo data to the block. + block.SetUtreexoUpdateData(updateData) + block.SetUtreexoAdds(adds) + + return nil +} + +// VerifyUData checks the accumulator proof to ensure that the leaf preimages exist in the +// accumulator. +func (uview *UtreexoViewpoint) VerifyUData(block *btcutil.Block, + bestChain *chainView, ud *wire.UData) error { + + // Extracts the block into additions and deletions that will be processed. + // Adds correspond to newly created UTXOs and dels correspond to STXOs. dels, err := ExtractAccumulatorDels(block, bestChain, ud.RememberIdx) if err != nil { return err @@ -84,17 +109,13 @@ func (uview *UtreexoViewpoint) ProcessUData(block *btcutil.Block, } } - // Update the underlying accumulator. - updateData, err := uview.Modify(ud, adds, dels) - if err != nil { - return fmt.Errorf("ProcessUData fail. Error: %v", err) + // TODO we should be verifying here but aren't as the accumulator.Verify + // function expects a complete proof. + if uview.proofInterval != 1 { + return nil } - // Add the utreexo data to the block. - block.SetUtreexoUpdateData(updateData) - block.SetUtreexoAdds(adds) - - return nil + return uview.accumulator.Verify(dels, ud.AccProof, false) } // AddProof first checks that the utreexo proofs are valid. If it is valid, @@ -124,7 +145,7 @@ func (uview *UtreexoViewpoint) Modify(ud *wire.UData, var err error var updateData utreexo.UpdateData if uview.proofInterval == 1 { - err = uview.accumulator.Verify(dels, ud.AccProof, true) + err = uview.accumulator.Ingest(dels, ud.AccProof) if err != nil { return nil, err } diff --git a/blockchain/validate.go b/blockchain/validate.go index d8e858a3..41afb81f 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -1075,7 +1075,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, // If utreexo accumulators are enabled, then check that the accumulator // proof is ok. Then convert the msgBlock.UData into UtxoViewpoint. if utreexoView != nil { - err := utreexoView.ProcessUData(block, b.bestChain, block.MsgBlock().UData) + err := utreexoView.VerifyUData(block, b.bestChain, block.MsgBlock().UData) if err != nil { return fmt.Errorf("checkConnectBlock fail. error: %v", err) }