From 454ea2291925e6df5dcb4b705c18c3797357947b Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Thu, 14 Nov 2024 16:57:48 +0100 Subject: [PATCH] itest: test min relay fee bump The `testMinRelayFeeBump` itest checks that the minting transaction and a basic send obtain a fee bump when the min relay fee is increased to a value that is higher than the fee estimation. fix --- itest/send_test.go | 121 +++++++++++++++++++++++++++++++++++++ itest/test_list_on_test.go | 4 ++ 2 files changed, 125 insertions(+) diff --git a/itest/send_test.go b/itest/send_test.go index 26ed01f54..849f53d29 100644 --- a/itest/send_test.go +++ b/itest/send_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/taproot-assets/internal/test" "github.com/lightninglabs/taproot-assets/proof" "github.com/lightninglabs/taproot-assets/tapfreighter" @@ -17,7 +19,9 @@ import ( "github.com/lightninglabs/taproot-assets/taprpc/mintrpc" "github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc" unirpc "github.com/lightninglabs/taproot-assets/taprpc/universerpc" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -129,6 +133,123 @@ func testBasicSendUnidirectional(t *harnessTest) { wg.Wait() } +// testMinRelayFeeBump tests that if the fee estimation is below the min relay +// fee the feerate is bumped to the min relay fee for both the minting +// transaction and a basic asset send. +func testMinRelayFeeBump(t *harnessTest) { + var ( + ctxb = context.Background() + wg sync.WaitGroup + ) + + const numUnits = 10 + + // Subscribe to receive assent send events from primary tapd node. + events := SubscribeSendEvents(t.t, t.tapd) + + // We will mint assets using the first output and then use the second + // output for the transfer. This ensures a valid fee calculation. + initialUTXOs := []*UTXORequest{ + { + Type: lnrpc.AddressType_NESTED_PUBKEY_HASH, + Amount: 1_000_000, + }, + { + Type: lnrpc.AddressType_NESTED_PUBKEY_HASH, + Amount: 999_990, + }, + } + + // Set the initial state of the wallet of the first node. The wallet + // state will reset at the end of this test. + SetNodeUTXOs(t, t.lndHarness.Alice, btcutil.Amount(1), initialUTXOs) + defer ResetNodeWallet(t, t.lndHarness.Alice) + + // Set the min relay fee to a higher value than the fee rate that will + // be returned by the fee estimation. + lowFeeRate := chainfee.SatPerVByte(1).FeePerKWeight() + highMinRelayFeeRate := chainfee.SatPerVByte(2).FeePerKVByte() + defaultMinRelayFeeRate := chainfee.SatPerVByte(1).FeePerKVByte() + defaultFeeRate := chainfee.SatPerKWeight(3125) + t.lndHarness.SetFeeEstimateWithConf(lowFeeRate, 6) + t.lndHarness.SetMinRelayFeerate(highMinRelayFeeRate) + + // Reset all fee rates to their default value at the end of this test. + defer t.lndHarness.SetMinRelayFeerate(defaultMinRelayFeeRate) + defer t.lndHarness.SetFeeEstimateWithConf(defaultFeeRate, 6) + + // First, we'll make a normal assets with enough units to allow us to + // send it around a few times. + rpcAssets := MintAssetsConfirmBatch( + t.t, t.lndHarness.Miner().Client, t.tapd, + []*mintrpc.MintAssetRequest{issuableAssets[0]}, + ) + + genInfo := rpcAssets[0].AssetGenesis + + // Check the final fee rate of the mint TX. + rpcMintOutpoint := rpcAssets[0].ChainAnchor.AnchorOutpoint + mintOutpoint, err := wire.NewOutPointFromString(rpcMintOutpoint) + require.NoError(t.t, err) + + // We check whether the minting TX is bumped to the min relay fee. + AssertFeeRate( + t.t, t.lndHarness.Miner().Client, initialUTXOs[0].Amount, + &mintOutpoint.Hash, highMinRelayFeeRate.FeePerKWeight(), + ) + + // Now that we have the asset created, we'll make a new node that'll + // serve as the node which'll receive the assets. The existing tapd + // node will be used to synchronize universe state. + secondTapd := setupTapdHarness( + t.t, t, t.lndHarness.Bob, t.universeServer, + ) + defer func() { + require.NoError(t.t, secondTapd.stop(!*noDelete)) + }() + + // Next, we'll attempt to complete two transfers with distinct + // addresses from our main node to Bob. + currentUnits := issuableAssets[0].Asset.Amount + + // Issue a single address which will be reused for each send. + bobAddr, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{ + AssetId: genInfo.AssetId, + Amt: numUnits, + AssetVersion: rpcAssets[0].Version, + }) + require.NoError(t.t, err) + + // Deduct what we sent from the expected current number of + // units. + currentUnits -= numUnits + + AssertAddrCreated(t.t, secondTapd, rpcAssets[0], bobAddr) + + sendResp, sendEvents := sendAssetsToAddr(t, t.tapd, bobAddr) + + ConfirmAndAssertOutboundTransfer( + t.t, t.lndHarness.Miner().Client, t.tapd, sendResp, + genInfo.AssetId, + []uint64{currentUnits, numUnits}, 0, 1, + ) + + sendInputAmt := initialUTXOs[1].Amount + 1000 + AssertTransferFeeRate( + t.t, t.lndHarness.Miner().Client, sendResp, sendInputAmt, + highMinRelayFeeRate.FeePerKWeight(), + ) + + AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) + AssertSendEventsComplete(t.t, bobAddr.ScriptKey, sendEvents) + + // Close event stream. + err = events.CloseSend() + require.NoError(t.t, err) + + wg.Wait() +} + // testRestartReceiver tests that the receiver node's asset balance after a // single asset transfer does not change if the receiver node restarts. // Before the addition of this test, after restarting the receiver node diff --git a/itest/test_list_on_test.go b/itest/test_list_on_test.go index 151dd7695..e32aaeca2 100644 --- a/itest/test_list_on_test.go +++ b/itest/test_list_on_test.go @@ -81,6 +81,10 @@ var testCases = []*testCase{ name: "basic send unidirectional", test: testBasicSendUnidirectional, }, + { + name: "min relay fee bump", + test: testMinRelayFeeBump, + }, { name: "restart receiver check balance", test: testRestartReceiverCheckBalance,