Files
tss-lib/crypto/commitments/builder.go
2020-11-15 16:23:52 +08:00

95 lines
2.6 KiB
Go

// Copyright © 2019 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 * 128) // ~128 KB
)
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 nextPartLen <= 0 {
return nil, fmt.Errorf("ParseSecrets: commitment part len is 0 or negative: part %d, len %d", len(parts), nextPartLen)
}
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
}