Going by the example here: https://bitcoinj.github.io/working-with-contracts
I believe I've done everything correctly. Yet my program fails either to propagate correctly or because of a tx error and I cannot determine why
A few things I believe to be the reason
1) My peergroup.broadcastTransaction(spendTx) is not broadcasting properly 2) A malformed raw transaction or scriptsig ( I assume it is this, but again, no errors) 3) Generally not understanding the best method of linking outputs to inputs and signing them appropriately (for instance, do I use UTXO class, or TransactionSignature) 3) Trying to spend funds from a watched address. I have the necessary keys to unlock the UTXO's but I would like to see if I can spend the funds without the use of the wallet class 4) Multisig support in general for bitcoinj is lacking or incomplete. i hope it's not this as I would really like to get this working. But -- I don't think this is the biggest issue because I ran the unit tests and they still all check out clean.
A step through the code to be thorough:
Create 3 ECKeys for a 2-of-3 multisig contract, put them into a list, create a redeem script that sorts keys in lexicographical order and writes a m-of-n multisigoutputscript, then instantiate a Transaction object and assign it as the OUTPUT that I will be using as my INPUT (amount + redeemscript) AKA the UTXO that I will be spending (EDIT: Quick mention. The ECKeys I'm really using are hardcoded values that I made a while ago, these are for illustration purposes. I also should mention that this is a P2SH multisig, not the raw non-standard multisig.
ECKey keyA = new ECKey();
ECKey keyB = new ECKey();
ECKey keyC = new ECKey();
List<ECKey> keys = ImmutableList.of(key1, key2, key3);
Script script = ScriptBuilder.createRedeemScript(2, keys);
Script scriptPubKey = ScriptBuilder.createP2SHOutputScript(script);
Transaction contract = new Transaction(params);
TransactionOutput multiSigOutput = contract.addOutput(Coin.valueOf(50000), scriptPubKey);
Create a second transaction object that I will be using to assemble the output script AKA the (value + destination) address that i will be signing my UTXO over to. Also where the sigHash is signed by 2 of my keys and added to the scriptSig of the transaction
Transaction spendTx = new Transaction(params);
Address address = Address.fromBase58(params, "19EfMrs5WkcvtBBnuEqP6v1yppeWww61Kc");
Script outputScript = ScriptBuilder.createOutputScript(address);
spendTx.addOutput(multiSigOutput.getValue(), outputScript);
// System.out.println(spendTx.getOutputs());
TransactionInput input = spendTx.addInput(multiSigOutput);
now manually sign the inputs...(signatures are in same order as they are in script)
//sign transaction manually
Sha256Hash sigHash = spendTx.hashForSignature(0, script, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = list.get(0).sign(sigHash);
ECKey.ECDSASignature signature1 = list.get(1).sign(sigHash);
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
TransactionSignature txSig1 = new TransactionSignature(signature1, Transaction.SigHash.ALL, false);
...now create multisiginputscript, validate and broadcast tx
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript((ImmutableList.of(txSig, txSig1)));
// System.out.println(inputScript);
input.setScriptSig(inputScript);
input.verify(multiSigOutput);
peerGroup.broadcastTransaction(spendTx);
System.out.println(kit.peerGroup().getConnectedPeers());
System.out.println("transaction broadcasted");
ok...this doesn't propagate, but the verification checks out. and I don't even know if it's so much a network problem as it is a code problem because when I change the value in the output script to > the balance of the UTXO it doesn't throw a InsufficientMoneyException like I imagine it should. I'd show some error logs but there aren't any. The only error is when I change the createmultisiginputscript to createP2SHmultisiginputscript, the console puts out a non-null nulldummy error which I also have problems fixing, so I've never been able to know if changing to that method is the correct fix either. I think I set up the connection to the peergroup correctly as well
File chainFile = new File(this.getFilesDir(), "test.spvchain");
System.out.println("does chainfile exist?" + chainFile.exists());
if(chainFile.exists()) {
try {
SPVBlockStore chainStore = new SPVBlockStore(params, chainFile);
BlockChain chain = new BlockChain(params, chainStore);
peerGroup = new PeerGroup(params, chain);
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.startAsync();
} catch (BlockStoreException e) {
e.printStackTrace();
}
So I don't really get it... I've come to the conclusion my understanding is off somehow. Sorry for the confusing long post. It's been days. Can anyone help?
EDIT: Here's the raw transaction
In hex: 0100000001d917c0a19e19fa1cf2314baf037fdf952877daa4da845ab35d44ef33b45838c300000000fc00473044022022b97b9372d35acaea70f3735dee290f5697cab7b5d6be6f7cdfe31139fba4f90220651091b83570843d4fe8afe02d81417194908b0f6af6f8f3b8f1ad020592409f01473044022036eff4f54b8bf3f834f7bb6e417a04a6a696047f5c75a896c6f9b624ad87680a02200bf2115b64b3b15647178b69151d4588d8a4ade16a4d66e375d0e1265c79fad6014c695221025ab78e076801b45ccb2172bce562103cce1714edbeb02ce6123ce1235eb08c762102d1b74577050b696d5886a7afa61d099ea7ab0a3797766f9819dbd72526b0ce512103facf04db5d9bee657151e30c21e839489c326a277891ebcf75b736ec1e17fc1f53aeffffffff0150c30000000000001976a9145a566f4eda18e818b8d5ca04ee7c5fa3cfbf0e0088ac00000000
In logs:
fbb119d8990cd3912a9ec0118fe3ad8ad61a8388e4a13dd342d9eb67aacfdc65
01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: in 0[] PUSHDATA(71)[3044022022b97b9372d35acaea70f3735dee290f5697cab7b5d6be6f7cdfe31139fba4f90220651091b83570843d4fe8afe02d81417194908b0f6af6f8f3b8f1ad020592409f01] PUSHDATA(71)[3044022036eff4f54b8bf3f834f7bb6e417a04a6a696047f5c75a896c6f9b624ad87680a02200bf2115b64b3b15647178b69151d4588d8a4ade16a4d66e375d0e1265c79fad601] PUSHDATA1[5221025ab78e076801b45ccb2172bce562103cce1714edbeb02ce6123ce1235eb08c762102d1b74577050b696d5886a7afa61d099ea7ab0a3797766f9819dbd72526b0ce512103facf04db5d9bee657151e30c21e839489c326a277891ebcf75b736ec1e17fc1f53ae] 0.0005 BTC 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: outpoint:c33858b433ef445db35a84daa4da772895df7f03af4b31f21cfa199ea1c017d9:0 hash160:6d49586d7529626aaab49812bcd7839aee7e5800 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: out DUP HASH160 PUSHDATA(20)[5a566f4eda18e818b8d5ca04ee7c5fa3cfbf0e00] EQUALVERIFY CHECKSIG 0.0005 BTC 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: fee 0.00 BTC/kB, 0.00 BTC for 337 bytes 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: prps UNKNOWN