From 65ed777e6ee63a95159145aed70fd7810284cb5c Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 15 Sep 2017 11:18:32 -0400 Subject: [PATCH] remove legacy peg-in/withdrawlocks --- qa/rpc-tests/pegging.py | 232 ------------------- src/Makefile.am | 2 +- src/Makefile.test.include | 1 - src/bench/mempool_eviction.cpp | 4 +- src/bench/verify_script.cpp | 2 +- src/bitcoin-tx.cpp | 68 +----- src/consensus/validation.h | 1 - src/policy/policy.cpp | 9 - src/policy/policy.h | 3 +- src/primitives/transaction.h | 6 - src/rpc/rawtransaction.cpp | 4 +- src/script/bitcoinconsensus.cpp | 10 +- src/script/bitcoinconsensus.h | 2 - src/script/interpreter.cpp | 265 +--------------------- src/script/interpreter.h | 61 +---- src/script/ismine.cpp | 1 - src/script/script.cpp | 145 ------------ src/script/script.h | 18 -- src/script/script_error.cpp | 20 -- src/script/script_error.h | 13 -- src/script/sigcache.h | 2 +- src/script/sign.cpp | 2 - src/script/sign.h | 2 +- src/script/standard.cpp | 9 +- src/script/standard.h | 3 +- src/test/lockedutxo_tests.cpp | 129 ----------- src/test/mempool_tests.cpp | 36 +-- src/test/multisig_tests.cpp | 16 +- src/test/script_P2SH_tests.cpp | 4 +- src/test/script_tests.cpp | 66 +++--- src/test/sigopcount_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 2 +- src/test/test_bitcoin.h | 4 +- src/test/transaction_tests.cpp | 16 +- src/txdb.cpp | 30 --- src/txdb.h | 3 - src/txmempool.cpp | 56 ++--- src/txmempool.h | 6 +- src/validation.cpp | 309 +++---------------------- src/validation.h | 10 +- src/wallet/rpcwallet.cpp | 387 -------------------------------- src/wallet/wallet.cpp | 10 +- 42 files changed, 178 insertions(+), 1793 deletions(-) delete mode 100755 qa/rpc-tests/pegging.py delete mode 100644 src/test/lockedutxo_tests.cpp diff --git a/qa/rpc-tests/pegging.py b/qa/rpc-tests/pegging.py deleted file mode 100755 index e9635212c2..0000000000 --- a/qa/rpc-tests/pegging.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python2 - -from test_framework.authproxy import AuthServiceProxy, JSONRPCException -import os -import random -import sys -import time -import subprocess -import shutil - -if len(sys.argv) != 3: - print("paths to bitcoind and sidechain daemon must be included as arguments") - sys.exit(0) -print(sys.argv[1]) -print(sys.argv[2]) - -fedpeg_key="cPxqWyf1HDGpGFH1dnfjz8HbiWxvwG8WXyetbuAiw4thKXUdXLpR" -fedpeg_pubkey="512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae" - -bitcoin_datadir="/tmp/"+''.join(random.choice('0123456789ABCDEF') for i in range(5)) -bitcoin_pass=''.join(random.choice('0123456789ABCDEF') for i in range(10)) -sidechain_datadir="/tmp/"+''.join(random.choice('0123456789ABCDEF') for i in range(5)) -sidechain_pass=''.join(random.choice('0123456789ABCDEF') for i in range(10)) -sidechain2_datadir="/tmp/"+''.join(random.choice('0123456789ABCDEF') for i in range(5)) -sidechain2_pass=''.join(random.choice('0123456789ABCDEF') for i in range(10)) - -bitcoin_port = 8000 + os.getpid()%999 -sidechain_port = bitcoin_port + 1 -sidechain2_port = bitcoin_port + 2 -sidechain1_p2p_port = bitcoin_port + 3 -sidechain2_p2p_port = bitcoin_port + 4 - -os.makedirs(bitcoin_datadir) -os.makedirs(sidechain_datadir) -os.makedirs(sidechain2_datadir) - -with open(os.path.join(bitcoin_datadir, "bitcoin.conf"), 'w') as f: - f.write("regtest=1\n") - f.write("rpcuser=bitcoinrpc\n") - f.write("rpcpassword="+bitcoin_pass+"\n") - f.write("rpcport="+str(bitcoin_port)+"\n") - f.write("discover=0\n") - f.write("listen=0\n") - f.write("testnet=0\n") - f.write("txindex=1\n") - f.write("daemon=1\n") - f.write("listen=0\n") - -with open(os.path.join(sidechain_datadir, "elements.conf"), 'w') as f: - f.write("regtest=1\n") - f.write("rpcuser=sidechainrpc\n") - f.write("rpcpassword="+sidechain_pass+"\n") - f.write("rpcport="+str(sidechain_port)+"\n") - f.write("discover=0\n") - f.write("testnet=0\n") - f.write("txindex=1\n") - f.write("fedpegscript="+fedpeg_pubkey+"\n") - f.write("daemon=1\n") - f.write("mainchainrpchost=127.0.0.1\n") - f.write("mainchainrpcport="+str(bitcoin_port)+"\n") - f.write("mainchainrpcuser=bitcoinrpc\n") - f.write("mainchainrpcpassword="+bitcoin_pass+"\n") - f.write("validatepegin=1\n") - f.write("validatepegout=0\n") - f.write("port="+str(sidechain1_p2p_port)+"\n") - f.write("connect=localhost:"+str(sidechain2_p2p_port)+"\n") - f.write("listen=1\n") - -with open(os.path.join(sidechain2_datadir, "elements.conf"), 'w') as f: - f.write("regtest=1\n") - f.write("rpcuser=sidechainrpc2\n") - f.write("rpcpassword="+sidechain2_pass+"\n") - f.write("rpcport="+str(sidechain2_port)+"\n") - f.write("discover=0\n") - f.write("testnet=0\n") - f.write("txindex=1\n") - f.write("fedpegscript="+fedpeg_pubkey+"\n") - f.write("daemon=1\n") - f.write("mainchainrpchost=127.0.0.1\n") - f.write("mainchainrpcport="+str(bitcoin_port)+"\n") - f.write("mainchainrpcuser=bitcoinrpc\n") - f.write("mainchainrpcpassword="+bitcoin_pass+"\n") - f.write("validatepegin=1\n") - f.write("validatepegout=0\n") - f.write("port="+str(sidechain2_p2p_port)+"\n") - f.write("connect=localhost:"+str(sidechain1_p2p_port)+"\n") - f.write("listen=1\n") - -try: - - # Default is 8, meaning 8+2 confirms for mempool acceptance normally - # this will require 10+2. - sidechain_args = " -peginconfirmationdepth=10 " - - # Start daemons - print("Starting daemons at "+bitcoin_datadir+", "+sidechain_datadir+" and "+sidechain2_datadir) - bitcoindstart = sys.argv[1]+"/bitcoind -datadir="+bitcoin_datadir - subprocess.Popen(bitcoindstart.split(), stdout=subprocess.PIPE) - - sidechainstart = sys.argv[2]+"/elementsd -datadir="+sidechain_datadir + sidechain_args - subprocess.Popen(sidechainstart.split(), stdout=subprocess.PIPE) - - sidechain2start = sys.argv[2]+"/elementsd -datadir="+sidechain2_datadir + sidechain_args - subprocess.Popen(sidechain2start.split(), stdout=subprocess.PIPE) - - print("Daemons started") - time.sleep(3) - - bitcoin = AuthServiceProxy("http://bitcoinrpc:"+bitcoin_pass+"@127.0.0.1:"+str(bitcoin_port)) - sidechain = AuthServiceProxy("http://sidechainrpc:"+sidechain_pass+"@127.0.0.1:"+str(sidechain_port)) - sidechain2 = AuthServiceProxy("http://sidechainrpc2:"+sidechain2_pass+"@127.0.0.1:"+str(sidechain2_port)) - print("Daemons started, making blocks to get funds") - - bitcoin.generate(101) - sidechain.generate(101) - - addr = bitcoin.getnewaddress() - - # Lockup some funds to unlock later - sidechain.sendtomainchain(addr, 50) - # Tests withdrawlock tracking in database - sidechain.generate(1) - # Tests withdrawlock in mempool - sidechain.sendtomainchain(addr, 50) - - addrs = sidechain.getpeginaddress() - txid1 = bitcoin.sendtoaddress(addrs["mainchain_address"], 24) - txid2 = bitcoin.sendtoaddress(addrs["mainchain_address"], 24) - # 10+2 confirms required to get into mempool and confirm - bitcoin.generate(11) - time.sleep(2) - proof = bitcoin.gettxoutproof([txid1]) - raw = bitcoin.getrawtransaction(txid1) - - print("Attempting peg-in") - try: - pegtxid = sidechain.claimpegin(raw, proof) - raise Exception("Peg-in should not mature enough yet, need another block.") - except JSONRPCException as e: - assert("Withdraw proof validation failed" in e.error["message"]) - pass - - # Should fail due to non-matching wallet address - try: - pegtxid = sidechain.claimpegin(raw, proof, sidechain.getnewaddress()) - raise Exception("Peg-in with non-matching address should fail.") - except JSONRPCException as e: - assert("Failed to find output in bitcoinTx to the mainchain_address" in e.error["message"]) - pass - - # 12 confirms allows in mempool - bitcoin.generate(1) - - timeout = 20 - # Both should succeed via wallet lookup for address match, and when given - pegtxid1 = sidechain.claimpegin(raw, proof) - - proof = bitcoin.gettxoutproof([txid2]) - raw = bitcoin.getrawtransaction(txid2) - pegtxid2 = sidechain.claimpegin(raw, proof, addrs["sidechain_address"]) - - while len(sidechain.getrawmempool()) != len(sidechain2.getrawmempool()): - time.sleep(1) - timeout -= 1 - if timeout == 0: - raise Exception("Peg-in has failed to propagate.") - sidechain2.generate(1) - while sidechain.getblockcount() != sidechain2.getblockcount(): - time.sleep(1) - timeout -= 1 - if timeout == 0: - raise Exception("Blocks are not propagating.") - - - tx1 = sidechain.gettransaction(pegtxid1) - tx2 = sidechain.gettransaction(pegtxid2) - - if "confirmations" in tx1 and tx1["confirmations"] > 0 and "confirmations" in tx2 and tx2["confirmations"] > 0: - print("Peg-in is confirmed: Success!") - else: - raise Exception("Peg-in confirmation has failed.") - - # Make a few large locks, then do many claims in mempool - n_locks = 10 - n_claims = 30 - - print("Flooding mempool with many small claims") - pegtxs = [] - for i in range(n_locks): - # Lockup some funds to unlock later - sidechain.sendtomainchain(addr, 50) - sidechain.generate(1) - sidechain.generate(101) - - for i in range(n_claims): - addrs = sidechain.getpeginaddress() - txid = bitcoin.sendtoaddress(addrs["mainchain_address"], 1) - bitcoin.generate(12) - proof = bitcoin.gettxoutproof([txid]) - raw = bitcoin.getrawtransaction(txid) - pegtxs += [sidechain.claimpegin(raw, proof)] - - sidechain.generate(1) - for pegtxid in pegtxs: - tx = sidechain.gettransaction(pegtxid) - if "confirmations" not in tx or tx["confirmations"] == 0: - raise Exception("Peg-in confirmation has failed.") - - print("Success!") - - # Testing sidechain info RPC - sideinfo = sidechain.getsidechaininfo() - assert sideinfo["fedpegscript"] == fedpeg_pubkey - assert sideinfo["pegged_asset"] == sidechain.dumpassetlabels()["bitcoin"] - assert sideinfo["min_peg_diff"] == "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - assert sideinfo["parent_blockhash"] == "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206" - -except JSONRPCException as e: - print("Pegging testing failed, aborting:") - print(e.error) -except Exception as e: - print("Pegging testing failed, aborting:") - print(e) - -print("Stopping daemons and cleaning up") -bitcoin.stop() -sidechain.stop() - -time.sleep(5) - -shutil.rmtree(sidechain_datadir) -shutil.rmtree(bitcoin_datadir) diff --git a/src/Makefile.am b/src/Makefile.am index 91dc08037a..6e9f51402c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -458,7 +458,7 @@ endif libelementsconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0 $(RELDFLAGS) libelementsconsensus_la_LIBADD = $(LIBSECP256K1) -libelementsconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL -DBITCOIN_SCRIPT_NO_CALLRPC +libelementsconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libelementsconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif diff --git a/src/Makefile.test.include b/src/Makefile.test.include index cdcb786d8e..095ee288fa 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -100,7 +100,6 @@ BITCOIN_TESTS =\ test/hash_tests.cpp \ test/key_tests.cpp \ test/limitedmap_tests.cpp \ - test/lockedutxo_tests.cpp \ test/withdrawspent_tests.cpp \ test/dbwrapper_tests.cpp \ test/main_tests.cpp \ diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index e99484a3a3..e0bc6d2e7d 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -16,11 +16,11 @@ static void AddTx(const CTransaction& tx, const CAmount& nFee, CTxMemPool& pool) unsigned int nHeight = 1; bool spendsCoinbase = false; unsigned int sigOpCost = 4; - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; LockPoints lp; pool.addUnchecked(tx.GetHash(), CTxMemPoolEntry( MakeTransactionRef(tx), nFee, nTime, dPriority, nHeight, - 0, spendsCoinbase, sigOpCost, lp, setWithdrawsSpent)); + 0, spendsCoinbase, sigOpCost, lp, setPeginsSpent)); } // Right now this is only testing eviction performance in an extremely small diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 22c89dc2e0..c6fdd861f2 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -81,7 +81,7 @@ static void VerifyScriptBench(benchmark::State& state) txCredit.vout[0].scriptPubKey, &txSpend.wit.vtxinwit[0].scriptWitness, flags, - MutableTransactionNoWithdrawsSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue), + MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue), &err); assert(err == SCRIPT_ERR_OK); assert(success); diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index ae28bf59d6..ba7e3cff00 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -701,10 +701,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) // ... and merge in other signatures: BOOST_FOREACH(const CTransaction& txv, txVariants) - sigdata = CombineSignatures(prevPubKey, MutableTransactionNoWithdrawsSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i)); + sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i)); UpdateTransaction(mergedTx, i, sigdata); - if (!VerifyScript(txin.scriptSig, prevPubKey, (mergedTx.wit.vtxinwit.size() > i) ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionNoWithdrawsSignatureChecker(&mergedTx, i, amount))) + if (!VerifyScript(txin.scriptSig, prevPubKey, (mergedTx.wit.vtxinwit.size() > i) ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } @@ -716,58 +716,6 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) tx = mergedTx; } -static void MutateTxPeginSign(CMutableTransaction& tx, const std::string& flagStr) -{ - if (!registers.count("peginkeys")) - throw std::runtime_error("peginkeys register variable must be set."); - UniValue keysObj = registers["peginkeys"]; - - if (!keysObj.isObject()) - throw std::runtime_error("peginkeysObjs must be an object"); - std::map types = boost::assign::map_list_of("contract",UniValue::VSTR)("txoutproof",UniValue::VSTR)("tx",UniValue::VSTR)("nout",UniValue::VNUM); - if (!keysObj.checkObject(types)) - throw std::runtime_error("peginkeysObjs internal object typecheck fail"); - - std::vector contractData(ParseHexUV(keysObj["contract"], "contract")); - std::vector txoutproofData(ParseHexUV(keysObj["txoutproof"], "txoutproof")); - std::vector txData(ParseHexUV(keysObj["tx"], "tx")); - int nOut = atoi(keysObj["nout"].getValStr()); - - if (contractData.size() != 40) - throw std::runtime_error("contract must be 40 bytes"); - - CDataStream ssProof(txoutproofData,SER_NETWORK, PROTOCOL_VERSION); - Sidechain::Bitcoin::CMerkleBlock merkleBlock; - ssProof >> merkleBlock; - - CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION); - Sidechain::Bitcoin::CTransactionRef txBTCRef; - ssTx >> txBTCRef; - Sidechain::Bitcoin::CTransaction txBTC(*txBTCRef); - - std::vector transactionHashes; - std::vector transactionIndices; - if (!CheckBitcoinProof(merkleBlock.header.GetHash(), merkleBlock.header.nBits) || - merkleBlock.txn.ExtractMatches(transactionHashes, transactionIndices) != merkleBlock.header.hashMerkleRoot || - transactionHashes.size() != 1 || - transactionHashes[0] != txBTC.GetHash()) - throw std::runtime_error("txoutproof is invalid or did not match tx"); - - if (nOut < 0 || (unsigned int) nOut >= txBTC.vout.size()) - throw std::runtime_error("nout must be >= 0, < txout count"); - - CScript scriptSig; - scriptSig << contractData; - scriptSig.PushWithdraw(txoutproofData); - scriptSig.PushWithdraw(txData); - scriptSig << nOut; - - //TODO: Verify the withdraw proof - for (unsigned int i = 0; i < tx.vin.size(); i++) { - tx.vin[i].scriptSig = scriptSig; - } -} - class Secp256k1Init { ECCVerifyHandle globalVerifyHandle; @@ -815,17 +763,13 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, } else if (command == "blind") { if (!ecc) { ecc.reset(new Secp256k1Init()); } MutateTxBlind(tx, commandVal); - } else if (command == "peginsign") - MutateTxPeginSign(tx, commandVal); - - else if (command == "load") + } else if (command == "load") { RegisterLoad(commandVal); - - else if (command == "set") + } else if (command == "set") { RegisterSet(commandVal); - - else + } else { throw std::runtime_error("unknown command"); + } } static void OutputTxJSON(const CTransaction& tx) diff --git a/src/consensus/validation.h b/src/consensus/validation.h index a501b378de..5a7d7f11a9 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -17,7 +17,6 @@ static const unsigned char REJECT_NONSTANDARD = 0x40; static const unsigned char REJECT_DUST = 0x41; static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; static const unsigned char REJECT_CHECKPOINT = 0x43; -static const unsigned char REJECT_SCRIPT = 0x44; /** Capture information about block/transaction validation */ class CValidationState { diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index beac18f8cf..ce3f037666 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -122,15 +122,6 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) { const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]); - if (prev.scriptPubKey.IsWithdrawLock()) { - if (!tx.vin[i].scriptSig.IsWithdrawProof()) { - if (tx.vout.size() < i) - if (!tx.vout[i].nValue.IsExplicit() || tx.vout[i].nValue.GetAmount() > MAX_MONEY / 100) - return false; - } - continue; - } - // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed // keys. (remember the 520 byte limit on redeemScript size) That works // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 diff --git a/src/policy/policy.h b/src/policy/policy.h index a52b278def..c9b9a75b59 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -68,8 +68,7 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM | - SCRIPT_VERIFY_WITNESS_PUBKEYTYPE | - SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED; + SCRIPT_VERIFY_WITNESS_PUBKEYTYPE; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 4b951f2202..a49d390e95 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -15,8 +15,6 @@ static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; static const int WITNESS_SCALE_FACTOR = 4; -static const CFeeRate withdrawLockTxFee = CFeeRate(5460); - /** * Confidential assets, values, and nonces all share enough code in common * that it makes sense to define a common abstract base class. */ @@ -226,10 +224,6 @@ class CTxOut return false; if (IsFee()) return false; - //Withdrawlocks are evaluated at a higher, static feerate - //to ensure peg-outs are IsStandard on mainchain - if (scriptPubKey.IsWithdrawLock() && nValue.GetAmount() < GetDustThreshold(withdrawLockTxFee)) - return true; return (nValue.GetAmount() < GetDustThreshold(minRelayTxFee)); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e2163eb7b5..71af737139 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1388,14 +1388,14 @@ UniValue signrawtransaction(const JSONRPCRequest& request) // ... and merge in other signatures: BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { if (txv.vin.size() > i) { - sigdata = CombineSignatures(prevPubKey, TransactionNoWithdrawsSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i)); + sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i)); } } UpdateTransaction(mergedTx, i, sigdata); ScriptError serror = SCRIPT_ERR_OK; - if (!VerifyScript(txin.scriptSig, prevPubKey, (mergedTx.wit.vtxinwit.size() > i) ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionNoWithdrawsSignatureChecker(&txConst, i, amount), &serror)) { + if (!VerifyScript(txin.scriptSig, prevPubKey, (mergedTx.wit.vtxinwit.size() > i) ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror)); } } diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index bfb1ba9c21..fa4bfcc998 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -77,7 +77,6 @@ static bool verify_flags(unsigned int flags) } static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CConfidentialValue amount, - CConfidentialValue amountPreviousInput, const unsigned char *txTo , unsigned int txToLen, unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err) { @@ -96,10 +95,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP set_error(err, bitcoinconsensus_ERR_OK); PrecomputedTransactionData txdata(tx); - if (amountPreviousInput.IsExplicit() && (amountPreviousInput.GetAmount() < -1 || (nIn != 0 && !MoneyRange(amountPreviousInput.GetAmount())))) - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), (tx.wit.vtxinwit.size() > nIn) ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionNoWithdrawsSignatureChecker(&tx, nIn, amount, txdata), NULL); - else - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), (tx.wit.vtxinwit.size() > nIn) ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, amountPreviousInput, txdata, CScript()), NULL); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), (tx.wit.vtxinwit.size() > nIn) ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } @@ -120,7 +116,7 @@ int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey CConfidentialValue prevInAm; stream >> prevInAm; - return ::verify_script(scriptPubKey, scriptPubKeyLen, am, prevInAm, txTo, txToLen, nIn, flags, err); + return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } @@ -137,7 +133,7 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i CConfidentialValue am(0); CConfidentialValue prevInAm(-2); - return ::verify_script(scriptPubKey, scriptPubKeyLen, am, prevInAm, txTo, txToLen, nIn, flags, err); + return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err); } unsigned int bitcoinconsensus_version() diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index c9cf022435..ad32197ceb 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -71,10 +71,8 @@ EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubK const unsigned char *txTo , unsigned int txToLen, unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err); -// Use -1 for amountPreviousInput if there is no previous input (ie nIn == 0) EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, const unsigned char* amount, unsigned int amountLen, - const unsigned char* amountPreviousInput, unsigned int amountPreviousInputLen, const unsigned char *txTo , unsigned int txToLen, unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err); diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 2e97f6f3c6..31f76063ab 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -23,10 +23,6 @@ #include "utilstrencodings.h" #include "util.h" -#ifndef BITCOIN_SCRIPT_NO_CALLRPC -#include "callrpc.h" -#endif - using namespace std; typedef vector valtype; @@ -272,26 +268,6 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) { return true; } -bool static WithdrawProofReadStackItem(const vector& stack, const bool fRequireMinimal, int *stackOffset, valtype& read) -{ - if (stack.size() < size_t(-(*stackOffset))) - return false; - int pushCount = CScriptNum(stacktop(*stackOffset), fRequireMinimal).getint(); - if (pushCount < 0 || pushCount > 2000 || stack.size() < size_t(-(*stackOffset) + pushCount)) - return false; - (*stackOffset)--; - - read.reserve(pushCount > 1 ? pushCount * 520 : 0); - for (int i = pushCount - 1; i >= 0; i--) { - if (i != 0 && stacktop((*stackOffset) - i).size() != 520) - return false; - const valtype& stackElem = stacktop((*stackOffset) - i); - read.insert(read.end(), stackElem.begin(), stackElem.end()); - } - (*stackOffset) -= pushCount; - return true; -} - bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror) { static const CScriptNum bnZero(0); @@ -1417,182 +1393,7 @@ bool EvalScript(vector >& stack, const CScript& script, un } break; - case OP_WITHDRAWPROOFVERIFY: - { - // In the make-withdraw case, reads the following from the stack: - // 1. genesis block hash of the chain the withdraw is coming from - // 2. the index within the locking tx's outputs we are claiming - // 3. the locking tx itself (WithdrawProofReadStackItem) - // 4. the merkle block structure which contains the block in which - // the locking transaction is present (WithdrawProofReadStackItem) - // 5. The contract which we are expected to send coins to - // - // In the combine-outputs case, reads the following from the stack: - // 1. genesis block hash of the chain the withdraw is coming from - - if (flags & SCRIPT_VERIFY_WITHDRAW) { - if (stack.size() < 7 && stack.size() != 1) - return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - - const valtype &vgenesisHash = stacktop(-1); - if (vgenesisHash.size() != 32) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT); - - assert(checker.GetValueIn() != CConfidentialValue(-1)); // Not using a NoWithdrawSignatureChecker - - CScript relockScript = CScript() << vgenesisHash << OP_WITHDRAWPROOFVERIFY; - - if (stack.size() == 1) { // increasing value of locked coins - if (!checker.GetValueIn().IsExplicit()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - CAmount minValue = checker.GetValueIn().GetAmount(); - CTxOut newOutput = checker.GetOutputOffsetFromCurrent(0); - if (newOutput.IsNull()) { - newOutput = checker.GetOutputOffsetFromCurrent(-1); - if (!checker.GetValueInPrevIn().IsExplicit()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - minValue += checker.GetValueInPrevIn().GetAmount(); - } - if (!newOutput.nValue.IsExplicit()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - if (newOutput.scriptPubKey != relockScript || newOutput.nValue.GetAmount() < minValue) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT); - } else { // stack.size() >= 7...ie regular withdraw - int stackReadPos = -2; - - const valtype &vlockTxOutIndex = stacktop(stackReadPos--); - - valtype vlockTx; - if (!WithdrawProofReadStackItem(stack, fRequireMinimal, &stackReadPos, vlockTx)) - return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - - valtype vmerkleBlock; - if (!WithdrawProofReadStackItem(stack, fRequireMinimal, &stackReadPos, vmerkleBlock)) - return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - - if (stack.size() < size_t(-stackReadPos)) - return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - valtype vcontract = std::vector(stacktop(stackReadPos--)); - - uint256 genesishash(vgenesisHash); - - try { - Sidechain::Bitcoin::CMerkleBlock merkleBlock; - CDataStream merkleBlockStream(vmerkleBlock, SER_NETWORK, PROTOCOL_VERSION); - merkleBlockStream >> merkleBlock; - if (!merkleBlockStream.empty() || !CheckBitcoinProof(merkleBlock.header.GetHash(), merkleBlock.header.nBits)) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK); - - vector txHashes; - vector txIndices; - if (merkleBlock.txn.ExtractMatches(txHashes, txIndices) != merkleBlock.header.hashMerkleRoot || txHashes.size() != 1) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK); - - // We disallow returns from the genesis block, allowing sidechains to - // make genesis outputs spendable with a 21m initially-locked-to-btc - // distributing transaction. - if (merkleBlock.header.GetHash() == genesishash) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK); - - Sidechain::Bitcoin::CTransactionRef locktx; - CDataStream locktxStream(vlockTx, SER_NETWORK, PROTOCOL_VERSION); - locktxStream >> locktx; - if (!locktxStream.empty()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX); - - int nlocktxOut = CScriptNum(vlockTxOutIndex, fRequireMinimal).getint(); - if (nlocktxOut < 0 || (unsigned int)nlocktxOut >= locktx->vout.size()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX); - - if (locktx->GetHash() != txHashes[0]) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX); - - if (vcontract.size() != 40) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT); - - opcodetype opcodeTmp; - CScript scriptDestination = checker.GetFedpegScript(); - { - CScript::iterator sdpc = scriptDestination.begin(); - vector vch; - while (scriptDestination.GetOp(sdpc, opcodeTmp, vch)) - { - assert((vch.size() == 33 && opcodeTmp < OP_PUSHDATA4) || - (opcodeTmp <= OP_16 && opcodeTmp >= OP_1) || opcodeTmp == OP_CHECKMULTISIG); - if (vch.size() == 33) - { - unsigned char tweak[32]; - size_t pub_len = 33; - int ret; - unsigned char *pub_start = &(*(sdpc - pub_len)); - CHMAC_SHA256(pub_start, pub_len).Write(&vcontract[0], 40).Finalize(tweak); - secp256k1_pubkey pubkey; - ret = secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey, pub_start, pub_len); - assert(ret == 1); - // If someone creates a tweak that makes this fail, they broke SHA256 - ret = secp256k1_ec_pubkey_tweak_add(secp256k1_ctx, &pubkey, tweak); - assert(ret == 1); - ret = secp256k1_ec_pubkey_serialize(secp256k1_ctx, pub_start, &pub_len, &pubkey, SECP256K1_EC_COMPRESSED); - assert(ret == 1); - assert(pub_len == 33); - } - } - } - - CScriptID expectedP2SH(scriptDestination); - if (locktx->vout[nlocktxOut].scriptPubKey != GetScriptForDestination(expectedP2SH)) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPTDEST); - - vcontract.erase(vcontract.begin() + 4, vcontract.begin() + 20); // Remove the nonce from the contract before further processing - assert(vcontract.size() == 24); - - // We check values by doing the following: - // * Tx must relock at least - - // * Tx must send at least the withdraw value to its P2SH withdraw, but may send more - CAmount withdrawVal = locktx->vout[nlocktxOut].nValue; - if (!checker.GetValueIn().IsExplicit()) // Heh, you just destroyed coins - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - - CAmount lockValueRequired = checker.GetValueIn().GetAmount() - withdrawVal; - if (lockValueRequired > 0) { - const CTxOut newLockOutput = checker.GetOutputOffsetFromCurrent(1); - if (!newLockOutput.nValue.IsExplicit()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - if (newLockOutput.IsNull() || newLockOutput.scriptPubKey != relockScript || newLockOutput.nValue.GetAmount() < lockValueRequired) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_RELOCK_SCRIPTVAL); - } - - const CTxOut withdrawOutput = checker.GetOutputOffsetFromCurrent(0); - if (!withdrawOutput.nValue.IsExplicit()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS); - if (withdrawOutput.nValue.GetAmount() < withdrawVal) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_VAL); - - CScript expectedWithdrawScriptPubKey; - if (vcontract[0] == 'P' && vcontract[1] == '2' && vcontract[2] == 'S' && vcontract[3] == 'H') - expectedWithdrawScriptPubKey = CScript() << OP_HASH160 << std::vector(vcontract.begin() + 4, vcontract.begin() + 24) << OP_EQUAL; - else if (vcontract[0] == 'P' && vcontract[1] == '2' && vcontract[2] == 'P' && vcontract[3] == 'H') - expectedWithdrawScriptPubKey = CScript() << OP_DUP << OP_HASH160 << std::vector(vcontract.begin() + 4, vcontract.begin() + 24) << OP_EQUALVERIFY << OP_CHECKSIG; - else - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT); - - if (withdrawOutput.scriptPubKey != expectedWithdrawScriptPubKey) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPT); - -#ifndef BITCOIN_SCRIPT_NO_CALLRPC - if (GetBoolArg("-validatepegin", DEFAULT_VALIDATE_PEGIN) && !checker.IsConfirmedBitcoinBlock(merkleBlock.header.GetHash(), flags & SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED, GetArg("-peginconfirmationdepth", DEFAULT_PEGIN_CONFIRMATION_DEPTH))) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED); -#endif - } catch (std::exception& e) { - // Probably invalid encoding of something which was deserialized - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT); - } - } - } // else...OP_NOP3 - } - break; - - default: + default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } @@ -1834,22 +1635,12 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig return ss.GetHash(); } -CTxOut BaseSignatureChecker::GetOutputOffsetFromCurrent(const int offset) const -{ - return CTxOut(); -} - -COutPoint BaseSignatureChecker::GetPrevOut() const -{ - return COutPoint(); -} - -bool TransactionNoWithdrawsSignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash) const +bool TransactionSignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash) const { return pubkey.Verify(sighash, vchSig); } -bool TransactionNoWithdrawsSignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const +bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const { CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) @@ -1870,7 +1661,7 @@ bool TransactionNoWithdrawsSignatureChecker::CheckSig(const vector= 0 && int(txTo->vout.size()) > 0); - if (int(nIn) + offset < 0 || int(txTo->vout.size()) <= int(nIn) + offset) - return CTxOut(); - return txTo->vout[int(nIn) + offset]; -} - -COutPoint TransactionSignatureChecker::GetPrevOut() const -{ - return txTo->vin[nIn].prevout; -} - -CConfidentialValue TransactionSignatureChecker::GetValueIn() const -{ - return amount; -} - -CConfidentialValue TransactionSignatureChecker::GetValueInPrevIn() const -{ - return amountPreviousInput; -} - -bool TransactionSignatureChecker::IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements, uint32_t nConfirmationsRequired) const -{ -#ifndef BITCOIN_SCRIPT_NO_CALLRPC - return ::IsConfirmedBitcoinBlock(hash, nConfirmationsRequired + (fConservativeConfirmationRequirements ? 2 : 0)); -#else - return true; -#endif -} - static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { vector > stack; @@ -2051,18 +1810,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); } - // If the scriptPubKey is not in exactly the withdrawlock format we expect, - // we will not execute WITHDRAW-related opcodes (treating them as NOPs) - // Additionally, if the scriptPubKey is a withdraw lock, the scriptSig must - // be push only. - if ((flags & SCRIPT_VERIFY_WITHDRAW) != 0) { - if (scriptPubKey.IsWithdrawLock()) { - if (!scriptSig.IsPushOnly()) - return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT); - } else - flags &= ~SCRIPT_VERIFY_WITHDRAW; - } - vector > stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror)) // serror is set @@ -2150,7 +1897,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C // would be possible, which is not a softfork (and P2SH should be one). assert((flags & SCRIPT_VERIFY_P2SH) != 0); assert((flags & SCRIPT_VERIFY_WITNESS) != 0); - if (stack.size() != 1 && (flags & SCRIPT_VERIFY_WITHDRAW) == 0) { + if (stack.size() != 1) { return set_error(serror, SCRIPT_ERR_CLEANSTACK); } } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index ff3ac36ead..58ee3a3705 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -108,13 +108,6 @@ enum // SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15), - // Execute sidechain-related opcodes instead of treating them as NOPs - // - SCRIPT_VERIFY_WITHDRAW = (1U << 16), - - // Dirty hack to require a higher bar of bitcoin block confirmation in mempool - // - SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED = (1U << 17) }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); @@ -142,44 +135,20 @@ class BaseSignatureChecker return false; } - virtual CScript GetFedpegScript() const - { - CScript fedpegScript(CScript() << OP_FALSE); - return fedpegScript; - } - virtual bool CheckLockTime(const CScriptNum& nLockTime) const { return false; } - virtual CTxOut GetOutputOffsetFromCurrent(const int offset) const; - virtual COutPoint GetPrevOut() const; - - virtual CConfidentialValue GetValueIn() const - { - return -1; - } - virtual bool CheckSequence(const CScriptNum& nSequence) const { return false; } - virtual CConfidentialValue GetValueInPrevIn() const - { - return -1; - } - - virtual bool IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements, uint32_t nConfirmationsRequired) const - { - return false; - } - virtual ~BaseSignatureChecker() {} }; -class TransactionNoWithdrawsSignatureChecker : public BaseSignatureChecker +class TransactionSignatureChecker : public BaseSignatureChecker { protected: const CTransaction* txTo; @@ -190,40 +159,20 @@ class TransactionNoWithdrawsSignatureChecker : public BaseSignatureChecker virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {} - TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; }; -class MutableTransactionNoWithdrawsSignatureChecker : public TransactionNoWithdrawsSignatureChecker +class MutableTransactionSignatureChecker : public TransactionSignatureChecker { private: const CTransaction txTo; public: - MutableTransactionNoWithdrawsSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amount) : TransactionNoWithdrawsSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} -}; - -class TransactionSignatureChecker : public TransactionNoWithdrawsSignatureChecker -{ -private: - const CConfidentialValue amountPreviousInput; - const CScript fedpegScript; - -public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, const CConfidentialValue& amountPreviousInputIn, const CScript& fedpegScriptIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn), amountPreviousInput(amountPreviousInputIn), fedpegScript(fedpegScriptIn) {} - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, const CConfidentialValue& amountPreviousInputIn, const PrecomputedTransactionData& txdataIn, const CScript& fedpegScriptIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn, txdataIn), amountPreviousInput(amountPreviousInputIn), fedpegScript(fedpegScriptIn) {} - CTxOut GetOutputOffsetFromCurrent(const int offset) const; - COutPoint GetPrevOut() const; - CConfidentialValue GetValueIn() const; - CConfidentialValue GetValueInPrevIn() const; - bool IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements, uint32_t nConfirmationsRequired) const; - virtual CScript GetFedpegScript() const - { - return fedpegScript; - } + MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} }; bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL); diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 2a878b265f..4b58b66bce 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -63,7 +63,6 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& { case TX_NONSTANDARD: case TX_NULL_DATA: - case TX_WITHDRAW_LOCK: case TX_FEE: break; case TX_PUBKEY: diff --git a/src/script/script.cpp b/src/script/script.cpp index 6c5850fc21..e60ff3c12f 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -215,151 +215,6 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const return subscript.GetSigOpCount(true); } -bool CScript::IsWithdrawProof() const -{ - // Format is xN xM - // for at least 6 total pushes - // Here we simply check that the script is push-only and has at least 6 pushes. - // The output must be P2SH to the appropriate script - const_iterator pc = begin(); - opcodetype opcode; - uint32_t push_count = 0; - while (pc < end()) - { - if (!GetOp(pc, opcode)) - return false; - if (opcode > OP_16 || opcode == OP_RESERVED) - return false; - push_count++; - } - return push_count >= 6; -} - -bool CScript::IsWithdrawLock() const -{ - // Locks look like [ OP_DROP] OP_WITHDRAWPROOFVERIFY - // This function must return true for an OP_WITHDRAWPROOFVERIFY opcode to execute. - // We require all pushes be in their minimal form, to make inspection of - // withdraw locks a purely byte-matching affair. - const_iterator pc = begin(); - vector data; - opcodetype opcode; - - if (!GetOp(pc, opcode, data)) - return false; - if (opcode == 24 && data.size() == 24) { // 4 byte type + 20 byte destination is suggested - if (!GetOp(pc, opcode, data) || opcode != OP_DROP || data.size() != 0) - return false; - - if (!GetOp(pc, opcode, data)) - return false; - } - - if (opcode != 32 || data.size() != 32) - return false; - - if (!GetOp(pc, opcode, data) || opcode != OP_WITHDRAWPROOFVERIFY || data.size() != 0) - return false; - - if (GetOp(pc, opcode)) - return false; - - return true; -} - -uint256 CScript::GetWithdrawLockGenesisHash() const -{ - assert(IsWithdrawLock()); - - const_iterator pc = begin(); - opcodetype opcode; - vector vchgenesishash; - - bool ret; - ret = GetOp(pc, opcode, vchgenesishash); - assert(ret); - if (vchgenesishash.size() != 32) { - ret = GetOp(pc, opcode); - assert(ret && opcode == OP_DROP); - ret = GetOp(pc, opcode, vchgenesishash); - assert(ret); - } - assert(vchgenesishash.size() == 32); - return uint256(vchgenesishash); -} - -static bool PopWithdrawPush(vector >& pushes, vector *read=NULL) { - if (pushes.empty()) - return false; - int pushCount = CScriptNum(pushes.back(), false).getint(); - pushes.pop_back(); - if (pushCount < 0 || pushCount > 2000 || pushes.size() < size_t(pushCount)) - return false; - for (int i = pushCount; i > 0; i--) { - if (i != 1 && pushes[pushes.size() - i].size() != 520) - return false; - if (read != NULL) { - const vector &push = pushes[pushes.size() - i]; - read->insert(read->end(), push.begin(), push.end()); - } - } - for (int i = 0; i < pushCount; i++) - pushes.pop_back(); - return true; -} - -COutPoint CScript::GetWithdrawSpent() const -{ - assert(IsWithdrawProof()); - - try { - const_iterator pc = begin(); - opcodetype opcode; - - // We have to read the script from back-to-front, so we stack-ize it - vector > pushes; - pushes.reserve(6); - while (pc < end()) { - pushes.push_back(vector()); - assert(GetOp(pc, opcode, pushes.back())); - if (opcode <= OP_16 && opcode >= OP_1) - pushes.back().push_back(opcode - OP_1 + 1); - else if (opcode == OP_1NEGATE) - pushes.back().push_back(0x81); - } - - int ntxOut = CScriptNum(pushes.back(), false).getint(); - pushes.pop_back(); - - vector vTx; - if (!PopWithdrawPush(pushes, &vTx)) - return COutPoint(); - Sidechain::Bitcoin::CTransactionRef tx; - CDataStream(vTx, SER_NETWORK, PROTOCOL_VERSION) >> tx; - - if (ntxOut < 0 || (unsigned int)ntxOut >= tx->vout.size()) - return COutPoint(); - - return COutPoint(tx->GetHash(), ntxOut); - } catch (std::exception& e) { - return COutPoint(); - } -} - -void CScript::PushWithdraw(const vector push) { - int64_t pushCount = 0; - for (vector::const_iterator it = push.begin(); it < push.end(); pushCount++) { - if (push.end() - it < 520) { - *this << vector(it, push.end()); - it = push.end(); - } else { - *this << vector(it, it + 520); - it += 520; - } - } - *this << pushCount; -} - bool CScript::IsPayToScriptHash() const { // Extra-fast test for pay-to-script-hash CScripts: diff --git a/src/script/script.h b/src/script/script.h index 6eb21b826e..ca3343016d 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -636,24 +636,6 @@ class CScript : public CScriptBase bool IsPayToScriptHash() const; bool IsPayToWitnessScriptHash() const; bool IsWitnessProgram(int& version, std::vector& program) const; - /** - * Returns true if this is a withdraw-lock scriptPubKey. - * Note that a withdraw-lock could be a plan [re-]lock output *or* a - * x-chain transfer lock. - */ - bool IsWithdrawLock() const; - - /** Returns true if this is a proof-of-withdraw, spending an IsWithdrawLock */ - bool IsWithdrawProof() const; - - //! Push a vector with a length postfix (as used by withdraw proofs) - void PushWithdraw(const std::vector push); - - /** Get the withdraw output spent, asserting IsWithdrawProof first */ - COutPoint GetWithdrawSpent() const; - - /** Get the genesis hash locked to, asserting IsWithdrawLock first */ - uint256 GetWithdrawLockGenesisHash() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly(const_iterator pc) const; diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 9768ebd82b..c9d13c92a8 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -87,26 +87,6 @@ const char* ScriptErrorString(const ScriptError serror) return "Witness provided for non-witness script"; case SCRIPT_ERR_WITNESS_PUBKEYTYPE: return "Using non-compressed keys in segwit"; - case SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT: - return "Withdraw proof validation failed - invalid proof format"; - case SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK: - return "Withdraw proof validation failed - SPV proof/block coinbase invalid"; - case SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX: - return "Withdraw proof validation failed - locking transaction misformatted"; - case SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT: - return "Withdraw proof validation failed - output does not match expected"; - case SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED: - return "Withdraw proof validation failed - lock block was not sufficiently confirmed on sending chain"; - case SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS: - return "Withdraw proof validation failed - amounts in outputs were blinded"; - case SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPTDEST: - return "Withdraw proof validation failed - Bitcoin output script destination does not match federation script"; - case SCRIPT_ERR_WITHDRAW_VERIFY_RELOCK_SCRIPTVAL: - return "Withdraw proof validation failed - Relock scriptpubkey or value is invalid"; - case SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_VAL: - return "Withdraw proof validation failed - Withdraw output value invalid"; - case SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPT: - return "Withdraw proof validation failed - Sidechain pegin destination does not match expected"; case SCRIPT_ERR_UNKNOWN_ERROR: case SCRIPT_ERR_ERROR_COUNT: default: break; diff --git a/src/script/script_error.h b/src/script/script_error.h index 0d0fbcd628..01c11fefc9 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -64,19 +64,6 @@ typedef enum ScriptError_t SCRIPT_ERR_WITNESS_UNEXPECTED, SCRIPT_ERR_WITNESS_PUBKEYTYPE, - /* sidechains */ - SCRIPT_ERR_WITHDRAW_VERIFY_FORMAT, - SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK, - SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX, - SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT, - SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPTDEST, - SCRIPT_ERR_WITHDRAW_VERIFY_RELOCK_SCRIPTVAL, - SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_VAL, - SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT_SCRIPT, - - SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED, - SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS, - SCRIPT_ERR_ERROR_COUNT, SCRIPT_ERR_RANGEPROOF, diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 20b287fb91..c0e329dc8e 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -28,7 +28,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amount, const CConfidentialValue& amountPreviousInput, const CScript& scriptFedRedeem, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, amountPreviousInput, scriptFedRedeem), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; }; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index d9e59bda4c..a786a42bae 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -82,7 +82,6 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP { case TX_NONSTANDARD: case TX_NULL_DATA: - case TX_WITHDRAW_LOCK: return false; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); @@ -319,7 +318,6 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature { case TX_NONSTANDARD: case TX_NULL_DATA: - case TX_WITHDRAW_LOCK: case TX_TRUE: // Don't know anything about this, assume bigger one is correct: if (sigs1.script.size() >= sigs2.script.size()) diff --git a/src/script/sign.h b/src/script/sign.h index 6856c6d740..6521e22a5f 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -36,7 +36,7 @@ class TransactionSignatureCreator : public BaseSignatureCreator { unsigned int nIn; int nHashType; CConfidentialValue amount; - const TransactionNoWithdrawsSignatureChecker checker; + const TransactionSignatureChecker checker; public: TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, int nHashTypeIn=SIGHASH_ALL); diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 7fa86af542..9865d60d6d 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -33,7 +33,6 @@ const char* GetTxnOutputType(txnouttype t) case TX_NULL_DATA: return "nulldata"; case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash"; case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash"; - case TX_WITHDRAW_LOCK: return "withdraw"; case TX_TRUE: return "true"; case TX_FEE: return "fee"; } @@ -107,12 +106,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector vSolutions; if (!Solver(scriptPubKey, typeRet, vSolutions)) return false; - if (typeRet == TX_NULL_DATA || typeRet == TX_WITHDRAW_LOCK || typeRet == TX_FEE){ + if (typeRet == TX_NULL_DATA || typeRet == TX_FEE){ // This is data, not addresses return false; } diff --git a/src/script/standard.h b/src/script/standard.h index c0ae8f3351..5e77084aa1 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -40,7 +40,7 @@ extern unsigned nMaxDatacarrierBytes; * Failing one of these tests may trigger a DoS ban - see CheckInputs() for * details. */ -static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_WITHDRAW; +static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; enum txnouttype { @@ -53,7 +53,6 @@ enum txnouttype TX_NULL_DATA, TX_WITNESS_V0_SCRIPTHASH, TX_WITNESS_V0_KEYHASH, - TX_WITHDRAW_LOCK, TX_TRUE, TX_FEE, }; diff --git a/src/test/lockedutxo_tests.cpp b/src/test/lockedutxo_tests.cpp deleted file mode 100644 index 986ba0efb1..0000000000 --- a/src/test/lockedutxo_tests.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "chainparams.h" -#include "coins.h" -#include "consensus/consensus.h" -#include "consensus/merkle.h" -#include "consensus/validation.h" -#include "validation.h" -#include "miner.h" -#include "pubkey.h" -#include "script/standard.h" -#include "txmempool.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" -#include "random.h" - -#include "txdb.h" - -#include "test/test_bitcoin.h" - -#include - -BOOST_FIXTURE_TEST_SUITE(lockedutxo_tests, TestingSetup) - -BOOST_AUTO_TEST_CASE(Getlocked_validity) -{ - std::multimap > mLocksCreated; - - uint256 gen0 = uint256S("0"); - - CMutableTransaction mtx0; - mtx0.vout.push_back(CTxOut(CConfidentialAsset(Params().GetConsensus().pegged_asset), CConfidentialValue(1000), CScript() << OP_TRUE)); - CMutableTransaction mtx1; - mtx1.vout.push_back(CTxOut(CConfidentialAsset(Params().GetConsensus().pegged_asset), CConfidentialValue(100), CScript() << OP_TRUE)); - CMutableTransaction mtx2; - mtx2.vout.push_back(CTxOut(CConfidentialAsset(Params().GetConsensus().pegged_asset), CConfidentialValue(10), CScript() << OP_TRUE)); - CMutableTransaction mtx3; - mtx3.vout.push_back(CTxOut(CConfidentialAsset(Params().GetConsensus().pegged_asset), CConfidentialValue(1), CScript() << OP_TRUE)); - - //Push vout of size 1 for each CCoin - pcoinsTip->ModifyCoins(uint256S("0"))->FromTx(CTransaction(mtx0), 0); - pcoinsTip->ModifyCoins(uint256S("1"))->FromTx(CTransaction(mtx1), 0); - pcoinsTip->ModifyCoins(uint256S("2"))->FromTx(CTransaction(mtx2), 0); - pcoinsTip->ModifyCoins(uint256S("3"))->FromTx(CTransaction(mtx3), 0); - - //These coins need to exist, otherwise they will be deleted during GetLockedOutputs call - CAmount value = 1000; - mLocksCreated.insert(std::make_pair(gen0, std::make_pair(COutPoint(uint256S("0"), 0), value))); - value = 100; - mLocksCreated.insert(std::make_pair(gen0, std::make_pair(COutPoint(uint256S("1"), 0), value))); - value = 10; - mLocksCreated.insert(std::make_pair(gen0, std::make_pair(COutPoint(uint256S("2"), 0), value))); - value = 1; - mLocksCreated.insert(std::make_pair(gen0, std::make_pair(COutPoint(uint256S("3"), 0), value))); - - //Write list of 4 - pblocktree->WriteLocksCreated(mLocksCreated); - - //Read the list back, ensure it was written correctly - std::vector > locksCreated; - assert(pblocktree->ReadLocksCreated(gen0, locksCreated)); - assert(locksCreated.size() == 4); - std::multimap >::iterator it = mLocksCreated.equal_range(gen0).first; - assert(locksCreated[0] == it->second); - std::advance(it, 1); - assert(locksCreated[1] == it->second); - std::advance(it, 1); - assert(locksCreated[2] == it->second); - std::advance(it, 1); - assert(locksCreated[3] == it->second); - - //Call GetLockedOutputs to get the single output large enough - CAmount desiredAmount = 101; - std::vector > res; - assert(GetLockedOutputs(gen0, desiredAmount, res)); - assert(res.size() == 1 && res[0].second == 1000); - - //Read it back again - std::vector > locksCreated2; - assert(pblocktree->ReadLocksCreated(gen0, locksCreated2)); - assert(locksCreated2.size() == 4); - - //Write a blank list and read it back - std::vector > locksCreated3; - pblocktree->ReWriteLocksCreated(gen0, locksCreated3); - assert(pblocktree->ReadLocksCreated(gen0, locksCreated3)); - assert(locksCreated3.size() == 0); - - //Delete the largest element, and read back - locksCreated.erase(locksCreated.begin()); - pblocktree->ReWriteLocksCreated(gen0, locksCreated); - assert(pblocktree->ReadLocksCreated(gen0, locksCreated)); - assert(locksCreated.size() == 3); - - //Find at least 2 utxos to fulfill amount - std::vector > res2; - assert(GetLockedOutputs(gen0, desiredAmount, res2)); - assert(res2.size() > 1); - - //Delete the second-largest element, and read back - locksCreated.erase(locksCreated.begin()); - pblocktree->ReWriteLocksCreated(gen0, locksCreated); - assert(pblocktree->ReadLocksCreated(gen0, locksCreated)); - assert(locksCreated.size() == 2); - - //Will not find enough, but will return the last 2 - std::vector > res3; - assert(!GetLockedOutputs(gen0, desiredAmount, res3)); - assert(res3.size() == 2); - - - // Make sure this terminates - for (unsigned int i = 0; i < 10000; i++) { - // Make random set of 100 utxos - std::vector > locksCreated4; - for (unsigned int j = 0; j < GetRand(100); j++) { - locksCreated4.push_back(std::make_pair(COutPoint(GetRandHash(), GetRand(10)), GetRand(100000))); - } - pblocktree->ReWriteLocksCreated(gen0, locksCreated4); - CAmount desiredAmount = GetRand(1000000); - std::vector > res; - GetLockedOutputs(gen0, desiredAmount, res); - } -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index b9e574a9e1..5903cb1e05 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -422,8 +422,8 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) /* after tx6 is mined, tx7 should move up in the sort */ std::vector vtx; vtx.push_back(MakeTransactionRef(tx6)); - std::set > setWithdrawsSpent; - pool.removeForBlock(vtx, 1, setWithdrawsSpent); + std::set > setPeginsSpent; + pool.removeForBlock(vtx, 1, setPeginsSpent); sortedOrder.erase(sortedOrder.begin()+1); // Ties are broken by hash @@ -566,8 +566,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); // ... we should keep the same min fee until we get a block - std::set > setWithdrawsSpent; - pool.removeForBlock(vtx, 1, setWithdrawsSpent); + std::set > setPeginsSpent; + pool.removeForBlock(vtx, 1, setPeginsSpent); SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/2); // ... then feerate should drop 1/2 each halflife @@ -595,7 +595,7 @@ BOOST_AUTO_TEST_CASE(WithdrawsSpentTest) { CTxMemPool pool(CFeeRate(0)); - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; TestMemPoolEntryHelper entry; std::pair withdraw1, withdraw2, withdraw3; @@ -614,63 +614,63 @@ BOOST_AUTO_TEST_CASE(WithdrawsSpentTest) tx.vout.resize(1); tx.vout[0].nValue = 0; const uint256 tx1Hash(tx.GetHash()); - pool.addUnchecked(tx1Hash, entry.WithdrawsSpent(setWithdrawsSpent).FromTx(tx)); + pool.addUnchecked(tx1Hash, entry.WithdrawsSpent(setPeginsSpent).FromTx(tx)); BOOST_CHECK(pool.mapWithdrawsSpentToTxid.empty()); - setWithdrawsSpent = {withdraw1}; + setPeginsSpent = {withdraw1}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(2); tx.vout[1].nValue = 0; const uint256 tx2Hash(tx.GetHash()); - pool.addUnchecked(tx2Hash, entry.WithdrawsSpent(setWithdrawsSpent).FromTx(tx)); + pool.addUnchecked(tx2Hash, entry.WithdrawsSpent(setPeginsSpent).FromTx(tx)); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw1].ToString(), tx2Hash.ToString()); - setWithdrawsSpent = {withdraw2}; + setPeginsSpent = {withdraw2}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(3); tx.vout[2].nValue = 0; const uint256 tx3Hash(tx.GetHash()); - pool.addUnchecked(tx3Hash, entry.WithdrawsSpent(setWithdrawsSpent).FromTx(tx)); + pool.addUnchecked(tx3Hash, entry.WithdrawsSpent(setPeginsSpent).FromTx(tx)); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw2].ToString(), tx3Hash.ToString()); - setWithdrawsSpent = {withdraw3}; + setPeginsSpent = {withdraw3}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(4); tx.vout[3].nValue = 0; CTransactionRef txref(MakeTransactionRef(tx)); - pool.removeForBlock({txref}, 1, setWithdrawsSpent); + pool.removeForBlock({txref}, 1, setPeginsSpent); BOOST_CHECK_EQUAL(pool.size(), 3); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid.size(), 2); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw1].ToString(), tx2Hash.ToString()); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw2].ToString(), tx3Hash.ToString()); - setWithdrawsSpent = {withdraw1}; + setPeginsSpent = {withdraw1}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(5); tx.vout[4].nValue = 0; txref = MakeTransactionRef(tx); - pool.removeForBlock({txref}, 2, setWithdrawsSpent); + pool.removeForBlock({txref}, 2, setPeginsSpent); BOOST_CHECK_EQUAL(pool.size(), 2); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid.size(), 1); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw2].ToString(), tx3Hash.ToString()); - setWithdrawsSpent = {withdraw1, withdraw3}; + setPeginsSpent = {withdraw1, withdraw3}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(6); tx.vout[5].nValue = 0; const uint256 tx4Hash(tx.GetHash()); - pool.addUnchecked(tx4Hash, entry.WithdrawsSpent(setWithdrawsSpent).FromTx(tx)); + pool.addUnchecked(tx4Hash, entry.WithdrawsSpent(setPeginsSpent).FromTx(tx)); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw1].ToString(), tx4Hash.ToString()); BOOST_CHECK_EQUAL(pool.mapWithdrawsSpentToTxid[withdraw3].ToString(), tx4Hash.ToString()); - setWithdrawsSpent = {withdraw2, withdraw3}; + setPeginsSpent = {withdraw2, withdraw3}; GetRandBytes(tx.vin[0].prevout.hash.begin(), tx.vin[0].prevout.hash.size()); tx.vout.resize(7); tx.vout[6].nValue = 0; txref = MakeTransactionRef(tx); - pool.removeForBlock({txref}, 3, setWithdrawsSpent); + pool.removeForBlock({txref}, 3, setPeginsSpent); BOOST_CHECK_EQUAL(pool.size(), 1); BOOST_CHECK(pool.mapWithdrawsSpentToTxid.empty()); diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 59856891ed..dd5678ea6e 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -80,20 +80,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys.assign(1,key[0]); keys.push_back(key[1]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[0], 0, amount), &err)); + BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); for (int i = 0; i < 4; i++) { keys.assign(1,key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); keys.assign(1,key[1]); keys.push_back(key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -104,18 +104,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(a_or_b, keys, txTo[1], 0); if (i == 0 || i == 1) { - BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } s.clear(); s << OP_0 << OP_1; - BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[1], 0, amount), &err)); + BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); @@ -127,12 +127,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(escrow, keys, txTo[2], 0); if (i < j && i < 3 && j < 3) { - BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j)); + BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index fbbda73a99..f8fd8cc30c 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -41,7 +41,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri txTo.vin[0].scriptSig = scriptSig; txTo.vout[0].nValue = 1; - return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err); + return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err); } @@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(sign) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, -1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index bc79ecf60e..02930141ba 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -167,7 +167,7 @@ return; CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue); CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit); CMutableTransaction tx2 = tx; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, txCredit.vout[0].scriptPubKey, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, txCredit.vout[0].scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); @@ -1077,18 +1077,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); txTo12.vout[0].nValue = 2; - BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -1110,54 +1110,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) std::vector keys; keys.push_back(key1); keys.push_back(key2); CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key3); CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key3); CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); // Must have signatures CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionNoWithdrawsSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); } @@ -1183,19 +1183,19 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript& scriptSig = txTo.vin[0].scriptSig; SignatureData empty; - SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), empty, empty); + SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty); BOOST_CHECK(combined.scriptSig.empty()); // Single signature case: SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); CScript scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); // P2SH, single-signature case: @@ -1203,28 +1203,28 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) keystore.AddCScript(pkSingle); scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); scriptSigCopy = scriptSig; SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); // dummy scriptSigCopy with placeholder, should always choose non-placeholder: scriptSigCopy = CScript() << OP_0 << std::vector(pkSingle.begin(), pkSingle.end()); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy)); BOOST_CHECK(combined.scriptSig == scriptSig); // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); keystore.AddCScript(scriptPubKey); SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); BOOST_CHECK(combined.scriptSig == scriptSig); // A couple of partially-signed versions: @@ -1253,21 +1253,21 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript complete13 = CScript() << OP_0 << sig1 << sig3; CScript complete23 = CScript() << OP_0 << sig2 << sig3; - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b)); BOOST_CHECK(combined.scriptSig == partial1a); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a)); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a)); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b)); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b)); BOOST_CHECK(combined.scriptSig == complete13); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a)); BOOST_CHECK(combined.scriptSig == complete23); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b)); BOOST_CHECK(combined.scriptSig == complete23); - combined = CombineSignatures(scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a)); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a)); BOOST_CHECK(combined.scriptSig == partial3c); } diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index f41c4143f8..28f976c66c 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -71,7 +71,7 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction { ScriptError error; CTransaction inputi(input); - bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue, -1, CScript()), &error); + bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error); BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK)); return error; diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index e4e59e259c..573c16b963 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -174,7 +174,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPo CAmount inChainValue = pool && pool->HasNoInputsOf(txn) ? TotalValueOut(txn) : 0; return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, dPriority, nHeight, - inChainValue, spendsCoinbase, sigOpCost, lp, setWithdrawsSpent); + inChainValue, spendsCoinbase, sigOpCost, lp, setPeginsSpent); } void Shutdown(void* parg) diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 5997b0a88a..e6a618a71c 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -73,7 +73,7 @@ struct TestMemPoolEntryHelper bool spendsCoinbase; unsigned int sigOpCost; LockPoints lp; - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; TestMemPoolEntryHelper() : nFee(0), nTime(0), dPriority(0.0), nHeight(1), @@ -89,6 +89,6 @@ struct TestMemPoolEntryHelper TestMemPoolEntryHelper &Height(unsigned int _height) { nHeight = _height; return *this; } TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; } TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; } - TestMemPoolEntryHelper &WithdrawsSpent(std::set >& _setWithdrawsSpent) { setWithdrawsSpent = _setWithdrawsSpent; return *this; } + TestMemPoolEntryHelper &WithdrawsSpent(std::set >& _setPeginsSpent) { setPeginsSpent = _setPeginsSpent; return *this; } }; #endif diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index c9dbe72011..f5a805ff8b 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -172,7 +172,7 @@ return; unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); const CScriptWitness *witness = (tx.wit.vtxinwit.size() > i) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionNoWithdrawsSignatureChecker(&tx, i, amount, txdata), &err), + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -257,7 +257,7 @@ return; } const CScriptWitness *witness = (tx.wit.vtxinwit.size() > i) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionNoWithdrawsSignatureChecker(&tx, i, amount, txdata), &err); + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -400,7 +400,7 @@ void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& inp { ScriptError error; CTransaction inputi(input); - bool ret = VerifyScript(inputi.vin[0].scriptSig, output->vout[0].scriptPubKey, (inputi.wit.vtxinwit.size() > 0) ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionNoWithdrawsSignatureChecker(&inputi, 0, output->vout[0].nValue), &error); + bool ret = VerifyScript(inputi.vin[0].scriptSig, output->vout[0].scriptPubKey, (inputi.wit.vtxinwit.size() > 0) ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output->vout[0].nValue), &error); assert(ret == success); } @@ -496,7 +496,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { CScriptCheck* checks[mtx.vin.size()]; for(uint32_t i = 0; i < mtx.vin.size(); i++) { std::vector vChecks; - checks[i] = new CScriptCheck(coins, tx, i, 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata); + checks[i] = new CScriptCheck(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata); vChecks.push_back(checks[i]); control.Add(vChecks); } @@ -643,7 +643,7 @@ BOOST_AUTO_TEST_CASE(test_witness) CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false); CheckWithFlag(output2, input2, 0, false); BOOST_CHECK(*output1 == *output2); - UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); // P2SH 2-of-2 multisig @@ -654,7 +654,7 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output2, input2, 0, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false); BOOST_CHECK(*output1 == *output2); - UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); @@ -666,7 +666,7 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output2, input2, 0, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); BOOST_CHECK(*output1 == *output2); - UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); @@ -678,7 +678,7 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); BOOST_CHECK(*output1 == *output2); - UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionNoWithdrawsSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); } diff --git a/src/txdb.cpp b/src/txdb.cpp index 4b0a8cbebb..846334dbc5 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -171,36 +171,6 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector return WriteBatch(batch); } -bool CBlockTreeDB::WriteLocksCreated(const std::multimap > &map) { - if (map.size() == 0) - return true; - - uint256 prevGenesis; - CDBBatch batch(*this); - std::vector > vLocks; - for (std::multimap >::const_iterator it=map.begin(); it!=map.end(); it++) { - if (prevGenesis != it->first || it == map.begin()) { - if (it != map.begin()) - batch.Write(std::make_pair(DB_LOCKS, prevGenesis), vLocks); - prevGenesis = it->first; - if (!Read(std::make_pair(DB_LOCKS, it->first), vLocks)) - vLocks.clear(); - } - vLocks.push_back(it->second); - } - batch.Write(std::make_pair(DB_LOCKS, prevGenesis), vLocks); - return WriteBatch(batch); -} - - -bool CBlockTreeDB::ReadLocksCreated(const uint256 &genesisHash, std::vector > &vLocks) { - return Read(std::make_pair(DB_LOCKS, genesisHash), vLocks); -} - -bool CBlockTreeDB::ReWriteLocksCreated(const uint256 &genesisHash, const std::vector > &vLocks) { - return Write(std::make_pair(DB_LOCKS, genesisHash), vLocks); -} - bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0'); } diff --git a/src/txdb.h b/src/txdb.h index fa615981fc..3fe224ebf2 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -121,9 +121,6 @@ class CBlockTreeDB : public CDBWrapper bool ReadReindexing(bool &fReindex); bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos); bool WriteTxIndex(const std::vector > &list); - bool WriteLocksCreated(const std::multimap > &list); - bool ReadLocksCreated(const uint256 &genesisHash, std::vector > &vLocks); - bool ReWriteLocksCreated(const uint256 &genesisHash, const std::vector > &vLocks); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); bool LoadBlockIndexGuts(boost::function insertBlockIndex); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b89edbeea4..722d89764b 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -21,10 +21,10 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, CAmount _inChainInputValue, - bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp, std::set >& _setWithdrawsSpent): + bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp, std::set >& _setPeginsSpent): tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), - spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp), setWithdrawsSpent(_setWithdrawsSpent) + spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp), setPeginsSpent(_setPeginsSpent) { nTxWeight = GetTransactionWeight(*tx); nModSize = tx->CalculateModifiedSize(GetTxSize()); @@ -448,9 +448,11 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, vTxHashes.emplace_back(tx.GetHashWithWitness(), newit); newit->vTxHashesIdx = vTxHashes.size() - 1; - typedef std::pair WithdrawPair; - BOOST_FOREACH(const WithdrawPair& it, entry.setWithdrawsSpent) - assert(mapWithdrawsSpentToTxid.insert(std::make_pair(it, hash)).second); + typedef std::pair PeginPair; + BOOST_FOREACH(const PeginPair& it, entry.setPeginsSpent) { + std::pair, uint256>::iterator, bool> ret = mapWithdrawsSpentToTxid.insert(std::make_pair(it, hash)); + assert(ret.second); + } return true; } @@ -462,9 +464,10 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) BOOST_FOREACH(const CTxIn& txin, it->GetTx().vin) mapNextTx.erase(txin.prevout); - typedef std::pair WithdrawPair; - BOOST_FOREACH(const WithdrawPair& it2, it->setWithdrawsSpent) - assert(mapWithdrawsSpentToTxid.erase(it2)); + typedef std::pair PeginPair; + BOOST_FOREACH(const PeginPair& it2, it->setPeginsSpent) { + mapWithdrawsSpentToTxid.erase(it2); + } if (vTxHashes.size() > 1) { vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back()); @@ -603,7 +606,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx) * Called when a block is connected. Removes from mempool and updates the miner fee estimator. */ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, - const std::set >& setWithdrawsSpent) + const std::set >& setPeginsSpent) { LOCK(cs); std::vector entries; @@ -628,7 +631,8 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigne removeConflicts(*tx); ClearPrioritisation(tx->GetHash()); } - for (std::set >::const_iterator it = setWithdrawsSpent.begin(); it != setWithdrawsSpent.end(); it++) { + // Eject any conflicting pegins + for (std::set >::const_iterator it = setPeginsSpent.begin(); it != setPeginsSpent.end(); it++) { std::map, uint256>::const_iterator it2 = mapWithdrawsSpentToTxid.find(*it); if (it2 != mapWithdrawsSpentToTxid.end()) { txiter txit = mapTx.find(it2->second); @@ -679,7 +683,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const LOCK(cs); std::list waitingOnDependants; - std::set > setGlobalWithdrawsSpent; + std::set > setGlobalPeginsSpent; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { unsigned int i = 0; checkTotal += it->GetTxSize(); @@ -757,15 +761,15 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const waitingOnDependants.push_back(&(*it)); else { CValidationState state; - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; bool fCheckResult = tx.IsCoinBase() || - Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight, setWithdrawsSpent, NULL, false); + Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight, setPeginsSpent, NULL, false); assert(fCheckResult); UpdateCoins(tx, mempoolDuplicate, 1000000); - assert(setWithdrawsSpent == it->setWithdrawsSpent); - size_t prevWithdrawsCount = setGlobalWithdrawsSpent.size(); - setGlobalWithdrawsSpent.insert(setWithdrawsSpent.begin(), setWithdrawsSpent.end()); - assert(setGlobalWithdrawsSpent.size() == prevWithdrawsCount + setWithdrawsSpent.size()); + assert(setPeginsSpent == it->setPeginsSpent); + size_t prevWithdrawsCount = setGlobalPeginsSpent.size(); + setGlobalPeginsSpent.insert(setPeginsSpent.begin(), setPeginsSpent.end()); + assert(setGlobalPeginsSpent.size() == prevWithdrawsCount + setPeginsSpent.size()); } } unsigned int stepsSinceLastRemove = 0; @@ -778,15 +782,15 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const stepsSinceLastRemove++; assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; bool fCheckResult = entry->GetTx().IsCoinBase() || - Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight, setWithdrawsSpent, NULL, false); + Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight, setPeginsSpent, NULL, false); assert(fCheckResult); UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); - assert(setWithdrawsSpent == entry->setWithdrawsSpent); - size_t prevWithdrawsCount = setGlobalWithdrawsSpent.size(); - setGlobalWithdrawsSpent.insert(setWithdrawsSpent.begin(), setWithdrawsSpent.end()); - assert(setGlobalWithdrawsSpent.size() == prevWithdrawsCount + setWithdrawsSpent.size()); + assert(setPeginsSpent == entry->setPeginsSpent); + size_t prevWithdrawsCount = setGlobalPeginsSpent.size(); + setGlobalPeginsSpent.insert(setPeginsSpent.begin(), setPeginsSpent.end()); + assert(setGlobalPeginsSpent.size() == prevWithdrawsCount + setPeginsSpent.size()); stepsSinceLastRemove = 0; } } @@ -798,13 +802,13 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(&tx == it->second); } - for (std::set >::const_iterator it = setGlobalWithdrawsSpent.begin(); it != setGlobalWithdrawsSpent.end(); it++) { + for (std::set >::const_iterator it = setGlobalPeginsSpent.begin(); it != setGlobalPeginsSpent.end(); it++) { assert(!pcoins->IsWithdrawSpent(*it)); } for (std::map, uint256>::const_iterator it = mapWithdrawsSpentToTxid.begin(); it != mapWithdrawsSpentToTxid.end(); it++) { - assert(setGlobalWithdrawsSpent.erase(it->first)); + assert(setGlobalPeginsSpent.erase(it->first)); } - assert(setGlobalWithdrawsSpent.size() == 0); + assert(setGlobalPeginsSpent.size() == 0); assert(totalTxSize == checkTotal); assert(innerUsage == cachedInnerUsage); diff --git a/src/txmempool.h b/src/txmempool.h index ae939aa4c0..059c39c5da 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -112,12 +112,12 @@ class CTxMemPoolEntry int64_t nSigOpCostWithAncestors; public: - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, CAmount _inChainInputValue, bool spendsCoinbase, - int64_t nSigOpsCost, LockPoints lp, std::set >& setWithdrawsSpent); + int64_t nSigOpsCost, LockPoints lp, std::set >& setPeginsSpent); CTxMemPoolEntry(const CTxMemPoolEntry& other); @@ -544,7 +544,7 @@ class CTxMemPool void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); void removeConflicts(const CTransaction &tx); void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, - const std::set >& setWithdrawsSpent); + const std::set >& setPeginsSpent); void clear(); void _clear(); //lock free bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb); diff --git a/src/validation.cpp b/src/validation.cpp index 88b5f1ea03..6388c83726 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1089,7 +1089,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C { CCoinsView dummy; CCoinsViewCache view(&dummy); - std::set > setWithdrawsSpent; + std::set > setPeginsSpent; LockPoints lp; { @@ -1122,24 +1122,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (!view.HaveInputs(tx)) return state.Invalid(false, REJECT_DUPLICATE, "bad-txns-inputs-spent"); - // We disable replacement of peg-ins as they are spendable-by-anyone - BOOST_FOREACH(const CTxIn &txin, tx.vin) - { - CCoins coins; - bool ret; - ret = view.GetCoins(txin.prevout.hash, coins); - assert(ret); - if (coins.vout[txin.prevout.n].scriptPubKey.IsWithdrawLock() && txin.scriptSig.IsWithdrawProof()) { - std::pair outpoint = std::make_pair(coins.vout[txin.prevout.n].scriptPubKey.GetWithdrawLockGenesisHash(), txin.scriptSig.GetWithdrawSpent()); - if (pool.mapNextTx.count(txin.prevout)) - return state.Invalid(false, REJECT_CONFLICT, "txn-mempool-replace-withdraw"); - - if (view.IsWithdrawSpent(outpoint)) - return state.Invalid(false, REJECT_CONFLICT, "withdraw-already-claimed"); - setWithdrawsSpent.insert(outpoint); - } - } - // Bring the best block into scope view.GetBestBlock(); @@ -1177,8 +1159,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C CAmount inChainInputValue; double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue); - bool fIsWithdrawLockSpender = false; - // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. // Also track withdraw lock spends to allow them through free relay @@ -1189,13 +1169,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C fSpendsCoinbase = true; break; } - if (coins->vout[txin.prevout.n].scriptPubKey.IsWithdrawLock()) { - fIsWithdrawLockSpender = true; - } } CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, dPriority, chainActive.Height(), - inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp, setWithdrawsSpent); + inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp, setPeginsSpent); unsigned int nSize = entry.GetTxSize(); // Check that the transaction doesn't have an excessive number of @@ -1212,8 +1189,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee)); } - // No transactions are allowed below minRelayTxFee except from disconnected blocks and withdraw lock spends - if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize) && !fIsWithdrawLockSpender) + // No transactions are allowed below minRelayTxFee except from disconnected blocks + if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) { return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met"); } @@ -1383,21 +1360,21 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C scriptVerifyFlags = GetArg("-promiscuousmempoolflags", scriptVerifyFlags); } - std::set > setWithdrawsSpent2; + std::set > setPeginsSpent2; // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. PrecomputedTransactionData txdata(tx); - if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, txdata, setWithdrawsSpent2)) { + if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, txdata, setPeginsSpent2)) { // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - setWithdrawsSpent2.clear(); + setPeginsSpent2.clear(); CValidationState stateDummy; // Want reported failures to be from first CheckInputs - if (!tx.HasWitness() && CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata, setWithdrawsSpent2)) { - setWithdrawsSpent2.clear(); - if (!CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata, setWithdrawsSpent2)) { - setWithdrawsSpent2.clear(); + if (!tx.HasWitness() && CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata, setPeginsSpent2)) { + setPeginsSpent2.clear(); + if (!CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata, setPeginsSpent2)) { + setPeginsSpent2.clear(); // Only the witness is missing, so the transaction itself may be fine. state.SetCorruptionPossible(); } @@ -1405,8 +1382,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return false; // state filled in by CheckInputs } - assert(setWithdrawsSpent2 == setWithdrawsSpent); - setWithdrawsSpent2.clear(); + assert(setPeginsSpent2 == setPeginsSpent); + setPeginsSpent2.clear(); // Check again against just the consensus-critical mandatory script // verification flags, in case of bugs in the standard flags that cause @@ -1417,13 +1394,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, setWithdrawsSpent2)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, setPeginsSpent2)) { return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); } - assert(setWithdrawsSpent2 == setWithdrawsSpent); + assert(setPeginsSpent2 == setPeginsSpent); // Remove conflicting transactions from the mempool BOOST_FOREACH(const CTxMemPool::txiter it, allConflicting) @@ -1546,145 +1523,6 @@ bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus return false; } -bool utxoSort(const std::pair& a, const std::pair& b) { - return a.second > b.second; -} - -/** Select Inputs which lock at least nAmount to the given chain */ -bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::vector >& res) { - res.clear(); - - LOCK2(cs_main, mempool.cs); - - std::vector > locksCreated; - bool locksChanged = false; - // If this fails, we should still try to grab from mempool. - if (!pblocktree->ReadLocksCreated(genesisHash, locksCreated)) { - locksCreated.clear(); - } - - //For faster random esasure - std::list > locksList; - std::copy(locksCreated.begin(), locksCreated.end(), std::back_inserter(locksList)); - - unsigned int skippedLocks = 0; - while (locksList.size() - skippedLocks > 0) { - uint64_t idx = GetRand(locksList.size() - skippedLocks); - std::list >::iterator it = locksList.begin(); - std::advance(it, idx); - const std::pair &lock = (*it); - //Should run this first - //Erase locks that have been spent in an active block - CCoins coins; - if (!pcoinsTip->GetCoins(lock.first.hash, coins) || !coins.IsAvailable(lock.first.n)) { - locksList.erase(it); - locksChanged = true; - continue; - } - - //Move too-small locks or locks currently spent in mempool to back of list - if (lock.second < nAmount || - mempool.mapNextTx.count(COutPoint(lock.first.hash, lock.first.n))) { - locksList.push_back(lock); - locksList.erase(it); - skippedLocks++; - continue; - } - - assert(coins.vout[lock.first.n].nValue.IsExplicit() && coins.vout[lock.first.n].nValue.GetAmount() == lock.second); - res.push_back(lock); - break; - } - if (locksChanged) { - //Convert back for serialization - std::vector > vChangedLocks(locksList.begin(), locksList.end()); - pblocktree->ReWriteLocksCreated(genesisHash, vChangedLocks); - } - //Found single lock large enough - if (res.size()) { - return true; - } - - CAmount nTotal = 0; - //Gather up smaller locked outputs for aggregation. - for (std::list >::iterator it = locksList.begin(); it != locksList.end(); it++) { - CCoins coins; - if (!pcoinsTip->GetCoins(it->first.hash, coins) || !coins.IsAvailable(it->first.n)) { - it = locksList.erase(it); - it--; - locksChanged = true; - continue; - } - - if (mempool.mapNextTx.count(COutPoint(it->first.hash, it->first.n))) { - continue; - } - - assert(coins.vout[it->first.n].nValue.IsExplicit() && coins.vout[it->first.n].nValue.GetAmount() == it->second); - res.push_back(*it); - - nTotal += it->second; - assert(MoneyRange(nTotal)); - } - - if (locksChanged) { - //Convert back for serialization - std::vector > vChangedLocks(locksList.begin(), locksList.end()); - pblocktree->ReWriteLocksCreated(genesisHash, vChangedLocks); - } - - //If not enough, combine mempool locks - if (nTotal < nAmount) { - std::vector vMempoolTxn; - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) { - vMempoolTxn.push_back(&e.GetTx()); - } - - std::random_shuffle(vMempoolTxn.begin(), vMempoolTxn.end()); - - BOOST_FOREACH(const CTransaction* ptx, vMempoolTxn) { - const CTransaction& tx = *ptx; - for (unsigned int j = 0; j < tx.vout.size() && nTotal < nAmount; j++) { - CTxOut txout = tx.vout[j]; - if (!txout.scriptPubKey.IsWithdrawLock()) { - continue; - } - - uint256 withdrawGenHash = txout.scriptPubKey.GetWithdrawLockGenesisHash(); - if (genesisHash != withdrawGenHash) { - continue; - } - - // Only written locks are filtered previously for invalid type - if (txout.nValue.IsCommitment() || txout.nAsset.IsCommitment() || txout.nAsset.GetAsset() != Params().GetConsensus().pegged_asset) { - continue; - } - - if (mempool.mapNextTx.count(COutPoint(tx.GetHash(), j))) { - continue; - } - - res.push_back(std::make_pair(COutPoint(tx.GetHash(), j), txout.nValue.GetAmount())); - nTotal += txout.nValue.GetAmount(); - if (nTotal >= nAmount) { - return true; - } - } - } - return false; - } - - //res list is already randomized - nTotal = 0; - size_t i = 0; - for (; i < res.size() && nTotal < nAmount; i++) { - nTotal += res[i].second; - } - - res.resize(i); - return true; -} - ////////////////////////////////////////////////////////////////////////////// // // CBlock and CBlockIndex @@ -1921,11 +1759,6 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund if (nPos >= coins->vout.size() || coins->vout[nPos].IsNull()) assert(false); - if (coins->vout[txin.prevout.n].scriptPubKey.IsWithdrawLock() && txin.scriptSig.IsWithdrawProof()) { - std::pair outpoint = std::make_pair(coins->vout[txin.prevout.n].scriptPubKey.GetWithdrawLockGenesisHash(), txin.scriptSig.GetWithdrawSpent()); - inputs.SetWithdrawSpent(outpoint, true); - } - // mark an outpoint spent, and construct undo information txundo.vprevout.push_back(CTxInUndo(coins->vout[nPos])); coins->Spend(nPos); @@ -1950,7 +1783,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; - if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, amountPreviousInput, Params().GetConsensus().fedpegScript, cacheStore, *txdata), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) { return false; } return true; @@ -1964,7 +1797,7 @@ int GetSpendHeight(const CCoinsViewCache& inputs) } namespace Consensus { -bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, std::set >& setWithdrawsSpent, std::vector *pvChecks, const bool cacheStore) +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, std::set >& setPeginsSpent, std::vector *pvChecks, const bool cacheStore) { // This doesn't trigger the DoS code on purpose; if it did, it would make it easier // for an attacker to attempt to split the network. @@ -1994,17 +1827,6 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange"); } - if (coins->vout[prevout.n].scriptPubKey.IsWithdrawLock() && tx.vin[i].scriptSig.IsWithdrawProof()) { - uint256 genesisHash(coins->vout[prevout.n].scriptPubKey.GetWithdrawLockGenesisHash()); - COutPoint withdrawSpent(tx.vin[i].scriptSig.GetWithdrawSpent()); - std::pair withdraw = std::make_pair(genesisHash, withdrawSpent); - if (inputs.IsWithdrawSpent(withdraw)) - return state.Invalid(false, REJECT_INVALID, "bad-txns-double-withdraw", strprintf("Double-withdraw of %s:%d", withdrawSpent.hash.ToString(), withdrawSpent.n)); - if (setWithdrawsSpent.count(withdraw)) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-double-withdraw-in-obj", false, - strprintf("Double-withdraw of %s:%d in single tx/block", withdrawSpent.hash.ToString(), withdrawSpent.n)); - setWithdrawsSpent.insert(withdraw); - } } // Tally transaction fees @@ -2018,11 +1840,11 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::set >& setWithdrawsSpent, std::vector *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::set >& setPeginsSpent, std::vector *pvChecks) { if (!tx.IsCoinBase()) { - if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), setWithdrawsSpent, pvChecks, cacheStore)) + if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), setPeginsSpent, pvChecks, cacheStore)) return false; if (pvChecks) @@ -2038,14 +1860,13 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // Of course, if an assumed valid block is invalid due to false scriptSigs // this optimization would allow an invalid chain to be accepted. if (fScriptChecks) { - CAmount prevValueIn = -1; for (unsigned int i = 0; i < tx.vin.size(); i++) { const COutPoint &prevout = tx.vin[i].prevout; const CCoins* coins = inputs.AccessCoins(prevout.hash); assert(coins); // Verify signature - CCheck* check = new CScriptCheck(*coins, tx, i, prevValueIn, flags, cacheStore, &txdata); + CCheck* check = new CScriptCheck(*coins, tx, i, flags, cacheStore, &txdata); ScriptError serror = QueueCheck(pvChecks, check); if (serror != SCRIPT_ERR_OK) { if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { @@ -2055,7 +1876,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // arguments; if so, don't trigger DoS protection to // avoid splitting the network between upgraded and // non-upgraded nodes. - CScriptCheck check2(*coins, tx, i, prevValueIn, + CScriptCheck check2(*coins, tx, i, flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(serror))); @@ -2067,16 +1888,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // as to the correct behavior - we may want to continue // peering with non-upgraded nodes even after soft-fork // super-majority signaling has occurred. - if (serror == SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED) - return state.Invalid(false, REJECT_SCRIPT, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(serror))); - else - return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(serror))); + return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(serror))); } - const CConfidentialValue& value = coins->vout[tx.vin[i].prevout.n].nValue; - if (value.IsExplicit()) - prevValueIn = value.GetAmount(); - else - prevValueIn = -1; } } } @@ -2192,20 +2005,6 @@ bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint coins->vout.resize(out.n+1); coins->vout[out.n] = undo.txout; - if (undo.txout.scriptPubKey.IsWithdrawLock()) { - if (!txin.scriptSig.IsWithdrawProof()) { - if (!txin.scriptSig.IsPushOnly()) - fClean = fClean && error("%s: lock spent by non-proof", __func__); - } else { - std::pair outpoint = std::make_pair(undo.txout.scriptPubKey.GetWithdrawLockGenesisHash(), txin.scriptSig.GetWithdrawSpent()); - bool fSpent = view.IsWithdrawSpent(outpoint); - if (!fSpent) - fClean = fClean && error("%s: withdraw not marked spent", __func__); - else - view.SetWithdrawSpent(outpoint, false); - } - } - return fClean; } @@ -2458,7 +2257,7 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, std::set >* setWithdrawsSpent, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, std::set >* setPeginsSpent, bool fJustCheck) { AssertLockHeld(cs_main); @@ -2481,19 +2280,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CTxUndo undoDummy; UpdateCoins(tx, view, undoDummy, pindex->nHeight); - CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); - vPos.push_back(std::make_pair(tx.GetHash(), pos)); - for (unsigned int i = 0; i < tx.vout.size(); i++) { - CTxOut txout= tx.vout[i]; - if (txout.scriptPubKey.IsWithdrawLock() && txout.nValue.IsExplicit() && txout.nAsset.IsExplicit() && txout.nAsset.GetAsset() == Params().GetConsensus().pegged_asset) - mLocksCreated.insert(std::make_pair(txout.scriptPubKey.GetWithdrawLockGenesisHash(), std::make_pair(COutPoint(tx.GetHash(), i), txout.nValue.GetAmount()))); - } - - if (fTxIndex) - if (!pblocktree->WriteTxIndex(vPos)) - return AbortNode(state, "Failed to write transaction index"); - pblocktree->WriteLocksCreated(mLocksCreated); - view.SetBestBlock(pindex->GetBlockHash()); } return true; @@ -2596,9 +2382,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_NULLDUMMY; } - //Enforce WITHDRAWPROOFVERIFY - flags |= SCRIPT_VERIFY_WITHDRAW; - int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); @@ -2613,12 +2396,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector > vPos; vPos.reserve(block.vtx.size()); - std::multimap > mLocksCreated; blockundo.vtxundo.reserve(block.vtx.size() - 1); std::vector txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated - std::set > setWithdrawsSpentDummy; + // Used when ConnectBlock() results are unneeded for mempool ejection + std::set > setPeginsSpentDummy; for (unsigned int i = 0; i < block.vtx.size(); i++) { @@ -2660,9 +2443,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { std::vector vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ - if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], setWithdrawsSpent == NULL ? setWithdrawsSpentDummy : *setWithdrawsSpent, nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], setPeginsSpent == NULL ? setPeginsSpentDummy : *setPeginsSpent, nScriptCheckThreads ? &vChecks : NULL)) { return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); + } control.Add(vChecks); } @@ -2675,12 +2459,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin vPos.push_back(std::make_pair(tx.GetHash(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); - for (unsigned int j = 0; j < tx.vout.size(); j++) { - CTxOut txout = tx.vout[j]; - if (txout.scriptPubKey.IsWithdrawLock() && txout.nValue.IsExplicit() && txout.nAsset.IsExplicit() && txout.nAsset.GetAsset() == Params().GetConsensus().pegged_asset) { - mLocksCreated.insert(std::make_pair(txout.scriptPubKey.GetWithdrawLockGenesisHash(), std::make_pair(COutPoint(tx.GetHash(), j), txout.nValue.GetAmount()))); - } - } if (!tx.HasValidFee()) return state.DoS(100, error("ConnectBlock(): transaction fee overflowed"), REJECT_INVALID, "bad-fee-outofrange"); mapFees += tx.GetFee(); @@ -2699,9 +2477,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin blockReward[policyAsset]), REJECT_INVALID, "bad-cb-amount"); - //Don't DoS ban in case of RPC script check failure if (!control.Wait()) - return state.Invalid(false, REJECT_SCRIPT); + return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed"); int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2; LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime4 - nTime2), nInputs <= 1 ? 0 : 0.001 * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * 0.000001); @@ -2731,8 +2508,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); - pblocktree->WriteLocksCreated(mLocksCreated); - // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -3030,34 +2805,16 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1; int64_t nTime3; LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); - std::set > setWithdrawsSpent; + // For mempool removal with pegin conflicts + std::set > setPeginsSpent; { CCoinsViewCache view(pcoinsTip); - bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, chainparams, &setWithdrawsSpent); + bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, chainparams, &setPeginsSpent); GetMainSignals().BlockChecked(blockConnecting, state); if (!rv) { if (state.IsInvalid()) { InvalidBlockFound(pindexNew, state); - //Possibly result of RPC to bitcoind failure - //or unseen Bitcoin blocks. - if (state.GetRejectCode() == REJECT_SCRIPT) { - //Write queue of invalid blocks that - //must be cleared to continue operation - std::vector vinvalidBlocks; - pblocktree->ReadInvalidBlockQueue(vinvalidBlocks); - bool blockAlreadyInvalid = false; - BOOST_FOREACH(uint256& hash, vinvalidBlocks) { - if (hash == pblock->GetHash()) { - blockAlreadyInvalid = true; - break; - } - } - if (!blockAlreadyInvalid) { - vinvalidBlocks.push_back(pblock->GetHash()); - pblocktree->WriteInvalidBlockQueue(vinvalidBlocks); - } - } - } + } return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } @@ -3074,7 +2831,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool.; - mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight, setWithdrawsSpent); + mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight, setPeginsSpent); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); diff --git a/src/validation.h b/src/validation.h index 7b40f4358c..492f3efa60 100644 --- a/src/validation.h +++ b/src/validation.h @@ -370,7 +370,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i * instead of being performed inline. */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::set >& setWithdrawsSpent, + unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::set >& setPeginsSpent, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ @@ -388,7 +388,7 @@ namespace Consensus { * This does not modify the UTXO set. This does not check scripts and sigs. * Preconditions: tx.IsCoinBase() is false. */ -bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, std::set >& setWithdrawsSpent, std::vector *pvChecks, const bool cacheStore); +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, std::set >& setPeginsSpent, std::vector *pvChecks, const bool cacheStore); } // namespace Consensus @@ -478,7 +478,6 @@ class CScriptCheck : public CCheck private: CScript scriptPubKey; CConfidentialValue amount; - CConfidentialValue amountPreviousInput; const CTransaction *ptxTo; unsigned int nIn; unsigned int nFlags; @@ -486,9 +485,8 @@ class CScriptCheck : public CCheck PrecomputedTransactionData *txdata; public: - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, const CConfidentialValue& amountPreviousInputIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), - amountPreviousInput(amountPreviousInputIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), txdata(txdataIn) { } bool operator()(); @@ -517,7 +515,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co * Validity checks that depend on the UTXO set are also done; ConnectBlock() * can fail if those validity checks fail (among other reasons). */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, - const CChainParams& chainparams, std::set >* setWithdrawsSpent = NULL, bool fJustCheck = false); + const CChainParams& chainparams, std::set >* setPeginsSpent = NULL, bool fJustCheck = false); /** Undo the effects of this block (with given index) on the UTXO set represented by coins. * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f82c726e41..5f63bb4177 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3388,390 +3388,6 @@ class CSecp256k1Init { static CSecp256k1Init instance_of_csecp256k1; } -CScriptID calculate_contract(const CScript& federationRedeemScript, const CBitcoinAddress& destAddress, const unsigned char nonce[16], unsigned char fullcontract[40]) { - fullcontract[0] = (unsigned char)'P'; - fullcontract[1] = (unsigned char)'2'; - if (destAddress.IsScript()) - fullcontract[2] = (unsigned char)'S'; - else - fullcontract[2] = (unsigned char)'P'; - fullcontract[3] = (unsigned char)'H'; - memcpy(fullcontract + 4, nonce, 16); - - std::vector destHash; - CScript destScript = GetScriptForDestination(destAddress.Get()); - CScript::iterator scriptIt = destScript.begin(); - opcodetype opcodeTmp; - assert(destScript.GetOp(scriptIt, opcodeTmp, destHash)); - if (!destAddress.IsScript()) { - assert(opcodeTmp == OP_DUP); - assert(destScript.GetOp(scriptIt, opcodeTmp, destHash)); - } - assert(opcodeTmp == OP_HASH160); - assert(destScript.GetOp(scriptIt, opcodeTmp, destHash)); - assert(opcodeTmp == 0x14 && destHash.size() == 20); - memcpy(fullcontract + 4 + 16, &destHash[0], destHash.size()); - - CScript scriptDestination(federationRedeemScript); - { - CScript::iterator sdpc = scriptDestination.begin(); - vector vch; - while (scriptDestination.GetOp(sdpc, opcodeTmp, vch)) - { - assert((vch.size() == 33 && opcodeTmp < OP_PUSHDATA4) || - (opcodeTmp <= OP_16 && opcodeTmp >= OP_1) || opcodeTmp == OP_CHECKMULTISIG); - if (vch.size() == 33) - { - unsigned char tweak[32]; - size_t pub_len = 33; - int ret; - unsigned char *pub_start = &(*(sdpc - pub_len)); - CHMAC_SHA256(pub_start, pub_len).Write(fullcontract, 40).Finalize(tweak); - secp256k1_pubkey watchman; - secp256k1_pubkey tweaked; - ret = secp256k1_ec_pubkey_parse(secp256k1_ctx, &watchman, pub_start, pub_len); - assert(ret == 1); - ret = secp256k1_ec_pubkey_parse(secp256k1_ctx, &tweaked, pub_start, pub_len); - assert(ret == 1); - // If someone creates a tweak that makes this fail, they broke SHA256 - ret = secp256k1_ec_pubkey_tweak_add(secp256k1_ctx, &tweaked, tweak); - assert(ret == 1); - ret = secp256k1_ec_pubkey_serialize(secp256k1_ctx, pub_start, &pub_len, &tweaked, SECP256K1_EC_COMPRESSED); - assert(ret == 1); - assert(pub_len == 33); - - // Sanity checks to reduce pegin risk. If the tweaked - // value flips a bit, we may lose pegin funds irretrievably. - // We take the tweak, derive its pubkey and check that - // `tweaked - watchman = tweak` to check the computation - // two different ways - secp256k1_pubkey tweaked2; - ret = secp256k1_ec_pubkey_create(secp256k1_ctx, &tweaked2, tweak); - assert(ret); - ret = secp256k1_ec_pubkey_negate(secp256k1_ctx, &watchman); - assert(ret); - secp256k1_pubkey* pubkey_combined[2]; - pubkey_combined[0] = &watchman; - pubkey_combined[1] = &tweaked; - secp256k1_pubkey maybe_tweaked2; - ret = secp256k1_ec_pubkey_combine(secp256k1_ctx, &maybe_tweaked2, pubkey_combined, 2); - assert(ret); - assert(!memcmp(&maybe_tweaked2, &tweaked2, 64)); - } - } - } - - return CScriptID(scriptDestination); -} - -UniValue getpeginaddress(const JSONRPCRequest& request) -{ - if (!EnsureWalletIsAvailable(request.fHelp)) - return NullUniValue; - - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - "getpeginaddress ( \"account\" )\n" - "\nReturns information needed for claimpegin to move coins to the sidechain.\n" - "The user should send coins from their Bitcoin wallet to the mainchain_address returned.\n" - "IMPORTANT: Like getaddress, getpeginaddress adds new secrets to wallet.dat, necessitating backup on a regular basis.\n" - - "\nArguments:\n" - "1. \"account\" (string, optional) The account name for the address to be linked to. if not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n" - "\nResult:\n" - "\"mainchain_address\" (string) Mainchain Bitcoin deposit address to send bitcoin to\n" - "\"sidechain_address\" (string) The sidechain address in this wallet which must be used in `claimpegin` to retrieve pegged-in funds\n" - "\nExamples:\n" - + HelpExampleCli("getpeginaddress", "") - + HelpExampleCli("getpeginaddress", "\"\"") - + HelpExampleCli("getpeginaddress", "\"myaccount\"") - + HelpExampleRpc("getpeginaddress", "\"myaccount\"") - ); - - //Creates new address for receiving unlocked utxos - CBitcoinAddress address(CBitcoinAddress(getnewaddress(request).get_str()).GetUnblinded()); - - //Call contracthashtool, get deposit address on mainchain. - unsigned char nonce[16]; - memset(nonce, 0, sizeof(nonce)); - unsigned char fullcontract[40]; - CParentBitcoinAddress destAddr(calculate_contract(Params().GetConsensus().fedpegScript, address, nonce, fullcontract)); - - UniValue fundinginfo(UniValue::VOBJ); - - AuditLogPrintf("%s : getpeginaddress mainchain_address: %s sidechain_address: %s\n", getUser(), destAddr.ToString(), address.ToString()); - - fundinginfo.pushKV("mainchain_address", destAddr.ToString()); - fundinginfo.pushKV("sidechain_address", address.ToString()); - return fundinginfo; -} - -UniValue sendtomainchain(const JSONRPCRequest& request) -{ - if (!EnsureWalletIsAvailable(request.fHelp)) - return NullUniValue; - - if (request.fHelp || request.params.size() != 2) - throw runtime_error( - "sendtomainchain mainchainaddress amount\n" - "\nSends sidechain funds to the given mainchain address, through the federated withdraw mechanism\n" - + HelpRequiringPassphrase() + - "\nArguments:\n" - "1. \"address\" (string, required) The destination address on Bitcoin mainchain\n" - "2. \"amount\" (numeric, required) The amount being sent to Bitcoin mainchain\n" - "\nResult:\n" - "\"txid\" (string) Transaction ID of the resulting sidechain transaction\n" - "\nExamples:\n" - + HelpExampleCli("sendtomainchain", "\"mgWEy4vBJSHt3mC8C2SEWJQitifb4qeZQq\" 0.1") - + HelpExampleRpc("sendtomainchain", "\"mgWEy4vBJSHt3mC8C2SEWJQitifb4qeZQq\" 0.1") - ); - - LOCK2(cs_main, pwalletMain->cs_wallet); - - EnsureWalletIsUnlocked(); - - CParentBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - - CAmount nAmount = AmountFromValue(request.params[1]); - if (nAmount <= 0) - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); - - // Parse Bitcoin address for asm field - CScript scriptPubKeyMainchain(GetScriptForDestination(address.Get())); - CScript::const_iterator pc(scriptPubKeyMainchain.begin()); - CScript::const_iterator pend(scriptPubKeyMainchain.end()); - opcodetype type; - vector vData; - while (pc != pend) { - scriptPubKeyMainchain.GetOp(pc, type, vData); - if (type == OP_HASH160) { - scriptPubKeyMainchain.GetOp(pc, type, vData); - break; - } - } - assert(pc != pend && type == 0x14); - - CScript scriptPubKey; - - vector hex; - hex.push_back((unsigned char)'P'); - hex.push_back((unsigned char)'2'); - if (scriptPubKeyMainchain.IsPayToScriptHash()) - hex.push_back((unsigned char)'S'); - else - hex.push_back((unsigned char)'P'); - hex.push_back((unsigned char)'H'); - hex.insert(hex.end(), vData.begin(), vData.end()); - - uint256 genesisBlockHash = Params().ParentGenesisBlockHash(); - - scriptPubKey << hex; - scriptPubKey << OP_DROP; - scriptPubKey << std::vector(genesisBlockHash.begin(), genesisBlockHash.end()); - scriptPubKey << OP_WITHDRAWPROOFVERIFY; - assert(scriptPubKey.IsWithdrawLock()); - - EnsureWalletIsUnlocked(); - - CWalletTx wtxNew; - SendMoney(scriptPubKey, nAmount, Params().GetConsensus().pegged_asset, false, CPubKey(), wtxNew, true); - - std::string blinds; - for (unsigned int i=0; ivout.size(); i++) { - blinds += "blind:" + wtxNew.GetOutputBlindingFactor(i).ToString() + "\n"; - } - - AuditLogPrintf("%s : sendtomainchain %s\nblinds:\n%s\n", getUser(), wtxNew.tx->GetHash().GetHex(), blinds); - - return wtxNew.GetHash().GetHex(); -} - -extern UniValue sendrawtransaction(const JSONRPCRequest& request); - -unsigned int GetPeginTxnOutputIndex(const Sidechain::Bitcoin::CTransaction& txn, const CBitcoinAddress& sidechainAddress, unsigned char* fullcontract) -{ - unsigned char nonce[16]; - memset(nonce, 0, sizeof(nonce)); - unsigned int nOut = 0; - //Call contracthashtool - CScript mainchain_script = GetScriptForDestination(calculate_contract(Params().GetConsensus().fedpegScript, sidechainAddress, &nonce[0], fullcontract)); - for (; nOut < txn.vout.size(); nOut++) - if (txn.vout[nOut].scriptPubKey == mainchain_script) - break; - return nOut; -} - -UniValue claimpegin(const JSONRPCRequest& request) -{ - - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw std::runtime_error( - "claimpegin bitcoinTx txoutproof ( sidechain_address )\n" - "\nClaim coins from the main chain by creating a withdraw transaction with the necessary metadata after the corresponding Bitcoin transaction.\n" - "Note that the transaction will not be relayed unless it is buried at least 102 blocks deep.\n" - "If a transaction is not relayed it may require manual addition to a functionary mempool in order for it to be mined.\n" - "\nArguments:\n" - "1. \"bitcoinTx\" (string, required) The raw bitcoin transaction (in hex) depositing bitcoin to the mainchain_address generated by getpeginaddress\n" - "2. \"txoutproof\" (string, required) A rawtxoutproof (in hex) generated by bitcoind's `gettxoutproof` containing a proof of only bitcoinTx\n" - "3. \"sidechain_address\" (string, optional) The sidechain_address generated by getpeginaddress. Only needed if not in wallet.\n" - "\nResult:\n" - "\"txid\" (string) Txid of the resulting sidechain transaction\n" - "\nExamples:\n" -//XXX: Fix the examples - + HelpExampleCli("claimpegin", "\"2NEqRzqBst5rWrVx7SpwG37T17mvehLhKaN\", \"010000000151ef48c69a67700e6b30a4413eda4b631802c4514d7a09971dc12c703917e39f000000006c4730440220158c57dc3e80a826e4e348b7f530a9a9a3bb6b2913b089c03d08d0bdbf4e0d5b02201a8acf14cecbb74373894816fa69efa96e8f4e0ca633dcf99c99251200149c7b8323210214fd9d286f6aa8a7bdd043b1d5f3e3cdf754e9f1e50b65e5648704b01b2febb0acffffffff0100000000000000000000000000\" \"d50c8eec366e98b258414509d88e72ed0d2b24f63256e076d2b9d0ac3d55abc1\"") - + HelpExampleRpc("claimpegin", "\"2NEqRzqBst5rWrVx7SpwG37T17mvehLhKaN\", \"010000000151ef48c69a67700e6b30a4413eda4b631802c4514d7a09971dc12c703917e39f000000006c4730440220158c57dc3e80a826e4e348b7f530a9a9a3bb6b2913b089c03d08d0bdbf4e0d5b02201a8acf14cecbb74373894816fa69efa96e8f4e0ca633dcf99c99251200149c7b8323210214fd9d286f6aa8a7bdd043b1d5f3e3cdf754e9f1e50b65e5648704b01b2febb0acffffffff0100000000000000000000000000\", \"d50c8eec366e98b258414509d88e72ed0d2b24f63256e076d2b9d0ac3d55abc1\"") - ); - - if (IsInitialBlockDownload()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Peg-ins cannot be completed during initial sync or reindexing."); - } - - if (!IsHex(request.params[0].get_str()) || !IsHex(request.params[1].get_str())) { - throw JSONRPCError(RPC_TYPE_ERROR, "the first two arguments must be hex strings"); - } - - - std::vector txData = ParseHex(request.params[0].get_str()); - CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION); - Sidechain::Bitcoin::CTransactionRef txBTCRef; - try { - ssTx >> txBTCRef; - } - catch (...) { - throw JSONRPCError(RPC_TYPE_ERROR, "The included bitcoinTx is malformed. Are you sure that is the whole string?"); - } - Sidechain::Bitcoin::CTransaction txBTC(*txBTCRef); - - std::vector txOutProofData = ParseHex(request.params[1].get_str()); - CDataStream ssTxOutProof(txOutProofData, SER_NETWORK, PROTOCOL_VERSION); - Sidechain::Bitcoin::CMerkleBlock merkleBlock; - try { - ssTxOutProof >> merkleBlock; - } - catch (...) { - throw JSONRPCError(RPC_TYPE_ERROR, "The included txoutproof is malformed. Are you sure that is the whole string?"); - } - - if (!ssTxOutProof.empty() || !CheckBitcoinProof(merkleBlock.header.GetHash(), merkleBlock.header.nBits)) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid tx out proof"); - - vector txHashes; - vector txIndices; - if (merkleBlock.txn.ExtractMatches(txHashes, txIndices) != merkleBlock.header.hashMerkleRoot) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid tx out proof"); - - if (txHashes.size() != 1 || txHashes[0] != txBTC.GetHash()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "The txoutproof must contain bitcoinTx and only bitcoinTx"); - - unsigned int nOut = 0; - unsigned char fullcontract[40]; - CBitcoinAddress sidechainAddress; - if (request.params.size() > 2) { - sidechainAddress = CBitcoinAddress(request.params[2].get_str()); - if (!sidechainAddress.IsValid()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Given sidechain_address is invalid."); - } - nOut = GetPeginTxnOutputIndex(txBTC, sidechainAddress, fullcontract); - } - else { - // Look through address book for pegin contract value - for (std::map::const_iterator iter = pwalletMain->mapAddressBook.begin(); iter != pwalletMain->mapAddressBook.end(); ++iter) { - sidechainAddress = CBitcoinAddress(iter->first); - nOut = GetPeginTxnOutputIndex(txBTC, sidechainAddress, fullcontract); - if (nOut != txBTC.vout.size()) { - break; - } - } - } - if (nOut == txBTC.vout.size()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Failed to find output in bitcoinTx to the mainchain_address from getpeginaddress"); - CAmount value = txBTC.vout[nOut].nValue; - - uint256 genesisBlockHash = Params().ParentGenesisBlockHash(); - - //Output we're re-locking - CScript relock_spk; - relock_spk << std::vector(genesisBlockHash.begin(), genesisBlockHash.end()); - relock_spk << OP_WITHDRAWPROOFVERIFY; - - if (value > MAX_MONEY / 200) - throw JSONRPCError(RPC_VERIFY_REJECTED, "IsStandard rules prevent pegging-in > 0.105 million BTC reliably at a time - please work with your functionary to mine a large lock-merge transaction first"); - - //Pad the locked outputs by the IsStandard lock dust value - CTxOut dummyTxOut(Params().GetConsensus().pegged_asset, 0, relock_spk); - CAmount lockDust(dummyTxOut.GetDustThreshold(withdrawLockTxFee)); - - LOCK(cs_main); - - std::vector > lockedUTXO; - if (!GetLockedOutputs(genesisBlockHash, value+lockDust, lockedUTXO)) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Failed to find inputs with sufficient value - are you sure bitcoinTx is valid?"); - - while (lockedUTXO.size() != 1) { - CMutableTransaction mtxn; - mtxn.vin.push_back(CTxIn(lockedUTXO[0].first.hash, lockedUTXO[0].first.n, CScript(), ~(uint32_t)0)); - mtxn.vin.push_back(CTxIn(lockedUTXO[1].first.hash, lockedUTXO[1].first.n, CScript(), ~(uint32_t)0)); - CAmount out_value = lockedUTXO[0].second + lockedUTXO[1].second; - mtxn.vout.push_back(CTxOut(Params().GetConsensus().pegged_asset, out_value, relock_spk)); - - CValidationState state; - bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(mtxn), false, &fMissingInputs, NULL, false, true)) - throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("Failed to merge locked outputs, please try again later (%i: %s)", state.GetRejectCode(), state.GetRejectReason())); - - CInv inv(MSG_TX, mtxn.GetHash()); - g_connman->ForEachNode([&inv](CNode* pnode) - { - pnode->PushInventory(inv); - }); - - lockedUTXO.erase(lockedUTXO.begin(), lockedUTXO.begin() + 2); - lockedUTXO.push_back(std::make_pair(COutPoint(mtxn.GetHash(), 0), out_value)); - } - - assert(lockedUTXO.size() == 1 && lockedUTXO[0].second >= value+lockDust); - - uint256 utxo_txid(lockedUTXO[0].first.hash); - uint32_t utxo_vout = lockedUTXO[0].first.n; - CAmount utxo_value = lockedUTXO[0].second; - - - CScript scriptSig; - scriptSig << std::vector(fullcontract, fullcontract + 40); - scriptSig.PushWithdraw(txOutProofData); - scriptSig.PushWithdraw(txData); - scriptSig << nOut; - - //Build the transaction - CMutableTransaction mtxn; - CTxIn txin(utxo_txid, utxo_vout, scriptSig, ~(uint32_t)0); - CTxOut txout(Params().GetConsensus().pegged_asset, value, GetScriptForDestination(sidechainAddress.Get())); - CTxOut txrelock(Params().GetConsensus().pegged_asset, utxo_value - value, relock_spk); - mtxn.vin.push_back(txin); - mtxn.vout.push_back(txout); - mtxn.vout.push_back(txrelock); - - //No signing needed, just send - CTransaction finalTxn(mtxn); - - CValidationState state; - bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(finalTxn), false, &fMissingInputs, NULL, false, true)) - throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("Failed to merge locked outputs, please try again later (%i: %s)", state.GetRejectCode(), state.GetRejectReason())); - - CInv inv(MSG_TX, finalTxn.GetHash()); - g_connman->ForEachNode([&inv](CNode* pnode) - { - pnode->PushInventory(inv); - }); - - AuditLogPrintf("%s : claimpegin %s\n", getUser(), finalTxn.ToString()); - - return finalTxn.GetHash().GetHex(); -} - UniValue issueasset(const JSONRPCRequest& request) { if (!EnsureWalletIsAvailable(request.fHelp)) @@ -4109,14 +3725,12 @@ static const CRPCCommand commands[] = { "wallet", "dumpissuanceblindingkey", &dumpissuanceblindingkey, true, {"txid", "vin"} }, { "wallet", "dumpwallet", &dumpwallet, true, {"filename"} }, { "wallet", "encryptwallet", &encryptwallet, true, {"passphrase"} }, - { "wallet", "claimpegin", &claimpegin, false, {} }, { "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} }, { "wallet", "getaccount", &getaccount, true, {"address"} }, { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, {"account"} }, { "wallet", "getbalance", &getbalance, false, {"account","minconf","include_watchonly"} }, { "wallet", "getnewaddress", &getnewaddress, true, {"account"} }, { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} }, - { "wallet", "getpeginaddress", &getpeginaddress, false, {} }, { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf"} }, { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf"} }, { "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} }, @@ -4147,7 +3761,6 @@ static const CRPCCommand commands[] = { "wallet", "setaccount", &setaccount, true, {"address","account"} }, { "wallet", "reissueasset", &reissueasset, true, {"asset", "assetamount"} }, { "wallet", "signblock", &signblock, true, {} }, - { "wallet", "sendtomainchain", &sendtomainchain, false, {} }, { "wallet", "destroyamount", &destroyamount, false, {"asset", "amount", "comment"} }, { "wallet", "settxfee", &settxfee, true, {"amount"} }, { "wallet", "signmessage", &signmessage, true, {"address","message"} }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a3d470fc69..be0c086b44 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1492,10 +1492,8 @@ void CWalletTx::GetAmounts(list& listReceived, if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable()) { - //Don't alarm user over blank address for withdrawLocks - if (!txout.scriptPubKey.IsWithdrawLock()) - LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", - this->GetHash().ToString()); + LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", + this->GetHash().ToString()); address = CNoDestination(); } @@ -3317,8 +3315,8 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt if (GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) { // Lastly, ensure this tx will pass the mempool's chain limits LockPoints lp; - std::set > setWithdrawsSpent; - CTxMemPoolEntry entry(wtxNew.tx, 0, 0, 0, 0, 0, false, 0, lp, setWithdrawsSpent); + std::set > setPeginsSpent; + CTxMemPoolEntry entry(wtxNew.tx, 0, 0, 0, 0, 0, false, 0, lp, setPeginsSpent); CTxMemPool::setEntries setAncestors; size_t nLimitAncestors = GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); size_t nLimitAncestorSize = GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000;