lntemp+itest: refactor testSignOutputRaw
This commit is contained in:
5 files changed
+120
-91
No files matched your search
@@ -1944,3 +1944,26 @@ func (h *HarnessTest) ReceiveChannelEvent(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOutputIndex returns the output index of the given address in the given
|
||||||
|
// transaction.
|
||||||
|
func (h *HarnessTest) GetOutputIndex(txid *chainhash.Hash, addr string) int {
|
||||||
|
// We'll then extract the raw transaction from the mempool in order to
|
||||||
|
// determine the index of the p2tr output.
|
||||||
|
tx := h.Miner.GetRawTransaction(txid)
|
||||||
|
|
||||||
|
p2trOutputIndex := -1
|
||||||
|
for i, txOut := range tx.MsgTx().TxOut {
|
||||||
|
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||||
|
txOut.PkScript, h.Miner.ActiveNet,
|
||||||
|
)
|
||||||
|
require.NoError(h, err)
|
||||||
|
|
||||||
|
if addrs[0].String() == addr {
|
||||||
|
p2trOutputIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.Greater(h, p2trOutputIndex, -1)
|
||||||
|
|
||||||
|
return p2trOutputIndex
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package lntemp
|
package lntemp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -2133,3 +2134,36 @@ func (h *HarnessTest) AssertInvoiceEqual(a, b *lnrpc.Invoice) {
|
|||||||
require.Equal(h, htlcA.Amp, htlcB.Amp)
|
require.Equal(h, htlcA.Amp, htlcB.Amp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssertUTXOInWallet asserts that a given UTXO can be found in the node's
|
||||||
|
// wallet.
|
||||||
|
func (h *HarnessTest) AssertUTXOInWallet(hn *node.HarnessNode,
|
||||||
|
op *lnrpc.OutPoint, account string) {
|
||||||
|
|
||||||
|
err := wait.NoError(func() error {
|
||||||
|
req := &walletrpc.ListUnspentRequest{
|
||||||
|
Account: account,
|
||||||
|
}
|
||||||
|
resp := hn.RPC.ListUnspent(req)
|
||||||
|
|
||||||
|
err := fmt.Errorf("tx with hash %x not found", op.TxidBytes)
|
||||||
|
for _, utxo := range resp.Utxos {
|
||||||
|
if !bytes.Equal(utxo.Outpoint.TxidBytes, op.TxidBytes) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fmt.Errorf("tx with output index %v not found",
|
||||||
|
op.OutputIndex)
|
||||||
|
if utxo.Outpoint.OutputIndex != op.OutputIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}, DefaultTimeout)
|
||||||
|
|
||||||
|
require.NoErrorf(h, err, "outpoint %v not found in %s's wallet",
|
||||||
|
op, hn.Name())
|
||||||
|
}
|
||||||
@@ -445,4 +445,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
Name: "derive shared key",
|
Name: "derive shared key",
|
||||||
TestFunc: testDeriveSharedKey,
|
TestFunc: testDeriveSharedKey,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "sign output raw",
|
||||||
|
TestFunc: testSignOutputRaw,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -197,43 +197,35 @@ func runDeriveSharedKey(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
|||||||
|
|
||||||
// testSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
// testSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
// custom ways of specifying the signing key in the key descriptor/locator.
|
||||||
func testSignOutputRaw(net *lntest.NetworkHarness, t *harnessTest) {
|
func testSignOutputRaw(ht *lntemp.HarnessTest) {
|
||||||
runSignOutputRaw(t, net, net.Alice)
|
runSignOutputRaw(ht, ht.Alice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
// custom ways of specifying the signing key in the key descriptor/locator.
|
||||||
func runSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
func runSignOutputRaw(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||||
alice *lntest.HarnessNode) {
|
|
||||||
|
|
||||||
ctxb := context.Background()
|
|
||||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// For the next step, we need a public key. Let's use a special family
|
||||||
// for this. We want this to be an index of zero.
|
// for this. We want this to be an index of zero.
|
||||||
const testCustomKeyFamily = 44
|
const testCustomKeyFamily = 44
|
||||||
keyDesc, err := alice.WalletKitClient.DeriveNextKey(
|
req := &walletrpc.KeyReq{
|
||||||
ctxt, &walletrpc.KeyReq{
|
KeyFamily: testCustomKeyFamily,
|
||||||
KeyFamily: testCustomKeyFamily,
|
}
|
||||||
},
|
keyDesc := alice.RPC.DeriveNextKey(req)
|
||||||
)
|
require.Equal(ht, int32(0), keyDesc.KeyLoc.KeyIndex)
|
||||||
require.NoError(t.t, err)
|
|
||||||
require.Equal(t.t, int32(0), keyDesc.KeyLoc.KeyIndex)
|
|
||||||
|
|
||||||
targetPubKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
|
targetPubKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
// First, try with a key descriptor that only sets the public key.
|
// First, try with a key descriptor that only sets the public key.
|
||||||
assertSignOutputRaw(
|
assertSignOutputRaw(
|
||||||
t, net, alice, targetPubKey, &signrpc.KeyDescriptor{
|
ht, alice, targetPubKey, &signrpc.KeyDescriptor{
|
||||||
RawKeyBytes: keyDesc.RawKeyBytes,
|
RawKeyBytes: keyDesc.RawKeyBytes,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Now try again, this time only with the (0 index!) key locator.
|
// Now try again, this time only with the (0 index!) key locator.
|
||||||
assertSignOutputRaw(
|
assertSignOutputRaw(
|
||||||
t, net, alice, targetPubKey, &signrpc.KeyDescriptor{
|
ht, alice, targetPubKey, &signrpc.KeyDescriptor{
|
||||||
KeyLoc: &signrpc.KeyLocator{
|
KeyLoc: &signrpc.KeyLocator{
|
||||||
KeyFamily: keyDesc.KeyLoc.KeyFamily,
|
KeyFamily: keyDesc.KeyLoc.KeyFamily,
|
||||||
KeyIndex: keyDesc.KeyLoc.KeyIndex,
|
KeyIndex: keyDesc.KeyLoc.KeyIndex,
|
||||||
@@ -243,29 +235,25 @@ func runSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
|||||||
|
|
||||||
// And now test everything again with a new key where we know the index
|
// And now test everything again with a new key where we know the index
|
||||||
// is not 0.
|
// is not 0.
|
||||||
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
|
req = &walletrpc.KeyReq{
|
||||||
defer cancel()
|
KeyFamily: testCustomKeyFamily,
|
||||||
keyDesc, err = alice.WalletKitClient.DeriveNextKey(
|
}
|
||||||
ctxt, &walletrpc.KeyReq{
|
keyDesc = alice.RPC.DeriveNextKey(req)
|
||||||
KeyFamily: testCustomKeyFamily,
|
require.Equal(ht, int32(1), keyDesc.KeyLoc.KeyIndex)
|
||||||
},
|
|
||||||
)
|
|
||||||
require.NoError(t.t, err)
|
|
||||||
require.Equal(t.t, int32(1), keyDesc.KeyLoc.KeyIndex)
|
|
||||||
|
|
||||||
targetPubKey, err = btcec.ParsePubKey(keyDesc.RawKeyBytes)
|
targetPubKey, err = btcec.ParsePubKey(keyDesc.RawKeyBytes)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
// First, try with a key descriptor that only sets the public key.
|
// First, try with a key descriptor that only sets the public key.
|
||||||
assertSignOutputRaw(
|
assertSignOutputRaw(
|
||||||
t, net, alice, targetPubKey, &signrpc.KeyDescriptor{
|
ht, alice, targetPubKey, &signrpc.KeyDescriptor{
|
||||||
RawKeyBytes: keyDesc.RawKeyBytes,
|
RawKeyBytes: keyDesc.RawKeyBytes,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Now try again, this time only with the key locator.
|
// Now try again, this time only with the key locator.
|
||||||
assertSignOutputRaw(
|
assertSignOutputRaw(
|
||||||
t, net, alice, targetPubKey, &signrpc.KeyDescriptor{
|
ht, alice, targetPubKey, &signrpc.KeyDescriptor{
|
||||||
KeyLoc: &signrpc.KeyLocator{
|
KeyLoc: &signrpc.KeyLocator{
|
||||||
KeyFamily: keyDesc.KeyLoc.KeyFamily,
|
KeyFamily: keyDesc.KeyLoc.KeyFamily,
|
||||||
KeyIndex: keyDesc.KeyLoc.KeyIndex,
|
KeyIndex: keyDesc.KeyLoc.KeyIndex,
|
||||||
@@ -277,53 +265,44 @@ func runSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
|||||||
// assertSignOutputRaw sends coins to a p2wkh address derived from the given
|
// assertSignOutputRaw sends coins to a p2wkh address derived from the given
|
||||||
// target public key and then tries to spend that output again by invoking the
|
// target public key and then tries to spend that output again by invoking the
|
||||||
// SignOutputRaw RPC with the key descriptor provided.
|
// SignOutputRaw RPC with the key descriptor provided.
|
||||||
func assertSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
func assertSignOutputRaw(ht *lntemp.HarnessTest,
|
||||||
alice *lntest.HarnessNode, targetPubKey *btcec.PublicKey,
|
alice *node.HarnessNode, targetPubKey *btcec.PublicKey,
|
||||||
keyDesc *signrpc.KeyDescriptor) {
|
keyDesc *signrpc.KeyDescriptor) {
|
||||||
|
|
||||||
ctxb := context.Background()
|
|
||||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
pubKeyHash := btcutil.Hash160(targetPubKey.SerializeCompressed())
|
pubKeyHash := btcutil.Hash160(targetPubKey.SerializeCompressed())
|
||||||
targetAddr, err := btcutil.NewAddressWitnessPubKeyHash(
|
targetAddr, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
pubKeyHash, harnessNetParams,
|
pubKeyHash, harnessNetParams,
|
||||||
)
|
)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
targetScript, err := txscript.PayToAddrScript(targetAddr)
|
targetScript, err := txscript.PayToAddrScript(targetAddr)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
// Send some coins to the generated p2wpkh address.
|
// Send some coins to the generated p2wpkh address.
|
||||||
_, err = alice.SendCoins(ctxt, &lnrpc.SendCoinsRequest{
|
req := &lnrpc.SendCoinsRequest{
|
||||||
Addr: targetAddr.String(),
|
Addr: targetAddr.String(),
|
||||||
Amount: 800_000,
|
Amount: 800_000,
|
||||||
})
|
}
|
||||||
require.NoError(t.t, err)
|
alice.RPC.SendCoins(req)
|
||||||
|
|
||||||
// Wait until the TX is found in the mempool.
|
// Wait until the TX is found in the mempool.
|
||||||
txid, err := waitForTxInMempool(net.Miner.Client, minerMempoolTimeout)
|
txid := ht.Miner.AssertNumTxsInMempool(1)[0]
|
||||||
require.NoError(t.t, err)
|
|
||||||
|
|
||||||
targetOutputIndex := getOutputIndex(
|
targetOutputIndex := ht.GetOutputIndex(txid, targetAddr.String())
|
||||||
t, net.Miner, txid, targetAddr.String(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Clear the mempool.
|
// Clear the mempool.
|
||||||
mineBlocks(t, net, 1, 1)
|
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
|
|
||||||
// Try to spend the output now to a new p2wkh address.
|
// Try to spend the output now to a new p2wkh address.
|
||||||
p2wkhResp, err := alice.NewAddress(ctxt, &lnrpc.NewAddressRequest{
|
addrReq := &lnrpc.NewAddressRequest{Type: AddrTypeWitnessPubkeyHash}
|
||||||
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
|
p2wkhResp := alice.RPC.NewAddress(addrReq)
|
||||||
})
|
|
||||||
require.NoError(t.t, err)
|
|
||||||
|
|
||||||
p2wkhAdrr, err := btcutil.DecodeAddress(
|
p2wkhAdrr, err := btcutil.DecodeAddress(
|
||||||
p2wkhResp.Address, harnessNetParams,
|
p2wkhResp.Address, harnessNetParams,
|
||||||
)
|
)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
p2wkhPkScript, err := txscript.PayToAddrScript(p2wkhAdrr)
|
p2wkhPkScript, err := txscript.PayToAddrScript(p2wkhAdrr)
|
||||||
require.NoError(t.t, err)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
tx := wire.NewMsgTx(2)
|
tx := wire.NewMsgTx(2)
|
||||||
tx.TxIn = []*wire.TxIn{{
|
tx.TxIn = []*wire.TxIn{{
|
||||||
@@ -339,24 +318,22 @@ func assertSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
require.NoError(t.t, tx.Serialize(&buf))
|
require.NoError(ht, tx.Serialize(&buf))
|
||||||
|
|
||||||
signResp, err := alice.SignerClient.SignOutputRaw(
|
signReq := &signrpc.SignReq{
|
||||||
ctxt, &signrpc.SignReq{
|
RawTxBytes: buf.Bytes(),
|
||||||
RawTxBytes: buf.Bytes(),
|
SignDescs: []*signrpc.SignDescriptor{{
|
||||||
SignDescs: []*signrpc.SignDescriptor{{
|
Output: &signrpc.TxOut{
|
||||||
Output: &signrpc.TxOut{
|
PkScript: targetScript,
|
||||||
PkScript: targetScript,
|
Value: 800_000,
|
||||||
Value: 800_000,
|
},
|
||||||
},
|
InputIndex: 0,
|
||||||
InputIndex: 0,
|
KeyDesc: keyDesc,
|
||||||
KeyDesc: keyDesc,
|
Sighash: uint32(txscript.SigHashAll),
|
||||||
Sighash: uint32(txscript.SigHashAll),
|
WitnessScript: targetScript,
|
||||||
WitnessScript: targetScript,
|
}},
|
||||||
}},
|
}
|
||||||
},
|
signResp := alice.RPC.SignOutputRaw(signReq)
|
||||||
)
|
|
||||||
require.NoError(t.t, err)
|
|
||||||
|
|
||||||
tx.TxIn[0].Witness = wire.TxWitness{
|
tx.TxIn[0].Witness = wire.TxWitness{
|
||||||
append(signResp.RawSigs[0], byte(txscript.SigHashAll)),
|
append(signResp.RawSigs[0], byte(txscript.SigHashAll)),
|
||||||
@@ -364,30 +341,25 @@ func assertSignOutputRaw(t *harnessTest, net *lntest.NetworkHarness,
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
require.NoError(t.t, tx.Serialize(&buf))
|
require.NoError(ht, tx.Serialize(&buf))
|
||||||
|
|
||||||
_, err = alice.WalletKitClient.PublishTransaction(
|
alice.RPC.PublishTransaction(&walletrpc.Transaction{
|
||||||
ctxt, &walletrpc.Transaction{
|
TxHex: buf.Bytes(),
|
||||||
TxHex: buf.Bytes(),
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
require.NoError(t.t, err)
|
|
||||||
|
|
||||||
// Wait until the spending tx is found.
|
// Wait until the spending tx is found.
|
||||||
txid, err = waitForTxInMempool(net.Miner.Client, minerMempoolTimeout)
|
txid = ht.Miner.AssertNumTxsInMempool(1)[0]
|
||||||
require.NoError(t.t, err)
|
p2wkhOutputIndex := ht.GetOutputIndex(txid, p2wkhAdrr.String())
|
||||||
p2wkhOutputIndex := getOutputIndex(
|
|
||||||
t, net.Miner, txid, p2wkhAdrr.String(),
|
|
||||||
)
|
|
||||||
op := &lnrpc.OutPoint{
|
op := &lnrpc.OutPoint{
|
||||||
TxidBytes: txid[:],
|
TxidBytes: txid[:],
|
||||||
OutputIndex: uint32(p2wkhOutputIndex),
|
OutputIndex: uint32(p2wkhOutputIndex),
|
||||||
}
|
}
|
||||||
assertWalletUnspent(t, alice, op, "")
|
ht.AssertUTXOInWallet(alice, op, "")
|
||||||
|
|
||||||
// Mine another block to clean up the mempool and to make sure the spend
|
// Mine another block to clean up the mempool and to make sure the
|
||||||
// tx is actually included in a block.
|
// spend tx is actually included in a block.
|
||||||
mineBlocks(t, net, 1, 1)
|
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deriveCustomizedKey uses the family and index to derive a public key from
|
// deriveCustomizedKey uses the family and index to derive a public key from
|
||||||
|
|||||||
@@ -4,10 +4,6 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
var allTestCases = []*testCase{
|
var allTestCases = []*testCase{
|
||||||
{
|
|
||||||
name: "sign output raw",
|
|
||||||
test: testSignOutputRaw,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "sign verify message",
|
name: "sign verify message",
|
||||||
test: testSignVerifyMessage,
|
test: testSignVerifyMessage,
|
||||||
|
|||||||
Reference in new issue
Block a user