You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.5 KiB
141 lines
3.5 KiB
package amp_test |
|
|
|
import ( |
|
"testing" |
|
|
|
"github.com/lightningnetwork/lnd/amp" |
|
"github.com/stretchr/testify/require" |
|
) |
|
|
|
type sharerTest struct { |
|
name string |
|
numShares int |
|
merge bool |
|
} |
|
|
|
var sharerTests = []sharerTest{ |
|
{ |
|
name: "root only", |
|
numShares: 1, |
|
}, |
|
{ |
|
name: "two shares", |
|
numShares: 2, |
|
}, |
|
{ |
|
name: "many shares", |
|
numShares: 10, |
|
}, |
|
{ |
|
name: "merge 4 shares", |
|
numShares: 4, |
|
merge: true, |
|
}, |
|
{ |
|
name: "merge many shares", |
|
numShares: 20, |
|
merge: true, |
|
}, |
|
} |
|
|
|
// TestSharer executes the end-to-end derivation between sender and receiver, |
|
// asserting that shares are properly computed and, when reconstructed by the |
|
// receiver, produce identical child hashes and preimages as the sender. |
|
func TestSharer(t *testing.T) { |
|
for _, test := range sharerTests { |
|
test := test |
|
t.Run(test.name, func(t *testing.T) { |
|
t.Parallel() |
|
|
|
testSharer(t, test) |
|
}) |
|
} |
|
} |
|
|
|
func testSharer(t *testing.T, test sharerTest) { |
|
// Construct a new sharer with a random seed. |
|
var ( |
|
sharer amp.Sharer |
|
err error |
|
) |
|
sharer, err = amp.NewSeedSharer() |
|
require.NoError(t, err) |
|
|
|
// Assert that we can instantiate an equivalent root sharer using the |
|
// root share. |
|
root := sharer.Root() |
|
sharerFromRoot := amp.SeedSharerFromRoot(&root) |
|
require.Equal(t, sharer, sharerFromRoot) |
|
|
|
// Generate numShares-1 randomized shares. |
|
children := make([]*amp.Child, 0, test.numShares) |
|
for i := 0; i < test.numShares-1; i++ { |
|
var left amp.Sharer |
|
left, sharer, err = sharer.Split() |
|
require.NoError(t, err) |
|
|
|
child := left.Child(0) |
|
|
|
assertChildShare(t, child, 0) |
|
children = append(children, child) |
|
} |
|
|
|
// Compute the final share and finalize the sharing. |
|
child := sharer.Child(0) |
|
sharer = sharer.Zero() |
|
|
|
assertChildShare(t, child, 0) |
|
children = append(children, child) |
|
|
|
// If we are testing merging, merge half of the created children back |
|
// into the sharer. |
|
if test.merge { |
|
for i := len(children) / 2; i < len(children); i++ { |
|
sharer = sharer.Merge(children[i]) |
|
} |
|
children = children[:len(children)/2] |
|
|
|
// We must create a new last child from what we just merged |
|
// back. |
|
child := sharer.Child(0) |
|
|
|
assertChildShare(t, child, 0) |
|
children = append(children, child) |
|
} |
|
|
|
assertReconstruction(t, children...) |
|
} |
|
|
|
// assertChildShare checks that the child has the expected child index, and that |
|
// the child's preimage is valid for the its hash. |
|
func assertChildShare(t *testing.T, child *amp.Child, expIndex int) { |
|
t.Helper() |
|
|
|
require.Equal(t, uint32(expIndex), child.Index) |
|
require.True(t, child.Preimage.Matches(child.Hash)) |
|
} |
|
|
|
// assertReconstruction takes a list of children and simulates the receiver |
|
// recombining the shares, and then deriving the child preimage and hash for |
|
// each HTLC. This asserts that the receiver can always rederive the full set of |
|
// children knowing only the shares and child indexes for each. |
|
func assertReconstruction(t *testing.T, children ...*amp.Child) { |
|
t.Helper() |
|
|
|
// Reconstruct a child descriptor for each of the provided children. |
|
// In practice, the receiver will only know the share and the child |
|
// index it learns for each HTLC. |
|
descs := make([]amp.ChildDesc, 0, len(children)) |
|
for _, child := range children { |
|
descs = append(descs, amp.ChildDesc{ |
|
Share: child.Share, |
|
Index: child.Index, |
|
}) |
|
} |
|
|
|
// Now, recombine the shares and rederive a child for each of the |
|
// descriptors above. The resulting set of children should exactly match |
|
// the set provided. |
|
children2 := amp.ReconstructChildren(descs...) |
|
require.Equal(t, children, children2) |
|
}
|
|
|