diff --git a/qa/rpc-tests/feature_fedpeg.py b/qa/rpc-tests/feature_fedpeg.py index 282d8de8c7..a6c03540a5 100755 --- a/qa/rpc-tests/feature_fedpeg.py +++ b/qa/rpc-tests/feature_fedpeg.py @@ -240,25 +240,50 @@ class FedPegTest(BitcoinTestFramework): if sidechain.gettransaction(pegtxid1)["confirmations"] != 6: raise Exception("Peg-in should be back to 6 confirms.") - # Do many claims in mempool - n_claims = 5 + # Do multiple claims in mempool + n_claims = 6 print("Flooding mempool with many small claims") pegtxs = [] sidechain.generate(101) + # Do mixture of raw peg-in and automatic peg-in tx construction + # where raw creation is done on another node for i in range(n_claims): addrs = sidechain.getpeginaddress() txid = parent.sendtoaddress(addrs["mainchain_address"], 1) - parent.generate(12) + parent.generate(1) proof = parent.gettxoutproof([txid]) raw = parent.getrawtransaction(txid) - pegtxs += [sidechain.claimpegin(raw, proof)] + if i % 2 == 0: + parent.generate(11) + pegtxs += [sidechain.claimpegin(raw, proof)] + else: + # The raw API doesn't check for the additional 2 confirmation buffer + # So we only get 10 confirms then send off. Miners will add to block anyways. + + # Don't mature whole way yet to test signing immature peg-in input + parent.generate(8) + # Wallet in sidechain2 gets funds instead of sidechain + raw_pegin = sidechain2.createrawpegin(raw, proof, addrs["claim_script"])["hex"] + # First node should also be able to make a valid transaction with or without 3rd arg + # since this wallet originated the claim_script itself + sidechain.createrawpegin(raw, proof, addrs["claim_script"]) + sidechain.createrawpegin(raw, proof) + signed_pegin = sidechain.signrawtransaction(raw_pegin) + assert(signed_pegin["complete"]) + assert("warning" in signed_pegin) # warning for immature peg-in + # fully mature them now + parent.generate(1) + pegtxs += [sidechain.sendrawtransaction(signed_pegin["hex"])] self.sync_all() sidechain2.generate(1) - for pegtxid in pegtxs: - tx = sidechain.gettransaction(pegtxid) + for i, pegtxid in enumerate(pegtxs): + if i % 2 == 0: + tx = sidechain.gettransaction(pegtxid) + else: + tx = sidechain2.gettransaction(pegtxid) if "confirmations" not in tx or tx["confirmations"] == 0: raise Exception("Peg-in confirmation has failed.") diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index f821938738..b26bbd8521 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1244,6 +1244,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) " }\n" " ,...\n" " ]\n" + " \"warning\" : \"text\" (string) Warning that a peg-in input signed may be immature. This could mean lack of connectivity to or misconfiguration of the bitcoind." "}\n" "\nExamples:\n" @@ -1411,6 +1412,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request) // Script verification errors UniValue vErrors(UniValue::VARR); + // Track an immature peg-in that's otherwise valid, give warning + bool immature_pegin = false; + // Use CTransaction for the constant parts of the // transaction to avoid rehashing. const CTransaction txConst(mergedTx); @@ -1421,10 +1425,14 @@ UniValue signrawtransaction(const JSONRPCRequest& request) if (!txin.m_is_pegin && (coins == NULL || !coins->IsAvailable(txin.prevout.n))) { TxInErrorToJSON(txin, vErrors, "Input not found or already spent"); continue; - } else if (txin.m_is_pegin && (txConst.wit.vtxinwit.size() <= i || !IsValidPeginWitness(txConst.wit.vtxinwit[i].m_pegin_witness, txin.prevout))) { + } else if (txin.m_is_pegin && (txConst.wit.vtxinwit.size() <= i || !IsValidPeginWitness(txConst.wit.vtxinwit[i].m_pegin_witness, txin.prevout, false))) { TxInErrorToJSON(txin, vErrors, "Peg-in input has invalid proof."); continue; } + // Report warning about immature peg-in though + if(txin.m_is_pegin && !IsValidPeginWitness(txConst.wit.vtxinwit[i].m_pegin_witness, txin.prevout, true)) { + immature_pegin = true; + } const CScript& prevPubKey = txin.m_is_pegin ? GetPeginOutputFromWitness(txConst.wit.vtxinwit[i].m_pegin_witness).scriptPubKey : coins->vout[txin.prevout.n].scriptPubKey; const CConfidentialValue& amount = txin.m_is_pegin ? GetPeginOutputFromWitness(txConst.wit.vtxinwit[i].m_pegin_witness).nValue : coins->vout[txin.prevout.n].nValue; @@ -1455,6 +1463,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request) if (!vErrors.empty()) { result.push_back(Pair("errors", vErrors)); } + if (immature_pegin) { + result.push_back(Pair("warning", "Possibly immature peg-in input(s) detected, signed anyways.")); + } AuditLogPrintf("%s : signrawtransaction %s\n", getUser(), EncodeHexTx(mergedTx)); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 27863d1cc6..5807fa48bf 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3539,7 +3539,7 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef "3. \"claim_script\" (string, optional) The witness program generated by getpeginaddress. Only needed if not in wallet.\n" "\nResult:\n" "{\n" - " \"transaction\" (string) Raw transaction in hex\n" + " \"hex\" (string) Raw transaction in hex\n" " \"mature\" (bool) Whether the peg-in is mature (only included when validating peg-ins)\n" "\nExamples:\n" + HelpExampleCli("createrawpegin", "\"0200000002b80a99d63ca943d72141750d983a3eeda3a5c5a92aa962884ffb141eb49ffb4f000000006a473044022031ffe1d76decdfbbdb7e2ee6010e865a5134137c261e1921da0348b95a207f9e02203596b065c197e31bcc2f80575154774ac4e80acd7d812c91d93c4ca6a3636f27012102d2130dfbbae9bd27eee126182a39878ac4e117d0850f04db0326981f43447f9efeffffffb80a99d63ca943d72141750d983a3eeda3a5c5a92aa962884ffb141eb49ffb4f010000006b483045022100cf041ce0eb249ae5a6bc33c71c156549c7e5ad877ae39e2e3b9c8f1d81ed35060220472d4e4bcc3b7c8d1b34e467f46d80480959183d743dad73b1ed0e93ec9fd14f012103e73e8b55478ab9c5de22e2a9e73c3e6aca2c2e93cd2bad5dc4436a9a455a5c44feffffff0200e1f5050000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87e86cbe00000000001976a914a25fe72e7139fd3f61936b228d657b2548b3936a88acc0020000\", \"00000020976e918ed537b0f99028648f2a25c0bd4513644fb84d9cbe1108b4df6b8edf6ba715c424110f0934265bf8c5763d9cc9f1675a0f728b35b9bc5875f6806be3d19cd5b159ffff7f2000000000020000000224eab3da09d99407cb79f0089e3257414c4121cb85a320e1fd0f88678b6b798e0713a8d66544b6f631f9b6d281c71633fb91a67619b189a06bab09794d5554a60105\" \"0014058c769ffc7d12c35cddec87384506f536383f9c\"")