From 0144bdb241b34a9c298ea7c32e0a3fa7e35c98f8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Jan 2021 14:51:51 -0800 Subject: [PATCH] amp/child: add Child deriviation --- amp/child.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 amp/child.go diff --git a/amp/child.go b/amp/child.go new file mode 100644 index 00000000..3ba77fae --- /dev/null +++ b/amp/child.go @@ -0,0 +1,85 @@ +package amp + +import ( + "crypto/sha256" + "encoding/binary" + "fmt" + + "github.com/lightningnetwork/lnd/lntypes" +) + +// Share represents an n-of-n sharing of a secret 32-byte value. The secret can +// be recovered by XORing all n shares together. +type Share [32]byte + +// ChildDesc contains the information necessary to derive a child hash/preimage +// pair that is attached to a particular HTLC. This information will be known by +// both the sender and receiver in the process of fulfilling an AMP payment. +type ChildDesc struct { + // Share is one of n shares of the root seed. Once all n shares are + // known to the receiver, the Share will also provide entropy to the + // derivation of child hash and preimage. + Share Share + + // Index is 32-bit value that can be used to derive up to 2^32 child + // hashes and preimages from a single Share. This allows the payment + // hashes sent over the network to be refreshed without needing to + // modify the Share. + Index uint32 +} + +// Child is a payment hash and preimage pair derived from the root seed. In +// addition to the derived values, a Child carries all information required in +// the derivation apart from the root seed (unless n=1). +type Child struct { + // ChildDesc contains the data required to derive the child hash and + // preimage below. + ChildDesc + + // Preimage is the child payment preimage that can be used to settle the + // HTLC carrying Hash. + Preimage lntypes.Preimage + + // Hash is the child payment hash that to be carried by the HTLC. + Hash lntypes.Hash +} + +// String returns a human-readable description of a Child. +func (c *Child) String() string { + return fmt.Sprintf("share=%x, index=%d -> preimage=%v, hash=%v", + c.Share, c.Index, c.Preimage, c.Hash) +} + +// DeriveChild computes the child preimage and child hash for a given (root, +// share, index) tuple. The derivation is defined as: +// +// child_preimage = SHA256(root || share || be32(index)), +// child_hash = SHA256(child_preimage). +func DeriveChild(root Share, desc ChildDesc) *Child { + var ( + indexBytes [4]byte + preimage lntypes.Preimage + hash lntypes.Hash + ) + + // Serialize the child index in big-endian order. + binary.BigEndian.PutUint32(indexBytes[:], desc.Index) + + // Compute child_preimage as SHA256(root || share || child_index). + h := sha256.New() + _, _ = h.Write(root[:]) + _, _ = h.Write(desc.Share[:]) + _, _ = h.Write(indexBytes[:]) + copy(preimage[:], h.Sum(nil)) + + // Compute child_hash as SHA256(child_preimage). + h = sha256.New() + _, _ = h.Write(preimage[:]) + copy(hash[:], h.Sum(nil)) + + return &Child{ + ChildDesc: desc, + Preimage: preimage, + Hash: hash, + } +}