Use RPC calls to check bitcoin blocks are valid and confirmed

This commit is contained in:
Matt Corallo 2014-12-06 14:38:47 -08:00
parent 6dc16a139c
commit eca4077baa
7 changed files with 62 additions and 5 deletions

View file

@ -10,7 +10,7 @@ using namespace json_spirit;
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
Object CallRPC(const string& strMethod, const Array& params)
Object CallRPC(const string& strMethod, const Array& params, string port)
{
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
throw runtime_error(strprintf(
@ -27,7 +27,9 @@ Object CallRPC(const string& strMethod, const Array& params)
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
if (port == "")
port = GetArg("-rpcport", itostr(BaseParams().RPCPort()));
const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), port);
if (!fConnected)
throw CConnectionFailed("couldn't connect to server");
@ -67,3 +69,26 @@ Object CallRPC(const string& strMethod, const Array& params)
return reply;
}
bool IsConfirmedBitcoinBlock(const uint256& hash, int nMinConfirmationDepth)
{
try {
Array params;
params.push_back(hash.GetHex());
Object reply = CallRPC("getblock", params, GetArg("-rpcconnectport", "18332"));
if (find_value(reply, "error").type() != null_type)
return false;
Value result = find_value(reply, "result");
if (result.type() != obj_type)
return false;
result = find_value(result.get_obj(), "confirmations");
return result.type() == int_type && result.get_int64() >= nMinConfirmationDepth;
} catch (CConnectionFailed& e) {
LogPrintf("ERROR: Lost connection to bitcoind RPC, you will want to restart after fixing this!\n");
return false;
} catch (...) {
LogPrintf("ERROR: Failure connecting to bitcoind RPC, you will want to restart after fixing this!\n");
return false;
}
return true;
}

View file

@ -8,6 +8,7 @@
#include "rpcclient.h"
#include "rpcprotocol.h"
#include "uint256.h"
#include <string>
@ -25,6 +26,7 @@ public:
};
json_spirit::Object CallRPC(const std::string& strMethod, const json_spirit::Array& params);
json_spirit::Object CallRPC(const std::string& strMethod, const json_spirit::Array& params, std::string port="");
bool IsConfirmedBitcoinBlock(const uint256& hash, int nMinConfirmationDepth);
#endif // BITCOIN_CALLRPC_H

View file

@ -8,6 +8,9 @@
#include <secp256k1.h>
#define FEDERATED_PEG_SIDECHAIN_ONLY
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
#include "callrpc.h"
#endif
#include "primitives/transaction.h"
#include "crypto/ripemd160.h"
@ -23,6 +26,7 @@
#include "streams.h"
#include "uint256.h"
#include "utilstrencodings.h"
#include "util.h"
using namespace std;
@ -1285,7 +1289,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_SECONDSCRIPT);
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
//TODO: Check that we're spending from a valid, buried bitcoin block
if (!GetBoolArg("-blindtrust", true) && !checker.IsConfirmedBitcoinBlock(merkleBlock.header.GetHash(), flags & SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED))
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED);
#endif
} catch (std::exception& e) {
// Probably invalid encoding of something which was deserialized
@ -1712,6 +1717,13 @@ CAmount TransactionSignatureChecker::GetValueInPrevIn() const
return nInMinusOneValue;
}
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
bool TransactionSignatureChecker::IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements) const
{
return ::IsConfirmedBitcoinBlock(hash, fConservativeConfirmationRequirements ? 10 : 8);
}
#endif
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);

View file

@ -82,6 +82,9 @@ enum
// Execute sidechain-related opcodes instead of treating them as NOPs
SCRIPT_VERIFY_WITHDRAW = (1U << 11),
// Dirty hack to require a higher bar of bitcoin block confirmation in mempool
SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED = (1U << 12)
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
@ -117,6 +120,14 @@ public:
return -1;
}
#define FEDERATED_PEG_SIDECHAIN_ONLY
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
virtual bool IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements) const
{
return false;
}
#endif
virtual ~BaseSignatureChecker() {}
};
@ -157,6 +168,9 @@ public:
CAmount GetValueIn() const;
CAmount GetValueInPrevIn() const;
CAmount GetTransactionFee() const;
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
bool IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements) const;
#endif
};
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);

View file

@ -79,6 +79,8 @@ const char* ScriptErrorString(const ScriptError serror)
return "Withdraw proof validation failed - locktime was not set correctly";
case SCRIPT_ERR_WITHDRAW_VERIFY_SECONDSCRIPT:
return "Withdraw proof validation failed - second script validation failed";
case SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED:
return "Withdraw proof validation failed - lock block was not sufficiently confirmed on sending chain";
case SCRIPT_ERR_REORG_VERIFY_FORMAT:
return "Reorg/Fraud proof validation failed - invalid proof format";
case SCRIPT_ERR_REORG_VERIFY_FRAUD_BLOCK:

View file

@ -58,6 +58,7 @@ typedef enum ScriptError_t
SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT,
SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTIME,
SCRIPT_ERR_WITHDRAW_VERIFY_SECONDSCRIPT,
SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED,
SCRIPT_ERR_REORG_VERIFY_FORMAT,
SCRIPT_ERR_REORG_VERIFY_FRAUD_BLOCK,
SCRIPT_ERR_REORG_VERIFY_FRAUD_ORIG_BLOCK,

View file

@ -51,7 +51,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_NULLDUMMY |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
SCRIPT_VERIFY_INCREASE_CONFIRMATIONS_REQUIRED;
/** 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;