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.
1
// Create a fake transaction
2
var bob = new Key();
3
var alice = new Key();
4
5
Script bobAlice =
6
PayToMultiSigTemplate.Instance.GenerateScriptPubKey(
7
2,
8
bob.PubKey, alice.PubKey);
9
10
var init = Network.Main.CreateTransaction();
11
init.Outputs.Add(Money.Coins(1m), bob.PubKey); // P2PK
12
init.Outputs.Add(Money.Coins(1m), alice.PubKey.Hash); // P2PKH
13
init.Outputs.Add(Money.Coins(1m), bobAlice);
Copied!
Now let’s say they want to use the coins of this transaction to pay Satoshi.
1
var satoshi = new Key();
Copied!
First they have to get their Coins.
1
Coin[] coins = init.Outputs.AsCoins().ToArray();
2
Coin bobCoin = coins[0];
3
Coin aliceCoin = coins[1];
4
Coin bobAliceCoin = coins[2];
Copied!
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.
1
var builder = Network.Main.CreateTransactionBuilder();
2
Transaction tx = builder
3
.AddCoins(bobCoin)
4
.AddKeys(bob)
5
.Send(satoshi, Money.Coins(0.2m))
6
.SetChange(bob)
7
.Then()
8
.AddCoins(aliceCoin)
9
.AddKeys(alice)
10
.Send(satoshi, Money.Coins(0.3m))
11
.SetChange(alice)
12
.Then()
13
.AddCoins(bobAliceCoin)
14
.AddKeys(bob, alice)
15
.Send(satoshi, Money.Coins(0.5m))
16
.SetChange(bobAlice)
17
.SendFees(Money.Coins(0.0001m))
18
.BuildTransaction(sign: true);
Copied!
Then you can verify it is fully signed and ready to send to the network.
1
Console.WriteLine(builder.Verify(tx)); // True
Copied!
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.
1
init = Network.Main.CreateTransaction();
2
init.Outputs.Add(Money.Coins(1.0m), bobAlice.Hash);
3
4
coins = init.Outputs.AsCoins().ToArray();
5
ScriptCoin bobAliceScriptCoin = coins[0].ToScriptCoin(bobAlice);
Copied!
Then the signature:
1
builder = Network.Main.CreateTransactionBuilder();
2
tx = builder
3
.AddCoins(bobAliceScriptCoin)
4
.AddKeys(bob, alice)
5
.Send(satoshi, Money.Coins(0.9m))
6
.SetChange(bobAlice.Hash)
7
.SendFees(Money.Coins(0.0001m))
8
.BuildTransaction(true);
9
Console.WriteLine(builder.Verify(tx)); // True
Copied!
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:
1
Key scanKey = new Key();
2
BitcoinStealthAddress darkAliceBob =
3
new BitcoinStealthAddress
4
(
5
scanKey: scanKey.PubKey,
6
pubKeys: new[] { alice.PubKey, bob.PubKey },
7
signatureCount: 2,
8
bitfield: null,
9
network: Network.Main
10
);
Copied!
Let’s say someone sent this transaction:
1
//Someone sent to darkAliceBob
2
init = Network.Main.CreateTransaction();
3
darkAliceBob
4
.SendTo(init, Money.Coins(1.0m));
Copied!
The scanner will detect the StealthCoin:
1
//Get the stealth coin with the scanKey
2
StealthCoin stealthCoin
3
= StealthCoin.Find(init, darkAliceBob, scanKey);
Copied!
And forward it to bob and alice, who will sign:
1
//Spend it
2
tx = builder
3
.AddCoins(stealthCoin)
4
.AddKeys(bob, alice, scanKey)
5
.Send(satoshi, Money.Coins(0.9m))
6
.SetChange(bobAlice.Hash)
7
.SendFees(Money.Coins(0.0001m))
8
.BuildTransaction(true);
9
Console.WriteLine(builder.Verify(tx)); // True
Copied!
Note: You need the scanKey for spending a StealthCoin
Copy link