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  }