Using the TransactionBuilder

You have seen how the TransactionBuilder works when you have signed your first P2SH and multi-sig transaction.
We will see how you can harness its full power, for signing more complicated transactions.
With the TransactionBuilder you can:
  • Spend any
    • P2PK, P2PKH,
    • multi-sig,
    • P2WPK, P2WSH.
  • Spend any P2SH on the previous redeem script.
  • Spend Stealth Coin (DarkWallet).
  • Issue and transfer Colored Coins (open asset, following chapter).
  • Combine partially signed transactions.
  • Estimate the final size of an unsigned transaction and its fees.
  • Verify if a transaction is fully signed.
The goal of the TransactionBuilder is to take Coins and Keys as input, and return back a signed or partially signed transaction.
The TransactionBuilder will figure out what Coin to use and what to sign by itself.
The usage of the builder is done in four steps:
  • You gather the Coins that will be spent,
  • You gather the Keys that you own,
  • You enumerate how much Money you want to send to what scriptPubKey,
  • You build and sign the transaction,
  • Optional: you give the transaction to somebody else, then he will sign or continue to build it.
Now let’s gather some Coins. For that, let us create a fake transaction with some funds on it. Let’s say that the transaction has a P2PKH, P2PK, and multi-sig coin of Bob and Alice.
// Create a fake transaction
var bob = new Key();
var alice = new Key();
Script bobAlice =
bob.PubKey, alice.PubKey);
var init = Network.Main.CreateTransaction();
init.Outputs.Add(Money.Coins(1m), bob.PubKey); // P2PK
init.Outputs.Add(Money.Coins(1m), alice.PubKey.Hash); // P2PKH
init.Outputs.Add(Money.Coins(1m), bobAlice);
Now let’s say they want to use the coins of this transaction to pay Satoshi.
var satoshi = new Key();
First they have to get their Coins.
Coin[] coins = init.Outputs.AsCoins().ToArray();
Coin bobCoin = coins[0];
Coin aliceCoin = coins[1];
Coin bobAliceCoin = coins[2];
Now let’s say bob wants to send 0.2 BTC, alice 0.3 BTC, and they agree to use bobAlice to send 0.5 BTC.
var builder = Network.Main.CreateTransactionBuilder();
Transaction tx = builder
.Send(satoshi, Money.Coins(0.2m))
.Send(satoshi, Money.Coins(0.3m))
.AddKeys(bob, alice)
.Send(satoshi, Money.Coins(0.5m))
.BuildTransaction(sign: true);
Then you can verify it is fully signed and ready to send to the network.
Console.WriteLine(builder.Verify(tx)); // True
The nice thing about this model is that it works the same way for P2SH, P2WSH, P2SH(P2WSH), and P2SH(P2PKH) except you need to create ScriptCoin.
init = Network.Main.CreateTransaction();
init.Outputs.Add(Money.Coins(1.0m), bobAlice.Hash);
coins = init.Outputs.AsCoins().ToArray();
ScriptCoin bobAliceScriptCoin = coins[0].ToScriptCoin(bobAlice);
Then the signature:
builder = Network.Main.CreateTransactionBuilder();
tx = builder
.AddKeys(bob, alice)
.Send(satoshi, Money.Coins(0.9m))
Console.WriteLine(builder.Verify(tx)); // True
For Stealth Coin, this is basically the same thing. Except that, if you remember our introduction on Dark Wallet, I said that you need a ScanKey to see the StealthCoin.
Let’s create darkAliceBob stealth address as in previous chapter:
Key scanKey = new Key();
BitcoinStealthAddress darkAliceBob =
new BitcoinStealthAddress
scanKey: scanKey.PubKey,
pubKeys: new[] { alice.PubKey, bob.PubKey },
signatureCount: 2,
bitfield: null,
network: Network.Main
Let’s say someone sent this transaction:
//Someone sent to darkAliceBob
init = Network.Main.CreateTransaction();
.SendTo(init, Money.Coins(1.0m));
The scanner will detect the StealthCoin:
//Get the stealth coin with the scanKey
StealthCoin stealthCoin
= StealthCoin.Find(init, darkAliceBob, scanKey);
And forward it to bob and alice, who will sign:
//Spend it
tx = builder
.AddKeys(bob, alice, scanKey)
.Send(satoshi, Money.Coins(0.9m))
Console.WriteLine(builder.Verify(tx)); // True
Note: You need the scanKey for spending a StealthCoin