github.com/decred/dcrlnd@v0.7.6/shachain/producer.go (about) 1 package shachain 2 3 import ( 4 "io" 5 ) 6 7 // Producer is an interface which serves as an abstraction over the data 8 // structure responsible for efficiently generating the secrets for a 9 // particular index based on a root seed. The generation of secrets should be 10 // made in such way that secret store might efficiently store and retrieve the 11 // secrets. This is typically implemented as a tree-based PRF. 12 type Producer interface { 13 // AtIndex produces a secret by evaluating using the initial seed and a 14 // particular index. 15 AtIndex(uint64) (*ShaHash, error) 16 17 // Encode writes a binary serialization of the Producer implementation 18 // to the passed io.Writer. 19 Encode(io.Writer) error 20 } 21 22 // RevocationProducer is an implementation of Producer interface using the 23 // shachain PRF construct. Starting with a single 32-byte element generated 24 // from a CSPRNG, shachain is able to efficiently generate a nearly unbounded 25 // number of secrets while maintaining a constant amount of storage. The 26 // original description of shachain can be found here: 27 // https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/shachain/design.txt 28 // with supplementary material here: 29 // https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#per-commitment-secret-requirements 30 type RevocationProducer struct { 31 // root is the element from which we may generate all hashes which 32 // corresponds to the index domain [281474976710655,0]. 33 root *element 34 } 35 36 // A compile time check to ensure RevocationProducer implements the Producer 37 // interface. 38 var _ Producer = (*RevocationProducer)(nil) 39 40 // NewRevocationProducer creates new instance of shachain producer. 41 func NewRevocationProducer(root ShaHash) *RevocationProducer { 42 return &RevocationProducer{ 43 root: &element{ 44 index: rootIndex, 45 hash: root, 46 }} 47 } 48 49 // NewRevocationProducerFromBytes deserializes an instance of a 50 // RevocationProducer encoded in the passed byte slice, returning a fully 51 // initialized instance of a RevocationProducer. 52 func NewRevocationProducerFromBytes(data []byte) (*RevocationProducer, error) { 53 root, err := NewHash(data) 54 if err != nil { 55 return nil, err 56 } 57 58 return &RevocationProducer{ 59 root: &element{ 60 index: rootIndex, 61 hash: *root, 62 }, 63 }, nil 64 } 65 66 // AtIndex produces a secret by evaluating using the initial seed and a 67 // particular index. 68 // 69 // NOTE: Part of the Producer interface. 70 func (p *RevocationProducer) AtIndex(v uint64) (*ShaHash, error) { 71 ind := newIndex(v) 72 73 element, err := p.root.derive(ind) 74 if err != nil { 75 return nil, err 76 } 77 78 return &element.hash, nil 79 } 80 81 // Encode writes a binary serialization of the Producer implementation to the 82 // passed io.Writer. 83 // 84 // NOTE: Part of the Producer interface. 85 func (p *RevocationProducer) Encode(w io.Writer) error { 86 _, err := w.Write(p.root.hash[:]) 87 return err 88 }