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

Match known hashes in pollard #3

Open
wants to merge 1 commit into
base: matchknown
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions utreexo/pollard.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func (p *Pollard) Modify(adds []LeafTXO, dels []uint64) error {
}

func (p *Pollard) Stats() string {
s := fmt.Sprintf("pol nl %d tops %d phe %d he %d re %d ow %d \n",
p.numLeaves, len(p.tops), p.proofHashesEver, p.hashesEver, p.rememberEver, p.overWire)
s := fmt.Sprintf("pol nl %d tops %d prhe %d phe %d he %d re %d ow %d \n",
p.numLeaves, len(p.tops), p.proofResolveHashesEver, p.proofHashesEver, p.hashesEver, p.rememberEver, p.overWire)
return s
}

Expand Down Expand Up @@ -374,7 +374,7 @@ func (p *Pollard) descendToPos(pos uint64) ([]*polNode, []*polNode, error) {
n = n.niece[lr]

if n == nil && h != 0 {
return nil, nil, fmt.Errorf(
return proofs, sibs, fmt.Errorf(
"descend pos %d nil neice at height %d", pos, h)
}

Expand Down
2 changes: 1 addition & 1 deletion utreexo/pollard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func pollardRandomRemember(blocks int32) error {
sn.durationMask = 0x0f
sn.lookahead = 4
for b := int32(0); b < blocks; b++ {
adds, delHashes := sn.NextBlock(rand.Uint32() & 0x03)
adds, delHashes := sn.NextBlock(rand.Uint32() & 0x77)

fmt.Printf("\t\t\tblock %d del %d add %d - %s\n",
sn.blockHeight, len(delHashes), len(adds), p.Stats())
Expand Down
111 changes: 72 additions & 39 deletions utreexo/pollardproof.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,11 @@ func (p *Pollard) VerifyBlockProof(
return false, proofmap
}

knownHashes, err := p.matchKnownData(proofmap, bp)
proofmap, err = p.matchKnownData(proofmap, bp)
if err != nil {
fmt.Printf("VerifyBlockProof matchKnownData ERROR %s\n", err.Error())
return false, proofmap
}
for k, v := range knownHashes {
proofmap[k] = v
}

// fmt.Printf("Reconstruct complete\n")
topposs, topheights := getTopsReverse(p.numLeaves, height)
Expand Down Expand Up @@ -206,10 +203,10 @@ func (p *Pollard) VerifyBlockProof(
func (p *Pollard) matchKnownData(
rec map[uint64]Hash,
bp BlockProof) (map[uint64]Hash, error) {
proofmap := map[uint64]Hash{}
proofmap := rec

height := p.height()
fmt.Printf("Targets: %v\n", bp.Targets)
/*fmt.Printf("Targets: %v\n", bp.Targets)
fmt.Printf("Num leaves: %d\n", p.numLeaves)
for pos, hash := range rec {
fmt.Printf("rec[%d] = %x\n", pos, hash[:4])
Expand All @@ -222,65 +219,101 @@ func (p *Pollard) matchKnownData(
fmt.Printf("%x ", th[:4])
}
fmt.Printf("\n")

*/
var left, right uint64

for _, t := range bp.Targets {

fmt.Printf("Processing %d\n", t)
//fmt.Printf("Processing %d\n", t)
// Fetch whatever is in the pollard on the path to
// this leaf
nodes, _, _ := p.descendToPos(t)

for i, n := range nodes {
if n != nil {
fmt.Printf("nodes[%d] = %x\n", i, n.data[:4])
} else {
fmt.Printf("nodes[%d] = nil\n", i)
_, sibs, err := p.descendToPos(t)
/*
if err != nil {
fmt.Printf("Error descendToPos: %s\n", err)
}
}

for i, s := range sibs {
if s != nil {
fmt.Printf("sibs[%d] = %x\n", i, s.data[:4])
} else {
fmt.Printf("sibs[%d] = nil\n", i)
}
}*/

subH := detectSubTreeHeight(t, p.numLeaves, height)
fmt.Printf("Subtree height for [%d] is [%d]\n", left, subH)
//fmt.Printf("Subtree height for [%d] is [%d]\n", left, subH)
pos := up1(t, height)
fmt.Printf("We are at position [%d]\n", pos)
//fmt.Printf("We are at position [%d]\n", pos)
right = t | 1
left = right ^ 1
leftHash, rightHash := rec[left], rec[right]

found := false
for h := uint8(1); h < subH; h++ { // < or <=? I think <
if !found || nodes[h] == nil {
fmt.Printf("pos %d: Parent(%x, %x) -> ", pos, leftHash[:4], rightHash[:4])
hash := Parent(leftHash, rightHash)
fmt.Printf("%x\n", hash[:4])
p.hashesEver++
p.proofHashesEver++
if nodes[h] != nil {
if nodes[h].data == hash {
fmt.Printf("Found matching hash in nodes[%d]\n", h)
found = true
for h := uint8(1); h <= subH; h++ { // < or <=? I think <
_, ok := proofmap[pos]
if !ok {
if !found || sibs[h] == nil {
//fmt.Printf("pos %d: Parent(%x, %x) -> ", pos, leftHash[:4], rightHash[:4])
hash := Parent(leftHash, rightHash)
//fmt.Printf("%x\n", hash[:4])
p.hashesEver++
p.proofHashesEver++
if sibs[h] != nil {
if sibs[h].data == hash {
//fmt.Printf("Found matching hash in nodes[%d]\n", h)
found = true
}
}
proofmap[pos] = hash
} else {
//fmt.Printf("Using cached data after intersecting with pollard for %d\n", pos)
proofmap[pos] = sibs[h].data
}
proofmap[pos] = hash
} else {
fmt.Printf("Using cached data after intersecting with pollard for %d\n", pos)
proofmap[pos] = nodes[h].data
}
if h == subH {
break
}

if !found {
if !found || sibs[h+1] == nil {
hashes := map[uint64]Hash{}
ok := false
if pos&1 == 0 {
fmt.Printf("Left pos (calculated): [%d] - Right pos (from proof): [%d]\n", pos, pos^1)
//fmt.Printf("Left pos (calculated): [%d] - Right pos (from proof): [%d]\n", pos, pos^1)
rightHash, ok = proofmap[pos^1]
if !ok {
rightHash, hashes, err = ResolveNode(proofmap, pos^1, height)
for p, h := range hashes {
proofmap[p] = h
}
if err != nil {
return nil, err
}
p.hashesEver += uint64(len(hashes))
p.proofHashesEver += uint64(len(hashes))
p.proofResolveHashesEver += uint64(len(hashes))
}
leftHash = proofmap[pos]
rightHash = rec[pos^1]
} else {
fmt.Printf("Left pos (from proof): [%d] - Right pos (calculated): [%d]\n", pos^1, pos)
//fmt.Printf("Left pos (from proof): [%d] - Right pos (calculated): [%d]\n", pos^1, pos)
leftHash, ok = proofmap[pos^1]
if !ok {
leftHash, hashes, err = ResolveNode(proofmap, pos^1, height)
for p, h := range hashes {
proofmap[p] = h
}
if err != nil {
return nil, err
}
p.hashesEver += uint64(len(hashes))
p.proofHashesEver += uint64(len(hashes))
p.proofResolveHashesEver += uint64(len(hashes))
}
rightHash = proofmap[pos]
leftHash = rec[pos^1]
}
}
pos = up1(pos, height)
fmt.Printf("We are at [%d]\n", pos)
//fmt.Printf("We are at [%d]\n", pos)
}
}

Expand Down
2 changes: 1 addition & 1 deletion utreexo/pollarutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Pollard struct {
// BUT THEY'RE WEIRD! The left / right children are actual children,
// not neices as they are in every lower level.

proofHashesEver, hashesEver, rememberEver, overWire uint64
proofResolveHashesEver, proofHashesEver, hashesEver, rememberEver, overWire uint64

// Lookahead int32 // remember leafs below this TTL
// Minleaves uint64 // remember everything below this leaf count
Expand Down
42 changes: 42 additions & 0 deletions utreexo/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,45 @@ func U64tB(i uint64) []byte {
binary.Write(&buf, binary.BigEndian, i)
return buf.Bytes()
}

// ResolveNode will try to get a node at a given pos from a known set of nodes/leaves
// if not present, it will descend to calculate it from known data further down.
// should optimize this to return all the hashes it calculated so the caller can add it
// to its cache/knownData
func ResolveNode(knownData map[uint64]Hash, pos uint64, forestHeight uint8) (Hash, map[uint64]Hash, error) {
calculatedHashes := map[uint64]Hash{}
// First check if the node is in here
n, ok := knownData[pos]
if ok {
return n, calculatedHashes, nil
}

// If not, check if we're at a leaf. If so, we can't fix this.
if detectHeight(pos, forestHeight) == 0 {
return Hash{}, calculatedHashes, fmt.Errorf("Could not find leaf %d", pos)
}

// Otherwise, find if the children are known and hash them
leftPos := child(pos, forestHeight)
rightPos := leftPos ^ 1

left, leftHashes, err := ResolveNode(knownData, leftPos, forestHeight)
for pos, hash := range leftHashes {
calculatedHashes[pos] = hash
}

if err != nil {
return Hash{}, calculatedHashes, err
}

right, rightHashes, err := ResolveNode(knownData, rightPos, forestHeight)
for pos, hash := range rightHashes {
calculatedHashes[pos] = hash
}

if err != nil {
return Hash{}, calculatedHashes, err
}
calculatedHashes[pos] = Parent(left, right)
return calculatedHashes[pos], calculatedHashes, nil
}