-
Notifications
You must be signed in to change notification settings - Fork 18
/
batchproof.go
150 lines (126 loc) · 3.8 KB
/
batchproof.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (c) 2021 The utreexo developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package wire
import (
"fmt"
"io"
"strings"
"github.com/utreexo/utreexo"
"github.com/utreexo/utreexod/chaincfg/chainhash"
)
// BatchProofSerializeTargetSize returns how many bytes it would take to serialize all
// the targets in the batch proof.
func BatchProofSerializeTargetSize(bp *utreexo.Proof) int {
size := VarIntSerializeSize(uint64(len(bp.Targets)))
for _, target := range bp.Targets {
size += VarIntSerializeSize(target)
}
return size
}
// BatchProofAccProofSize returns how many bytes it would take to serialize the
// accumulator proof in the batch proof.
func BatchProofSerializeAccProofSize(bp *utreexo.Proof) int {
size := VarIntSerializeSize(uint64(len(bp.Proof)))
size += chainhash.HashSize * len(bp.Proof)
return size
}
// BatchProofSerializeSize returns the number of bytes it would tkae to serialize
// a BatchProof.
func BatchProofSerializeSize(bp *utreexo.Proof) int {
// First the targets.
size := BatchProofSerializeTargetSize(bp)
// Then the proofs.
return size + BatchProofSerializeAccProofSize(bp)
}
// -----------------------------------------------------------------------------
// BatchProof serialization defines how the utreexo accumulator proof will be
// serialized both for i/o.
//
// Note that this serialization format differs from the one from
// github.com/mit-dci/utreexo/accumulator as this serialization method uses
// varints and the one in that package does not. They are not compatible and
// should not be used together. The serialization method here is more compact
// and thus is better for wire and disk storage.
//
// The serialized format is:
// [<target count><targets><proof count><proofs>]
//
// All together, the serialization looks like so:
// Field Type Size
// target count varint 1-8 bytes
// targets []uint64 variable
// hash count varint 1-8 bytes
// hashes []32 byte variable
//
// -----------------------------------------------------------------------------
// BatchProofSerialize encodes the BatchProof to w using the BatchProof
// serialization format.
func BatchProofSerialize(w io.Writer, bp *utreexo.Proof) error {
err := WriteVarInt(w, 0, uint64(len(bp.Targets)))
if err != nil {
return err
}
for _, t := range bp.Targets {
err = WriteVarInt(w, 0, t)
if err != nil {
return err
}
}
err = WriteVarInt(w, 0, uint64(len(bp.Proof)))
if err != nil {
return err
}
// then the rest is just hashes
for _, h := range bp.Proof {
_, err = w.Write(h[:])
if err != nil {
return err
}
}
return nil
}
// BatchProofSerialize decodes the BatchProof to r using the BatchProof
// serialization format.
func BatchProofDeserialize(r io.Reader) (*utreexo.Proof, error) {
targetCount, err := ReadVarInt(r, 0)
if err != nil {
return nil, err
}
targets := make([]uint64, targetCount)
for i := range targets {
target, err := ReadVarInt(r, 0)
if err != nil {
return nil, err
}
targets[i] = target
}
proofCount, err := ReadVarInt(r, 0)
if err != nil {
return nil, err
}
proofs := make([]utreexo.Hash, proofCount)
for i := range proofs {
_, err = io.ReadFull(r, proofs[i][:])
if err != nil {
return nil, err
}
}
return &utreexo.Proof{Targets: targets, Proof: proofs}, nil
}
// BatchProofToString converts a batchproof into a human-readable string. Note
// that the hashes are in little endian order.
func BatchProofToString(bp *utreexo.Proof) string {
// First the targets.
str := "targets:" + strings.Join(strings.Fields(fmt.Sprint(bp.Targets)), ",") + " "
// Then the proofs.
str += "proofs: ["
for i, hash := range bp.Proof {
str += chainhash.Hash(hash).String()
if i != len(bp.Proof)-1 {
str += ","
}
}
str += "]"
return str
}