77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
|
package shachain
|
||
|
|
||
|
import (
|
||
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||
|
)
|
||
|
|
||
|
// Producer is an interface which serves as an abstraction over data
|
||
|
// structure responsible for efficient generating the secrets by given index.
|
||
|
// The generation of secrets should be made in such way that secret store
|
||
|
// might efficiently store and retrieve the secrets.
|
||
|
type Producer interface {
|
||
|
// AtIndex produce secret by given index.
|
||
|
AtIndex(uint64) (*chainhash.Hash, error)
|
||
|
|
||
|
// ToBytes convert producer to the binary representation.
|
||
|
ToBytes() ([]byte, error)
|
||
|
}
|
||
|
|
||
|
// RevocationProducer implementation of Producer. This version of shachain
|
||
|
// slightly changed in terms of method naming. Initial concept might be found
|
||
|
// here:
|
||
|
// https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/shachain/design.txt
|
||
|
type RevocationProducer struct {
|
||
|
// root is the element from which we may generate all hashes which
|
||
|
// corresponds to the index domain [281474976710655,0].
|
||
|
root *element
|
||
|
}
|
||
|
|
||
|
// A compile time check to ensure RevocationProducer implements the Producer
|
||
|
// interface.
|
||
|
var _ Producer = (*RevocationProducer)(nil)
|
||
|
|
||
|
// NewRevocationProducer create new instance of shachain producer.
|
||
|
func NewRevocationProducer(root *chainhash.Hash) *RevocationProducer {
|
||
|
return &RevocationProducer{
|
||
|
root: &element{
|
||
|
index: rootIndex,
|
||
|
hash: *root,
|
||
|
}}
|
||
|
}
|
||
|
|
||
|
// NewRevocationProducerFromBytes deserialize an instance of a RevocationProducer
|
||
|
// encoded in the passed byte slice, returning a fully initialize instance of a
|
||
|
// RevocationProducer.
|
||
|
func NewRevocationProducerFromBytes(data []byte) (*RevocationProducer, error) {
|
||
|
root, err := chainhash.NewHash(data)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &RevocationProducer{
|
||
|
root: &element{
|
||
|
index: rootIndex,
|
||
|
hash: *root,
|
||
|
},
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// AtIndex produce secret by given index.
|
||
|
// NOTE: Part of the Producer interface.
|
||
|
func (p *RevocationProducer) AtIndex(v uint64) (*chainhash.Hash, error) {
|
||
|
ind := newIndex(v)
|
||
|
|
||
|
element, err := p.root.derive(ind)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &element.hash, nil
|
||
|
}
|
||
|
|
||
|
// ToBytes convert producer to the binary representation.
|
||
|
// NOTE: Part of the Producer interface.
|
||
|
func (p *RevocationProducer) ToBytes() ([]byte, error) {
|
||
|
return p.root.hash.CloneBytes(), nil
|
||
|
}
|