-
Notifications
You must be signed in to change notification settings - Fork 260
/
commitment_builder.go
91 lines (82 loc) · 2.43 KB
/
commitment_builder.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
// Copyright © 2019-2020 Binance
//
// This file is part of Binance. The full Binance copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.
package commitments
import (
"errors"
"fmt"
"math/big"
)
const (
PartsCap = 3
MaxPartSize = int64(1 * 1024 * 1024) // 1 MB - rather liberal
)
type builder struct {
parts [][]*big.Int
}
func NewBuilder() *builder {
b := new(builder)
b.parts = make([][]*big.Int, 0, PartsCap)
return b
}
func (b *builder) Parts() [][]*big.Int {
return b.parts[:]
}
func (b *builder) AddPart(part []*big.Int) *builder {
b.parts = append(b.parts, part[:])
return b
}
func (b *builder) Secrets() ([]*big.Int, error) {
secretsLen := 0
if len(b.parts) > PartsCap {
return nil, fmt.Errorf("builder.Secrets: too many commitment parts provided: got %d, max %d", len(b.parts), PartsCap)
}
for _, p := range b.parts {
secretsLen += 1 + len(p) // +1 to accommodate length prefix element
}
secrets := make([]*big.Int, 0, secretsLen)
for i, p := range b.parts {
partLen := int64(len(p))
if MaxPartSize < partLen {
return nil, fmt.Errorf("builder.Secrets: commitment part too large: part %d, size %d", i, partLen)
}
secrets = append(secrets, big.NewInt(partLen))
secrets = append(secrets, p...)
}
return secrets, nil
}
func ParseSecrets(secrets []*big.Int) ([][]*big.Int, error) {
if secrets == nil || len(secrets) < 2 {
return nil, errors.New("ParseSecrets: secrets == nil or is too small")
}
var el, nextPartLen int64
parts := make([][]*big.Int, 0, PartsCap)
isLenEl := true // are we looking at a length prefix element? (first one is)
inLen := int64(len(secrets))
for el < inLen {
if el < 0 {
return nil, errors.New("ParseSecrets: `el` overflow")
}
if isLenEl {
nextPartLen = secrets[el].Int64()
if MaxPartSize < nextPartLen {
return nil, fmt.Errorf("ParseSecrets: commitment part too large: part %d, size %d", len(parts), nextPartLen)
}
el += 1
} else {
if PartsCap <= len(parts) {
return nil, fmt.Errorf("ParseSecrets: commitment has too many parts: part %d, max %d", len(parts), PartsCap)
}
if inLen < el+nextPartLen {
return nil, errors.New("ParseSecrets: not enough data to consume stated data length")
}
part := secrets[el : el+nextPartLen]
parts = append(parts, part)
el += nextPartLen
}
isLenEl = !isLenEl
}
return parts, nil
}