MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.88k stars 848 forks source link

How to add multiple recipients to a transaction? #985

Open starkdm opened 3 years ago

starkdm commented 3 years ago

The code below demonstrates creating a transaction, but with only one recipient (TransactionBuilder.Send). How to add multiple recipients to a transaction?

TransactionBuilder builder = Network.TestNet.CreateTransactionBuilder();
builder.AddCoins(unspentCoins);
builder.SendEstimatedFees(new FeeRate(rate));
builder.AddKeys(privateKey);
builder.SetChange(address);
builder.Send(receiver, new Money(money));
Transaction transaction = builder.BuildTransaction(true);
ArtjomP commented 3 years ago

Just add a new Send line builder.Send(receiver2, new Money(money2))

starkdm commented 3 years ago

The previous recipient will be replaced. As a result, one output is obtained. Check it.

ArtjomP commented 3 years ago

Strange. It works well for me. Check the Outputs of the built transaction

starkdm commented 3 years ago

Apparently the problem is that I set a very small output value. If the value is less than 294 satoshi, TransactionBuilder does not add a transaction output. Why is there such a limitation?

yahiheb commented 3 years ago

For P2WPKH (native segwit) outputs, 293 satoshis or smaller are being considered dust

https://bitcoin.stackexchange.com/questions/10986/what-is-meant-by-bitcoin-dust

starkdm commented 3 years ago

Thanks!

knocte commented 3 years ago

I wonder if this should fail with an exception named AmountLessThanDustException or something, instead of failing silently?

lontivero commented 3 years ago

It doesn't fail silently, it is configured to work in that way. You can switch the DustPrevention to false to make it work in the other way.

knocte commented 3 years ago

DustPrevention=true fails silently and DustPrevention=false doesn't throw an exception when using less than dust. To me, it means both options fail silently. There should be a way for the developer to know if dust limit was violated or not without having to check if number of inputs didn't increase after adding one.

knocte commented 3 years ago

@NicolasDorier how about a PR that changes that setting from bool to an enum like:

enum DustPrevention {
    DiscardInputs, // equivalent to "true", the current default
    Throw, // would throw an exception if input added is smaller than dust
    None
}