lnwallet/interface_test: add testCreateSimpleTx

This commit is contained in:
Johan T. Halseth 2019-03-05 14:22:30 +01:00
parent 306c0c8aab
commit 54f1f32e71
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -2221,6 +2221,187 @@ func testLastUnusedAddr(miner *rpctest.Harness,
} }
} }
// testCreateSimpleTx checks that a call to CreateSimpleTx will return a
// transaction that is equal to the one that is being created by SendOutputs in
// a subsequent call.
func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
_ *lnwallet.LightningWallet, t *testing.T) {
// Send some money from the miner to the wallet
err := loadTestCredits(r, w, 20, 4)
if err != nil {
t.Fatalf("unable to send money to lnwallet: %v", err)
}
// The test cases we will run through for all backends.
testCases := []struct {
outVals []int64
feeRate lnwallet.SatPerKWeight
valid bool
}{
{
outVals: []int64{},
feeRate: 2500,
valid: false, // No outputs.
},
{
outVals: []int64{1e3},
feeRate: 2500,
valid: false, // Dust output.
},
{
outVals: []int64{1e8},
feeRate: 2500,
valid: true,
},
{
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
feeRate: 2500,
valid: true,
},
{
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
feeRate: 12500,
valid: true,
},
{
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
feeRate: 50000,
valid: true,
},
{
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5, 1e8, 2e8,
1e8, 2e7, 3e5},
feeRate: 44250,
valid: true,
},
}
for _, test := range testCases {
feeRate := test.feeRate
// Grab some fresh addresses from the miner that we will send
// to.
outputs := make([]*wire.TxOut, len(test.outVals))
for i, outVal := range test.outVals {
minerAddr, err := r.NewAddress()
if err != nil {
t.Fatalf("unable to generate address for "+
"miner: %v", err)
}
script, err := txscript.PayToAddrScript(minerAddr)
if err != nil {
t.Fatalf("unable to create pay to addr "+
"script: %v", err)
}
output := &wire.TxOut{
Value: outVal,
PkScript: script,
}
outputs[i] = output
}
// Now try creating a tx spending to these outputs.
createTx, createErr := w.CreateSimpleTx(
outputs, feeRate, true,
)
if test.valid == (createErr != nil) {
fmt.Println(spew.Sdump(createTx.Tx))
t.Fatalf("got unexpected error when creating tx: %v",
createErr)
}
// Also send to these outputs. This should result in a tx
// _very_ similar to the one we just created being sent. The
// only difference is that the dry run tx is not signed, and
// that the change output position might be different.
tx, sendErr := w.SendOutputs(outputs, feeRate)
if test.valid == (sendErr != nil) {
t.Fatalf("got unexpected error when sending tx: %v",
sendErr)
}
// We expected either both to not fail, or both to fail with
// the same error.
if createErr != sendErr {
t.Fatalf("error creating tx (%v) different "+
"from error sending outputs (%v)",
createErr, sendErr)
}
// If we expected the creation to fail, then this test is over.
if !test.valid {
continue
}
txid := tx.TxHash()
err = waitForMempoolTx(r, &txid)
if err != nil {
t.Fatalf("tx not relayed to miner: %v", err)
}
// Helper method to check that the two txs are similar.
assertSimilarTx := func(a, b *wire.MsgTx) error {
if a.Version != b.Version {
return fmt.Errorf("different versions: "+
"%v vs %v", a.Version, b.Version)
}
if a.LockTime != b.LockTime {
return fmt.Errorf("different locktimes: "+
"%v vs %v", a.LockTime, b.LockTime)
}
if len(a.TxIn) != len(b.TxIn) {
return fmt.Errorf("different number of "+
"inputs: %v vs %v", len(a.TxIn),
len(b.TxIn))
}
if len(a.TxOut) != len(b.TxOut) {
return fmt.Errorf("different number of "+
"outputs: %v vs %v", len(a.TxOut),
len(b.TxOut))
}
// They should be spending the same inputs.
for i := range a.TxIn {
prevA := a.TxIn[i].PreviousOutPoint
prevB := b.TxIn[i].PreviousOutPoint
if prevA != prevB {
return fmt.Errorf("different inputs: "+
"%v vs %v", spew.Sdump(prevA),
spew.Sdump(prevB))
}
}
// They should have the same outputs. Since the change
// output position gets randomized, they are not
// guaranteed to be in the same order.
for _, outA := range a.TxOut {
found := false
for _, outB := range b.TxOut {
if reflect.DeepEqual(outA, outB) {
found = true
break
}
}
if !found {
return fmt.Errorf("did not find "+
"output %v", spew.Sdump(outA))
}
}
return nil
}
// Assert that our "template tx" was similar to the one that
// ended up being sent.
if err := assertSimilarTx(createTx.Tx, tx); err != nil {
t.Fatalf("transactions not similar: %v", err)
}
}
}
type walletTestCase struct { type walletTestCase struct {
name string name string
test func(miner *rpctest.Harness, alice, bob *lnwallet.LightningWallet, test func(miner *rpctest.Harness, alice, bob *lnwallet.LightningWallet,
@ -2283,6 +2464,10 @@ var walletTests = []walletTestCase{
name: "reorg wallet balance", name: "reorg wallet balance",
test: testReorgWalletBalance, test: testReorgWalletBalance,
}, },
{
name: "create simple tx",
test: testCreateSimpleTx,
},
} }
func clearWalletStates(a, b *lnwallet.LightningWallet) error { func clearWalletStates(a, b *lnwallet.LightningWallet) error {