I worked pretty hard this week to refactor how NBitcoin sign transactions.
Actually I got inspired by
http://bitcore.io/blog/articles/transactionbuilder/.
Now you get a better, shinier, and C# version of that with Stealth Payment support and soon colored coin.
var stealthKeys = Enumerable.Range(0, 3).Select(_ => new Key()).ToArray();
var scanKey = new Key();
var satoshi = new BitcoinStealthAddress(scanKey.PubKey, stealthKeys.Select(k => k.PubKey).ToArray(), 2, new BitField(3, 5), Network.Main);
var bob = new Key();
var coins = new Coin[] {
new Coin()
{
Outpoint = RandOutpoint(),
TxOut = new TxOut("1.00",bob.PubKey.ID)
} };
//Bob sends money to satoshi
TransactionBuilder builder = new TransactionBuilder();
var tx =
builder
.AddCoins(coins)
.AddKeys(bob)
.SendTo(satoshi, "1.00")
.BuildTransaction(true);
Assert.True(builder.Verify(tx));
//Satoshi scans a StealthCoin in the transaction with his scan key
var stealthCoin = StealthCoin.Find(tx, satoshi, scanKey);
Assert.NotNull(stealthCoin);
//Satoshi sends back the money to Bob
builder = new TransactionBuilder();
tx =
builder
.AddCoins(stealthCoin)
.AddKeys(stealthKeys)
.AddKeys(scanKey)
.SendTo(bob.PubKey.ID, "1.00")
.BuildTransaction(true);
Assert.True(builder.Verify(tx)); //Signed !
//Same scenario, Satoshi wants to send money back to Bob
//However, his keys are spread on two machines
//He partially sign on the 1st machine
builder = new TransactionBuilder();
tx =
builder
.AddCoins(stealthCoin)
.AddKeys(stealthKeys.Skip(2).ToArray()) //Only one Stealth Key
.AddKeys(scanKey)
.SendTo(bob.PubKey.ID, "1.00")
.BuildTransaction(true);
Assert.False(builder.Verify(tx)); //Not fully signed
//Then he partially sign on the 2nd machine
builder = new TransactionBuilder();
tx =
builder
.AddCoins(stealthCoin)
.AddKeys(stealthKeys[0]) //Other key
.AddKeys(scanKey)
.SignTransaction(tx);
Assert.True(builder.Verify(tx)); //Fully signed !
The process for other type of inputs are essentially the same.
The only difference is that for non-P2SH coins, you need to pass a Coin (outpoint,txout)
For a P2SH coin, you need to pass a ScriptCoin to the builder (outpoint,txout,amount)
For stealth, you pass a StealthCoin as above example.
You can chain other SendTo() if you have other non stealth payment to do.
TransactionBuilder allows you to mix multiple type of script. Given the right set of keys and coins, he will sign all what he can.
TransactionBuilder also select automatically the coins to cover the sum of money send with SendTo() + fees. (You can provide your own algorithm with interface ICoinSelector though)
Update : Article about it at
http://www.codeproject.com/Articles/835098/NBitcoin-Build-Them-All