@@ -8,8 +8,8 @@ package merkletree
88*/
99import "C"
1010import (
11- "errors"
1211 "fmt"
12+ "unsafe"
1313)
1414
1515// CPPMerkleTree provides an interface to the C++ CT MerkleTree library.
@@ -39,50 +39,56 @@ func (m *CPPMerkleTree) LevelCount() uint64 {
3939// the tree structure, does not store the data itself.
4040// Returns the position of the leaf in the tree.
4141func (m * CPPMerkleTree ) AddLeaf (leaf []byte ) uint64 {
42- return uint64 (C .AddLeaf (m .peer , C .BYTE_SLICE (& leaf )))
42+ var leafPtr unsafe.Pointer
43+ // Don't flake out if we're passed an empty leaf slice.
44+ // We'll end up passing nullptr to the C++ code, but that's fine since we'll
45+ // also be passing a size of 0.
46+ if len (leaf ) > 0 {
47+ leafPtr = unsafe .Pointer (& leaf [0 ])
48+ }
49+ return uint64 (C .AddLeaf (m .peer , leafPtr , C .size_t (len (leaf ))))
4350}
4451
4552// AddLeafHash adds a leaf hash directly to the tree. Returns the position of
4653// the leaf in the tree.
4754func (m * CPPMerkleTree ) AddLeafHash (hash []byte ) uint64 {
48- return uint64 (C .AddLeafHash (m .peer , C . BYTE_SLICE (& hash )))
55+ return uint64 (C .AddLeafHash (m .peer , unsafe . Pointer (& hash [ 0 ]), C . size_t ( len ( hash ) )))
4956}
5057
5158// LeafHash returns the leaf hash for the leaf at the requested index.
5259func (m * CPPMerkleTree ) LeafHash (leaf uint64 ) ([]byte , error ) {
5360 hash := make ([]byte , m .nodeSize )
54- success := C .LeafHash (m .peer , C .BYTE_SLICE ( & hash ), C .size_t (leaf ))
55- if ! success {
56- return nil , fmt .Errorf ("failed to get leafhash of leaf %d" , leaf )
61+ size := C .LeafHash (m .peer , C .size_t ( leaf ), unsafe . Pointer ( & hash [ 0 ] ), C .size_t (len ( hash ) ))
62+ if got , want := size , m . nodeSize ; got != want {
63+ return nil , fmt .Errorf ("failed to get leafhash of leaf %d, got %d bytes expected %d " , leaf , got , want )
5764 }
5865 return hash , nil
5966}
6067
6168// CurrentRoot returns the current root of the tree.
6269func (m * CPPMerkleTree ) CurrentRoot () ([]byte , error ) {
6370 hash := make ([]byte , m .nodeSize )
64- success := C .CurrentRoot (m .peer , C . BYTE_SLICE (& hash ))
65- if ! success {
66- return nil , errors . New ("failed to get current root" )
71+ size := C .CurrentRoot (m .peer , unsafe . Pointer (& hash [ 0 ]), C . size_t ( len ( hash ) ))
72+ if got , want := size , m . nodeSize ; got != want {
73+ return nil , fmt . Errorf ("failed to get current root, got %d bytes, expected %d" , got , want )
6774 }
6875 return hash , nil
6976}
7077
7178// RootAtSnapshot returns the root at a given index.
7279func (m * CPPMerkleTree ) RootAtSnapshot (snapshot uint64 ) ([]byte , error ) {
7380 hash := make ([]byte , m .nodeSize )
74- success := C .RootAtSnapshot (m .peer , C .BYTE_SLICE ( & hash ), C .size_t (snapshot ))
75- if ! success {
76- return nil , fmt .Errorf ("failed to get root at snapshot %d" , snapshot )
81+ size := C .RootAtSnapshot (m .peer , C .size_t ( snapshot ), unsafe . Pointer ( & hash [ 0 ] ), C .size_t (len ( hash ) ))
82+ if got , want := size , m . nodeSize ; got != want {
83+ return nil , fmt .Errorf ("failed to get root at snapshot %d, got %d bytes, expected %d " , snapshot , got , want )
7784 }
7885 return hash , nil
7986}
8087
81- func splitSlice (slice []byte , chunkSize int ) ([][]byte , error ) {
88+ func splitSlice (slice []byte , numEntries , chunkSize int ) ([][]byte , error ) {
8289 if len (slice )% chunkSize != 0 {
8390 return nil , fmt .Errorf ("slice len %d is not a multiple of chunkSize %d" , len (slice ), chunkSize )
8491 }
85- numEntries := len (slice ) / chunkSize
8692 ret := make ([][]byte , numEntries )
8793 for i := 0 ; i < numEntries ; i ++ {
8894 start := i * chunkSize
@@ -96,33 +102,33 @@ func splitSlice(slice []byte, chunkSize int) ([][]byte, error) {
96102func (m * CPPMerkleTree ) PathToCurrentRoot (leaf uint64 ) ([][]byte , error ) {
97103 var numEntries C.size_t
98104 entryBuffer := make ([]byte , C .size_t (m .LevelCount ())* m .nodeSize )
99- success := C .PathToCurrentRoot (m .peer , C .BYTE_SLICE ( & entryBuffer ), & numEntries , C .size_t (leaf ) )
105+ success := C .PathToCurrentRoot (m .peer , C .size_t ( leaf ), unsafe . Pointer ( & entryBuffer [ 0 ]) , C .size_t (len ( entryBuffer )), & numEntries )
100106 if ! success {
101107 return nil , fmt .Errorf ("failed to get path to current root from leaf %d" , leaf )
102108 }
103- return splitSlice (entryBuffer , int (m .nodeSize ))
109+ return splitSlice (entryBuffer , int (numEntries ), int ( m .nodeSize ))
104110}
105111
106112// PathToRootAtSnapshot returns an audit path to a given root for a given leaf.
107113func (m * CPPMerkleTree ) PathToRootAtSnapshot (leaf , snapshot uint64 ) ([][]byte , error ) {
108114 var numEntries C.size_t
109115 entryBuffer := make ([]byte , C .size_t (m .LevelCount ())* m .nodeSize )
110- success := C .PathToRootAtSnapshot (m .peer , C .BYTE_SLICE ( & entryBuffer ), & numEntries , C .size_t (leaf ), C .size_t (snapshot ) )
116+ success := C .PathToRootAtSnapshot (m .peer , C .size_t ( leaf ), C .size_t (snapshot ), unsafe . Pointer ( & entryBuffer [ 0 ]), C .size_t (len ( entryBuffer )), & numEntries )
111117 if ! success {
112118 return nil , fmt .Errorf ("failed to get path to root at snapshot %d from leaf %d" , snapshot , leaf )
113119 }
114- return splitSlice (entryBuffer , int (m .nodeSize ))
120+ return splitSlice (entryBuffer , int (numEntries ), int ( m .nodeSize ))
115121}
116122
117123// SnapshotConsistency returns a consistency proof between two given snapshots.
118124func (m * CPPMerkleTree ) SnapshotConsistency (snapshot1 , snapshot2 uint64 ) ([][]byte , error ) {
119125 var numEntries C.size_t
120126 entryBuffer := make ([]byte , C .size_t (m .LevelCount ())* m .nodeSize )
121- success := C .SnapshotConsistency (m .peer , C .BYTE_SLICE ( & entryBuffer ), & numEntries , C .size_t (snapshot1 ), C .size_t (snapshot2 ) )
127+ success := C .SnapshotConsistency (m .peer , C .size_t ( snapshot1 ), C .size_t (snapshot2 ), unsafe . Pointer ( & entryBuffer [ 0 ]), C .size_t (len ( entryBuffer )), & numEntries )
122128 if ! success {
123129 return nil , fmt .Errorf ("failed to get path to snapshot consistency from %d to %d" , snapshot1 , snapshot2 )
124130 }
125- return splitSlice (entryBuffer , int (m .nodeSize ))
131+ return splitSlice (entryBuffer , int (numEntries ), int ( m .nodeSize ))
126132}
127133
128134// NewCPPMerkleTree returns a new wrapped C++ MerkleTree, using the
0 commit comments