github.com/decred/dcrlnd@v0.7.6/amp/child.go (about)

     1  package amp
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"encoding/binary"
     6  	"fmt"
     7  
     8  	"github.com/decred/dcrlnd/lntypes"
     9  )
    10  
    11  // Share represents an n-of-n sharing of a secret 32-byte value. The secret can
    12  // be recovered by XORing all n shares together.
    13  type Share [32]byte
    14  
    15  // Xor stores the byte-wise xor of shares x and y in z.
    16  func (z *Share) Xor(x, y *Share) {
    17  	for i := range z {
    18  		z[i] = x[i] ^ y[i]
    19  	}
    20  }
    21  
    22  // ChildDesc contains the information necessary to derive a child hash/preimage
    23  // pair that is attached to a particular HTLC. This information will be known by
    24  // both the sender and receiver in the process of fulfilling an AMP payment.
    25  type ChildDesc struct {
    26  	// Share is one of n shares of the root seed. Once all n shares are
    27  	// known to the receiver, the Share will also provide entropy to the
    28  	// derivation of child hash and preimage.
    29  	Share Share
    30  
    31  	// Index is 32-bit value that can be used to derive up to 2^32 child
    32  	// hashes and preimages from a single Share. This allows the payment
    33  	// hashes sent over the network to be refreshed without needing to
    34  	// modify the Share.
    35  	Index uint32
    36  }
    37  
    38  // Child is a payment hash and preimage pair derived from the root seed. In
    39  // addition to the derived values, a Child carries all information required in
    40  // the derivation apart from the root seed (unless n=1).
    41  type Child struct {
    42  	// ChildDesc contains the data required to derive the child hash and
    43  	// preimage below.
    44  	ChildDesc
    45  
    46  	// Preimage is the child payment preimage that can be used to settle the
    47  	// HTLC carrying Hash.
    48  	Preimage lntypes.Preimage
    49  
    50  	// Hash is the child payment hash that to be carried by the HTLC.
    51  	Hash lntypes.Hash
    52  }
    53  
    54  // String returns a human-readable description of a Child.
    55  func (c *Child) String() string {
    56  	return fmt.Sprintf("share=%x, index=%d -> preimage=%v, hash=%v",
    57  		c.Share, c.Index, c.Preimage, c.Hash)
    58  }
    59  
    60  // DeriveChild computes the child preimage and child hash for a given (root,
    61  // share, index) tuple. The derivation is defined as:
    62  //
    63  //	child_preimage = SHA256(root || share || be32(index)),
    64  //	child_hash     = SHA256(child_preimage).
    65  func DeriveChild(root Share, desc ChildDesc) *Child {
    66  	var (
    67  		indexBytes [4]byte
    68  		preimage   lntypes.Preimage
    69  		hash       lntypes.Hash
    70  	)
    71  
    72  	// Serialize the child index in big-endian order.
    73  	binary.BigEndian.PutUint32(indexBytes[:], desc.Index)
    74  
    75  	// Compute child_preimage as SHA256(root || share || child_index).
    76  	h := sha256.New()
    77  	_, _ = h.Write(root[:])
    78  	_, _ = h.Write(desc.Share[:])
    79  	_, _ = h.Write(indexBytes[:])
    80  	copy(preimage[:], h.Sum(nil))
    81  
    82  	// Compute child_hash as SHA256(child_preimage).
    83  	h = sha256.New()
    84  	_, _ = h.Write(preimage[:])
    85  	copy(hash[:], h.Sum(nil))
    86  
    87  	return &Child{
    88  		ChildDesc: desc,
    89  		Preimage:  preimage,
    90  		Hash:      hash,
    91  	}
    92  }