/
buildroot.go
112 lines (80 loc) · 2.25 KB
/
buildroot.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
103
104
105
106
107
108
109
110
111
112
package buildroot
import (
"github.com/KalyCoinProject/kalychain/helper/keccak"
itrie "github.com/KalyCoinProject/kalychain/state/immutable-trie"
"github.com/KalyCoinProject/kalychain/types"
"github.com/umbracle/fastrlp"
)
var arenaPool fastrlp.ArenaPool
// CalculateReceiptsRoot calculates the root of a list of receipts
func CalculateReceiptsRoot(receipts []*types.Receipt) types.Hash {
ar := arenaPool.Get()
res := calculateRootWithRlp(len(receipts), func(i int) *fastrlp.Value {
ar.Reset()
return receipts[i].MarshalRLPWith(ar)
})
arenaPool.Put(ar)
return res
}
// CalculateTransactionsRoot calculates the root of a list of transactions
func CalculateTransactionsRoot(transactions []*types.Transaction) types.Hash {
ar := arenaPool.Get()
res := calculateRootWithRlp(len(transactions), func(i int) *fastrlp.Value {
ar.Reset()
return transactions[i].MarshalRLPWith(ar)
})
arenaPool.Put(ar)
return res
}
// CalculateUncleRoot calculates the root of a list of uncles
func CalculateUncleRoot(uncles []*types.Header) types.Hash {
if len(uncles) == 0 {
return types.EmptyUncleHash
}
a := arenaPool.Get()
v := a.NewArray()
for _, i := range uncles {
v.Set(i.MarshalRLPWith(a))
}
root := keccak.Keccak256Rlp(nil, v)
arenaPool.Put(a)
return types.BytesToHash(root)
}
func calculateRootWithRlp(num int, h func(indx int) *fastrlp.Value) types.Hash {
hF := func(indx int) []byte {
return h(indx).MarshalTo(nil)
}
return CalculateRoot(num, hF)
}
// CalculateRoot calculates a root with a callback
func CalculateRoot(num int, h func(indx int) []byte) types.Hash {
if num == 0 {
return types.EmptyRootHash
}
if num <= 128 {
fastH := acquireFastHasher()
dst, ok := fastH.Hash(num, h)
// important to copy the return before releasing the hasher
res := types.BytesToHash(dst)
releaseFastHasher(fastH)
if ok {
return res
}
}
// fallback to slow hash
return types.BytesToHash(deriveSlow(num, h))
}
var numArenaPool fastrlp.ArenaPool
func deriveSlow(num int, h func(indx int) []byte) []byte {
t := itrie.NewTrie()
txn := t.Txn()
ar := numArenaPool.Get()
for i := 0; i < num; i++ {
indx := ar.NewUint(uint64(i))
txn.Insert(indx.MarshalTo(nil), h(i))
ar.Reset()
}
numArenaPool.Put(ar)
x, _ := txn.Hash()
return x
}