Skip to content

Commit

Permalink
blockchain: refactor verification out of process udata
Browse files Browse the repository at this point in the history
Take out verification from process udata as we were performing
verification and modification in the same function. Separating these out
make it possible to keep the utreexo state in case signature
verification fails.
  • Loading branch information
kcalvinalvin committed Oct 8, 2024
1 parent 5eae60d commit 72ddc71
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 20 deletions.
43 changes: 36 additions & 7 deletions blockchain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 "+
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
}
Expand Down
45 changes: 33 additions & 12 deletions blockchain/utreexoviewpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion blockchain/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down

0 comments on commit 72ddc71

Please sign in to comment.