-
Notifications
You must be signed in to change notification settings - Fork 9
/
dag_merkle_root.go
102 lines (95 loc) · 2.39 KB
/
dag_merkle_root.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package ethashproof
import (
"bufio"
"fmt"
"io"
"os"
"github.com/tranvictor/ethashproof/ethash"
"github.com/tranvictor/ethashproof/mtree"
)
func processDuringRead(f *os.File, startIn128Res int, fullSizeIn128Res uint32, mt *mtree.DagTree) error {
_, err := f.Seek(int64(8+startIn128Res*128), 0)
if err != nil {
return err
}
r := bufio.NewReader(f)
buf := [128]byte{}
var i uint32 = 0
for i < fullSizeIn128Res {
n, err := io.ReadFull(r, buf[:128])
if n == 0 {
if err == nil {
continue
}
if err == io.EOF {
break
}
return err
}
if n != 128 {
return fmt.Errorf("Malformed dataset")
}
mt.Insert(mtree.Word(buf), i)
if err != nil && err != io.EOF {
return err
}
i++
}
return nil
}
// 1. Generate the dataset if needed
// 2. Build merkle tree
// 3. If saveCache is true, save root merkle tree of 10 levels
// to disk
// 4. Return merkle root
func CalculateDatasetMerkleRoot(epoch uint64, saveCache bool) (mtree.Hash, error) {
blockno := epoch * 30000
fmt.Printf("Make the dag\n")
ethash.MakeDAG(blockno, ethash.DefaultDir)
fmt.Printf("Init the tree\n")
dt := mtree.NewSHA256DagTree()
fullSize := ethash.DAGSize(blockno)
fullSizeIn128Resolution := fullSize / 128
branchDepth := len(fmt.Sprintf("%b", fullSizeIn128Resolution-1))
dt.RegisterStoredLevel(uint32(branchDepth), uint32(0))
if saveCache {
indices := []uint32{}
for i := 0; i < 1<<CACHE_LEVEL; i++ {
eindex := i << (uint64(branchDepth) - CACHE_LEVEL)
if uint64(eindex) < fullSizeIn128Resolution {
indices = append(indices, uint32(eindex))
} else {
break
}
}
dt.RegisterIndex(indices...)
}
path := ethash.PathToDAG(uint64(blockno/30000), ethash.DefaultDir)
fmt.Printf("Calculating the proofs...\n")
f, err := os.Open(path)
if err != nil {
return mtree.Hash{}, err
}
defer f.Close()
processDuringRead(f, 0, uint32(fullSizeIn128Resolution), dt)
dt.Finalize()
if saveCache {
result := &DatasetMerkleTreeCache{
Epoch: epoch,
ProofLength: uint64(branchDepth),
CacheLength: CACHE_LEVEL,
RootHash: dt.RootHash(),
Proofs: [][]mtree.Hash{},
}
proofs := dt.ProofsForRegisteredIndices()
for _, proof := range proofs {
oneProof := proof[(uint64(branchDepth) - CACHE_LEVEL):len(proof)]
result.Proofs = append(result.Proofs, oneProof)
}
err = PersistCache(result)
if err != nil {
return mtree.Hash{}, err
}
}
return dt.RootHash(), nil
}