Ifetayo (OP)
Newbie
Offline
Activity: 1
Merit: 0
|
|
September 04, 2015, 10:11:05 AM Last edit: September 04, 2015, 06:11:39 PM by Ifetayo |
|
Hi guys, I am having issues setting up a multisig transaction with bitcoinj on my regtest network. I am running the latest bitcoinj lib. Please see the code below. The program is a 2 of 2 multisig payment. I use the WalletAppkit. The whole flow of the app is - I have 3 parties sender, intermediary, and receiver. - Intermediary and receiver send pubkey to sender. - Sender get two public keys from other two users on the regtest network, they are hard coded into the program for test convenience. - Sender forms a multisig transaction with the pubkey of the other two users, then broadcasts. - Intermediary gets the transaction, signs it and sends its signature to receiver - Receiver gets the sig of intermediary, signs the transaction with it's sig and intermediary's - Then it shows money has been gotten Problem - let say I have 5btc in the sender wallet, I then send 1btc to the receiver. On the receiver side instead of 1btc being put in the wallet I get the 3.99btc (that is the receiver gets the balance of the sender after mining fees). It's rather a strange behavior. - secondly it works sometimes the correct amount gets sent to the receiver but I am not able to send the amount. Thank you for your anticipated help. Please see my code below //....relevant imports
public class Bitsender {
NetworkParameters params = RegTestParams.get(); WalletAppKit kit = new WalletAppKit(params, new File("."),"sender-wallet" ); public void startUp(){ System.out.println("Setting things up.."); kit.connectToLocalHost(); kit.startAsync(); kit.awaitRunning(); WalletListener wlistener = new WalletListener(); kit.wallet().addEventListener(wlistener); } private void receive() { System.out.println("Feed me: " + kit.wallet().freshReceiveAddress().toString()); } public void getBal(){ System.out.println("Sender Balance is " + kit.wallet().getBalance()); } private void send(String address) throws AddressFormatException, InsufficientMoneyException { //this are the byte rep of the two multisig keys byte[] reckey = new byte[]{2,127,-81,126,111,23,-36,124,-79,-15,83,56,-52,18,58,-80,-100,-120,9,57,-98,99,-96,29,10,-19,-74,-84,-32,43,19,9,111}; byte[] intkey = new byte[]{3,-27,73,-95,-86,-98,70,-51,-34,99,53,8,-5,127,59,-22,-124,-76,-112,49,-62,61,-51,-42,107,88,-26,-100,-23,62,-118,-41,80}; //convert them to pubkyes ECKey receiverkey = new ECKey(null, reckey); ECKey intermediarykey = new ECKey(null, intkey); //create a transaction Transaction contract = new Transaction(params); //form a list of keys to be added to multisig script List<ECKey> keys = ImmutableList.of(receiverkey, intermediarykey); //construct script with keys Script script = ScriptBuilder.createMultiSigOutputScript(2, keys); //set amount to be sent Coin amount = Coin.parseCoin("10");//.valueOf(0, 80); //form an output and add the amount and script contract.addOutput(amount, script); System.out.println("Value to be sent " +contract.getOutput(0).getValue()); //adding input to the transaction from the wallet Wallet.SendRequest req = Wallet.SendRequest.forTx(contract); kit.wallet().completeTx(req); kit.wallet().signTransaction(req);
//kit.wallet().sendCoins(req); String sscript = new Gson().toJson(script); System.out.println("Script for this transaction is-----" + "\n" + sscript); System.out.println("End of script"); byte[] trx = contract.bitcoinSerialize(); String strx = new Gson().toJson(trx); System.out.println("Transaction is-----" + "\n" + strx); System.out.println("End of transaction"); kit.peerGroup().broadcastTransaction(req.tx); } /** * @param args the command line arguments */ public static void main(String[] args) throws IOException, AddressFormatException, InsufficientMoneyException { System.out.println("Sender Client"); String userInput = ""; Bitsender sender = new Bitsender(); sender.startUp(); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (!"quit".equals(userInput = in.readLine())) { if(userInput.equals("receive")){ sender.receive(); } else if(userInput.equals("bal")){ sender.getBal(); } else if(userInput.equals("send")){ //get the address of the bitreceiver sender.send(userInput); //sender.send(userInput.split(" ")[1]); } } } }
//...relevant imports public class Bitreceiver {
NetworkParameters params = RegTestParams.get(); WalletAppKit kit = new WalletAppKit(params, new File("."),"receiver-wallet" ); public void startUp(){ System.out.println("Setting things up.."); //kit.connectToLocalHost(); kit.startAsync(); kit.awaitRunning(); WalletListener wlistener = new WalletListener(); kit.wallet().addEventListener(wlistener); } public void getBal(){ System.out.println("Balance is " + kit.wallet().getBalance()); } private void receive() { //System.out.println("Feed me: " + kit.wallet().getActiveKeychain().getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).toAddress(params)); ECKey key = kit.wallet().freshReceiveKey();//.freshReceiveAddress(); Address addr = key.toAddress(params); byte[] pubkey = key.getPubKey(); String spk = new Gson().toJson(pubkey); System.out.println("Feed me address: " + addr.toString()); System.out.println("Feed me public key: " + spk); } private void claim(){ //System.out.println(kit.wallet().getWalletTransactions().toString()); byte[] reckey = new byte[]{2,127,-81,126,111,23,-36,124,-79,-15,83,56,-52,18,58,-80,-100,-120,9,57,-98,99,-96,29,10,-19,-74,-84,-32,43,19,9,111}; byte[] intkey = new byte[]{3,-27,73,-95,-86,-98,70,-51,-34,99,53,8,-5,127,59,-22,-124,-76,-112,49,-62,61,-51,-42,107,88,-26,-100,-23,62,-118,-41,80}; String sint = "{\"r\":95659142858888513941404554021932981678862401841800158047860591604698882661844,\"s\":44245425850115539565526070211043699757053575051384836017709636920266660223817}"; ECKey.ECDSASignature intsig = new Gson().fromJson(sint, ECKey.ECDSASignature.class); ECKey receiverkey = kit.wallet().getActiveKeychain().findKeyFromPubKey(reckey); byte[] contractbyte = new byte[]{1,0,0,0,1,-65,50,31,-50,1,92,17,17,116,-30,-68,80,43,-114,-56,89,116,-58,-65,-46,-111,6,-102,-43,-69,82,41,-46,7,-6,-94,75,1,0,0,0,106,71,48,68,2,32,70,5,-15,48,-90,-94,-56,-21,90,-23,97,65,106,-86,52,-101,-39,34,45,-103,75,35,123,65,4,-64,24,97,-47,-55,-95,50,2,32,10,48,-59,-72,31,-17,49,-104,-12,-115,96,109,-18,78,82,80,5,-105,33,94,83,51,-41,41,-124,-80,-76,-40,11,-35,0,59,1,33,3,-121,-54,-90,-3,-49,-25,21,-89,4,-19,111,-125,-12,-76,4,71,90,-117,-102,92,104,-103,109,-98,3,-49,100,23,125,102,-54,-120,-1,-1,-1,-1,2,0,-54,-102,59,0,0,0,0,71,82,33,2,127,-81,126,111,23,-36,124,-79,-15,83,56,-52,18,58,-80,-100,-120,9,57,-98,99,-96,29,10,-19,-74,-84,-32,43,19,9,111,33,3,-27,73,-95,-86,-98,70,-51,-34,99,53,8,-5,127,59,-22,-124,-76,-112,49,-62,61,-51,-42,107,88,-26,-100,-23,62,-118,-41,80,82,-82,96,85,-51,29,0,0,0,0,25,118,-87,20,-24,119,-65,42,-114,-21,-75,-74,-64,83,-94,31,-104,-33,-59,47,9,42,112,-95,-120,-84,0,0,0,0}; Transaction contract = new Transaction(params, contractbyte); contract.verify(); TransactionOutput multisigOutput = contract.getOutput(1); Script multisigScript = multisigOutput.getScriptPubKey(); Coin value = multisigOutput.getValue(); //byte[] contractbyte = new byte[]{1,0,0,0,1,75,-53,74,65,97,96,55,-110,-23,-44,-84,93,-111,-92,-107,-110,116,7,-88,32,90,-73,110,116,-2,25,-125,8,-52,-75,58,74,1,0,0,0,107,72,48,69,2,33,0,-31,-42,-97,41,115,46,-62,-78,116,80,100,17,0,121,-9,13,72,-67,9,28,72,75,-7,27,-7,-90,95,10,-11,8,-25,104,2,32,118,-15,48,-79,80,-83,-33,-115,-45,115,101,-42,105,39,96,-91,73,-2,44,51,-116,12,111,120,-104,-80,-44,97,108,62,-91,68,1,33,3,-88,94,-90,38,-41,-54,56,127,83,-118,7,15,112,98,84,-58,109,-100,-111,-90,23,-109,50,23,-108,85,-75,30,19,99,-110,-57,-1,-1,-1,-1,2,-104,-115,-46,-19,0,0,0,0,25,118,-87,20,101,93,-123,-49,-47,-23,2,-92,-22,-91,51,-49,-23,52,101,-28,-85,-13,-46,-18,-120,-84,-128,-106,-104,0,0,0,0,0,71,82,33,2,41,20,-11,-125,93,119,-120,69,101,101,11,-13,114,13,9,33,-103,-84,-127,-30,67,-74,42,-124,-120,109,33,-48,-128,27,-116,-86,33,2,-89,-31,-23,-13,-52,-51,48,-28,-45,13,-90,-105,49,104,-112,-10,-128,-72,-34,12,19,47,-9,-54,-11,98,-100,126,-21,44,38,109,82,-82,0,0,0,0}; System.out.println("Value sent " + value.value); Transaction spendtx = new Transaction(params); spendtx.addOutput(value, receiverkey); TransactionInput input = spendtx.addInput(multisigOutput); Sha256Hash sighash = spendtx.hashForSignature(0, multisigScript, Transaction.SigHash.ALL, false); ECKey.ECDSASignature recsig = receiverkey.sign(sighash); //ECKey.ECDSASignature.decodeFromDER(); //List<TransactionSignature> keys = ImmutableList.of(recsig, intsig); TransactionSignature tsrecsig = new TransactionSignature(recsig, Transaction.SigHash.ALL, false); TransactionSignature tsintsig = new TransactionSignature(intsig, Transaction.SigHash.ALL, false); Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(tsrecsig, tsintsig)); input.setScriptSig(inputScript); System.out.println(new Gson().toJson(multisigScript.toString())); //System.out.println(multisigOutput.getValue()); //input.verify(multisigOutput); kit.peerGroup().broadcastTransaction(spendtx); System.out.println(kit.wallet().getBalance()); kit.wallet().allowSpendingUnconfirmedTransactions(); } /** * @param args the command line arguments */ public static void main(String[] args) throws IOException, AddressFormatException, InsufficientMoneyException { System.out.println("Receiver Client"); String userInput = ""; Bitreceiver receiver = new Bitreceiver(); receiver.startUp(); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (!"quit".equals(userInput = in.readLine())) { if(userInput.equals("bal")){ receiver.getBal(); } else if(userInput.equals("receive")){ receiver.receive(); } else if(userInput.equals("claim")){ receiver.claim(); } else if(userInput.equals("send")){ receiver.send(); } } } }
//..relevant imports public class Bitintermediary {
NetworkParameters params = RegTestParams.get(); WalletAppKit kit = new WalletAppKit(params, new File("."),"intermediarywallet" ); public void startUp(){ System.out.println("Setting things up.."); //kit.connectToLocalHost(); kit.startAsync(); kit.awaitRunning(); WalletListener wlistener = new WalletListener(); kit.wallet().addEventListener(wlistener); //System.out.println("Send me money on: " + kit.wallet().freshReceiveAddress().toString()); } private void receive() { // System.out.println("Feed me: " + kit.wallet().freshReceiveAddress().toString()); ECKey key = kit.wallet().freshReceiveKey();//.freshReceiveAddress(); Address addr = key.toAddress(params); byte[] pubkey = key.getPubKey(); String spk = new Gson().toJson(pubkey); System.out.println("Feed me address: " + addr.toString()); System.out.println("Feed me public key: " + spk); } public void getBal(){ System.out.println("Balance is " + kit.wallet().getBalance()); } private void send(String address) throws AddressFormatException, InsufficientMoneyException { //Address to = Address.fromBase58(params, address); Address to = new Address(params, address); Coin value = Coin.parseCoin("10.00"); kit.wallet().sendCoins(kit.peerGroup(), to, value); System.out.println("Sending some coins to: " + address); } private void claim(){ byte[] reckey = new byte[]{2,127,-81,126,111,23,-36,124,-79,-15,83,56,-52,18,58,-80,-100,-120,9,57,-98,99,-96,29,10,-19,-74,-84,-32,43,19,9,111}; byte[] intkey = new byte[]{3,-27,73,-95,-86,-98,70,-51,-34,99,53,8,-5,127,59,-22,-124,-76,-112,49,-62,61,-51,-42,107,88,-26,-100,-23,62,-118,-41,80}; ECKey interkey = kit.wallet().getActiveKeychain().findKeyFromPubKey(intkey);//new ECKey(null, intkey); ECKey receiverkey = new ECKey(null, reckey); //ECKey jm = kit.wallet().isPubKeyMine(intkey);//.getActiveKeychain().findKeyFromPubKey(intkey); //kit.wallet(). //System.out.println(kit.wallet().isPubKeyMine(intkey)); System.out.println("Here \n" + kit.wallet().getActiveKeychain().findKeyFromPubKey(intkey).getPrivKey()); //ECKey key = new ECKey(); // System.out.println(interkey.getPrivKey()); byte[] contractbyte = new byte[]{1,0,0,0,1,-65,50,31,-50,1,92,17,17,116,-30,-68,80,43,-114,-56,89,116,-58,-65,-46,-111,6,-102,-43,-69,82,41,-46,7,-6,-94,75,1,0,0,0,106,71,48,68,2,32,70,5,-15,48,-90,-94,-56,-21,90,-23,97,65,106,-86,52,-101,-39,34,45,-103,75,35,123,65,4,-64,24,97,-47,-55,-95,50,2,32,10,48,-59,-72,31,-17,49,-104,-12,-115,96,109,-18,78,82,80,5,-105,33,94,83,51,-41,41,-124,-80,-76,-40,11,-35,0,59,1,33,3,-121,-54,-90,-3,-49,-25,21,-89,4,-19,111,-125,-12,-76,4,71,90,-117,-102,92,104,-103,109,-98,3,-49,100,23,125,102,-54,-120,-1,-1,-1,-1,2,0,-54,-102,59,0,0,0,0,71,82,33,2,127,-81,126,111,23,-36,124,-79,-15,83,56,-52,18,58,-80,-100,-120,9,57,-98,99,-96,29,10,-19,-74,-84,-32,43,19,9,111,33,3,-27,73,-95,-86,-98,70,-51,-34,99,53,8,-5,127,59,-22,-124,-76,-112,49,-62,61,-51,-42,107,88,-26,-100,-23,62,-118,-41,80,82,-82,96,85,-51,29,0,0,0,0,25,118,-87,20,-24,119,-65,42,-114,-21,-75,-74,-64,83,-94,31,-104,-33,-59,47,9,42,112,-95,-120,-84,0,0,0,0}; Transaction contract = new Transaction(params, contractbyte); contract.verify(); TransactionOutput multisigOutput = contract.getOutput(1); Script multisigScript = multisigOutput.getScriptPubKey(); //is the output what we expected //checkState(multisigScript.isSentToMultiSig()); Coin value = multisigOutput.getValue(); System.out.println("Value sent " + value.value); Transaction spendtx = new Transaction(params); spendtx.addOutput(value, receiverkey); spendtx.addInput(multisigOutput); //sign and send sig to receiver to claim Sha256Hash sighash = spendtx.hashForSignature(0, multisigScript, Transaction.SigHash.ALL, false); ECKey.ECDSASignature signature = interkey.sign(sighash); System.out.println(signature.toString()); String sig = new Gson().toJson(signature); System.out.println("Signature of intermediary is:\n" + sig); System.out.println("End of sig"); } public static void main(String[] args) throws IOException, AddressFormatException, InsufficientMoneyException { System.out.println("Intermediary Client"); String userInput = ""; Bitintermediary inter = new Bitintermediary(); inter.startUp(); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (!"quit".equals(userInput = in.readLine())) { if(userInput.equals("receive")){ inter.receive(); } else if(userInput.equals("bal")){ inter.getBal(); } else if(userInput.equals("claim")){ inter.claim(); } } } }
Thank you.
|