multisig partially signed transaction example
VahidShir opened this issue · comments
Vahid Shirmohammadi commented
Could you please show me a sample code of how to sign and create partially signed bitcoin transaction given following scenario?
(I followed a tutorial here but it was too old and at that time psbt protocol wasn't introduced).
In a 2-3 multisig I'm a cosigner and would like to sign a transaction by sending an amount of bitcoin say(0.1 BTC to some address) and then deliver the partially signed psbt content (or .psbt file) to other co-signers? The other co-signers have setup this multisig setup on their electrum wallet (I gave them my xpub).
//seed generated for testing
string mySeed = "amused raven leopard happy actor car emotion brisk pretty canvas bomb bench vague off duck marine wasp bar boring enact confirm cover admit ridge";
string coSigner2Xpub = "tpub.......";
string coSigner3Xpub = "tpub.......";
Mnemonic mnemonic = new Mnemonic(mySeed );
var mySeedByte = mnemonic.DeriveSeed();
string path = "m/44'/1'/0'/0";
KeyPath keyPath = new KeyPath(path);
var network = Network.TestNet;
ExtKey myExtKey = ExtKey.CreateFromSeed(mySeedByte).Derive(keyPath);
ExtPubKey myXpubKey = myExtKey.Neuter();
BitcoinExtPubKey myBitcoinExtPubKey = myXpubKey.GetWif(network);
var myXpub = myBitcoinExtPubKey.ToString(); // I already sent this xpub of mine to other cosigners
// Here is the sample code taken from the tutorial:
var network = Network.TestNet;
Key bob = new Key();
Key alice = new Key();
Key satoshi = new Key();
var scriptPubKey = PayToMultiSigTemplate
.Instance
.GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey });
var received = Transaction.Create(network);
received.Outputs.Add(Money.Coins(1.0m), scriptPubKey);
Coin coin = received.Outputs.AsCoins().First();
BitcoinAddress nico = new Key().PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main);
TransactionBuilder builder = Network.Main.CreateTransactionBuilder();
Transaction unsigned =
builder
.AddCoins(coin)
.Send(nico, Money.Coins(1.0m))
.BuildTransaction(sign: false);
Transaction aliceSigned =
builder
.AddCoins(coin)
.AddKeys(alice)
.SignTransaction(unsigned);
//Transaction bobSigned =
// builder
// .AddCoins(coin)
// .AddKeys(bob)
// //At this line, SignTransaction(unSigned) has the identical functionality with the SignTransaction(aliceSigned).
// //It's because unsigned transaction has already been signed by Alice privateKey from above.
// .SignTransaction(aliceSigned);
//Transaction fullySigned =
// builder
// .AddCoins(coin)
// .CombineSignatures(aliceSigned, bobSigned);
// Here I only signed as Alice since we wanna send the psbt to Bob so that he signs this psbt (and finalizing) then
// either broadcasting it himself or send the psbt back to us and we broadcast it.
var psbt = PSBT.FromTransaction(aliceSigned, network);
//This line throws the exception:
//NBitcoin.PSBTException: 'Input 0: Neither witness_utxo nor non_witness_output is set'
psbt.Finalize();