Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blockchain, wire: utreexoviewpoint partial proof support #94

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions blockchain/utreexoviewpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,39 @@ func (b *BlockChain) VerifyUData(ud *wire.UData, txIns []*wire.TxIn, remember bo
return nil
}

// GenerateUDataPartial generates a utreexo data based on the current state of the utreexo viewpoint.
// It leaves out the full proof hashes and only fetches the requested positions.
//
// This function is safe for concurrent access.
func (b *BlockChain) GenerateUDataPartial(dels []wire.LeafData, positions []uint64) (*wire.UData, error) {
b.chainLock.RLock()
defer b.chainLock.RUnlock()

ud := new(wire.UData)
ud.LeafDatas = dels

// Get the positions of the targets of delHashes.
delHashes, err := wire.HashesFromLeafDatas(ud.LeafDatas)
if err != nil {
return nil, err
}
targets := b.getLeafHashPositions(delHashes)

// Fetch the requested hashes.
hashes := make([]utreexo.Hash, len(positions))
for i, pos := range positions {
hashes[i] = b.utreexoView.accumulator.GetHash(pos)
}

// Put the proof together and return.
ud.AccProof = utreexo.Proof{
Targets: targets,
Proof: hashes,
}

return ud, nil
}

// GenerateUData generates a utreexo data based on the current state of the utreexo viewpoint.
//
// This function is safe for concurrent access.
Expand Down Expand Up @@ -979,6 +1012,54 @@ func (b *BlockChain) PruneFromAccumulator(leaves []wire.LeafData) error {
return nil
}

// packedPositions fetches and returns the positions of the leafHashes as chainhash.Hash.
//
// This function is NOT safe for concurrent access.
func (b *BlockChain) packedPositions(leafHashes []utreexo.Hash) []chainhash.Hash {
positions := b.utreexoView.accumulator.GetLeafHashPositions(leafHashes)
return chainhash.Uint64sToPackedHashes(positions)
}

// PackedPositions fetches and returns the positions of the leafHashes as chainhash.Hash.
//
// This function is safe for concurrent access.
func (b *BlockChain) PackedPositions(leafHashes []utreexo.Hash) []chainhash.Hash {
b.chainLock.RLock()
defer b.chainLock.RUnlock()

return b.packedPositions(leafHashes)
}

// getLeafHashPositions returns the positions of the passed in leaf hashes.
//
// This function is NOT safe for concurrent access.
func (b *BlockChain) getLeafHashPositions(leafHashes []utreexo.Hash) []uint64 {
return b.utreexoView.accumulator.GetLeafHashPositions(leafHashes)
}

// GetLeafHashPositions returns the positions of the passed in leaf hashes.
//
// This function is safe for concurrent access.
func (b *BlockChain) GetLeafHashPositions(leafHashes []utreexo.Hash) []uint64 {
b.chainLock.RLock()
defer b.chainLock.RUnlock()

return b.getLeafHashPositions(leafHashes)
}

// GetNeededPositions returns the positions of the needed hashes in order to verify the
// positions passed in.
//
// This function is safe for concurrent access.
func (b *BlockChain) GetNeededPositions(packedPositions []chainhash.Hash) []chainhash.Hash {
b.chainLock.RLock()
defer b.chainLock.RUnlock()

positions := chainhash.PackedHashesToUint64(packedPositions)
missing := b.utreexoView.accumulator.GetMissingPositions(positions)
return chainhash.Uint64sToPackedHashes(missing)
}

// ChainTipProof represents all the information that is needed to prove that a
// utxo exists in the chain tip with utreexo accumulator proof.
type ChainTipProof struct {
Expand Down
37 changes: 24 additions & 13 deletions wire/udata.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,20 +428,13 @@ func DeserializeRemembers(r io.Reader) ([]uint32, error) {
return remembers, nil
}

// GenerateUData creates a block proof, calling forest.ProveBatch with the leaf indexes
// to get a batched inclusion proof from the accumulator. It then adds on the leaf data,
// to create a block proof which both proves inclusion and gives all utxo data
// needed for transaction verification.
func GenerateUData(txIns []LeafData, pollard utreexo.Utreexo) (
*UData, error) {

ud := new(UData)
ud.LeafDatas = txIns

// HashesFromLeafDatas hashes the passed in leaf datas. Returns an error if a
// leaf data is compact as you can't generate the correct hash.
func HashesFromLeafDatas(leafDatas []LeafData) ([]utreexo.Hash, error) {
// make slice of hashes from leafdata
var unconfirmedCount int
delHashes := make([]utreexo.Hash, 0, len(ud.LeafDatas))
for _, ld := range ud.LeafDatas {
delHashes := make([]utreexo.Hash, 0, len(leafDatas))
for _, ld := range leafDatas {
if ld.IsUnconfirmed() {
unconfirmedCount++
continue
Expand All @@ -457,8 +450,26 @@ func GenerateUData(txIns []LeafData, pollard utreexo.Utreexo) (
delHashes = append(delHashes, ld.LeafHash())
}

return delHashes, nil
}

// GenerateUData creates a block proof, calling forest.ProveBatch with the leaf indexes
// to get a batched inclusion proof from the accumulator. It then adds on the leaf data,
// to create a block proof which both proves inclusion and gives all utxo data
// needed for transaction verification.
func GenerateUData(txIns []LeafData, pollard utreexo.Utreexo) (
*UData, error) {

ud := new(UData)
ud.LeafDatas = txIns

// Make a slice of hashes from the leafdatas.
delHashes, err := HashesFromLeafDatas(ud.LeafDatas)
if err != nil {
return nil, err
}

// Generate the utreexo accumulator proof for all the inputs.
var err error
ud.AccProof, err = pollard.Prove(delHashes)
if err != nil {
// Find out which exact one is causing the error.
Expand Down
Loading