Skip to content
Closed
10 changes: 7 additions & 3 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ BITCOIN_CORE_H = \
compat/endian.h \
compat/sanity.h \
compressor.h \
consensus/consensus.h \
consensus/cppwrappers.h \
core_io.h \
core_memusage.h \
httprpc.h \
Expand All @@ -116,7 +116,6 @@ BITCOIN_CORE_H = \
policy/fees.h \
policy/policy.h \
policy/rbf.h \
pow.h \
protocol.h \
random.h \
reverselock.h \
Expand Down Expand Up @@ -187,7 +186,6 @@ libbitcoin_server_a_SOURCES = \
noui.cpp \
policy/fees.cpp \
policy/policy.cpp \
pow.cpp \
rest.cpp \
rpc/blockchain.cpp \
rpc/mining.cpp \
Expand Down Expand Up @@ -258,12 +256,18 @@ libbitcoin_consensus_a_SOURCES = \
amount.h \
arith_uint256.cpp \
arith_uint256.h \
consensus/consensus.h \
consensus/header_verify.cpp \
consensus/header_verify.h \
consensus/interfaces.h \
consensus/merkle.cpp \
consensus/merkle.h \
consensus/params.h \
consensus/validation.h \
hash.cpp \
hash.h \
pow.cpp \
pow.h \
prevector.h \
primitives/block.cpp \
primitives/block.h \
Expand Down
65 changes: 65 additions & 0 deletions src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "chain.h"

#include "consensus/interfaces.h"

using namespace std;

/**
Expand Down Expand Up @@ -150,3 +152,66 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr
}
return sign * r.GetLow64();
}

// Interface translators: from CPP to C

namespace {
static inline const CBlockIndex* GetImpl(const void* indexObject)
{
return (const CBlockIndex*)indexObject;
}

static const void* GetAncestorImpl(const void* indexObject, const int64_t height)
{
return GetImpl(indexObject)->GetAncestor(height);
}
static const unsigned char* GetHashImpl(const void* indexObject)
{
return GetImpl(indexObject)->GetBlockHash().GetDataArray();
}
static int64_t GetHeightImpl(const void* indexObject)
{
return GetImpl(indexObject)->nHeight;
}
static int32_t GetVersionImpl(const void* indexObject)
{
return GetImpl(indexObject)->nVersion;
}
static uint32_t GetTimeImpl(const void* indexObject)
{
return GetImpl(indexObject)->nTime;
}
static uint32_t GetBitsImpl(const void* indexObject)
{
return GetImpl(indexObject)->nBits;
}
inline const void* GetPrevImpl(const void* indexObject)
{
return GetImpl(indexObject)->pprev;
}
inline int64_t GetMedianTimeImpl(const void* indexObject)
{
return GetImpl(indexObject)->GetMedianTimePast();
}
static void IndexDeallocatorImpl(void* indexObject)
{
// Bitcoin Core keeps the index in memory: Don't free anything.
}
} // Anonymous namespace

BlockIndexInterface CreateCoreIndexInterface()
{
BlockIndexInterface intexInt;

intexInt.GetAncestor = GetAncestorImpl;
intexInt.GetHash = GetHashImpl;
intexInt.GetHeight = GetHeightImpl;
intexInt.GetVersion = GetVersionImpl;
intexInt.GetTime = GetTimeImpl;
intexInt.GetBits = GetBitsImpl;
intexInt.GetPrev = GetPrevImpl;
intexInt.GetMedianTime = GetMedianTimeImpl;
intexInt.DeleteIndex = IndexDeallocatorImpl;

return intexInt;
}
7 changes: 7 additions & 0 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include <vector>

class BlockIndexInterface;

class CBlockFileInfo
{
public:
Expand Down Expand Up @@ -340,6 +342,11 @@ arith_uint256 GetBlockProof(const CBlockIndex& block);
/** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);

/**
* Bitcoin Core implementation of BlockIndexInterface.
*/
BlockIndexInterface CreateCoreIndexInterface();

/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex
{
Expand Down
34 changes: 34 additions & 0 deletions src/consensus/cppwrappers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_CONSENSUS_CPPWRAPPERS_H
#define BITCOIN_CONSENSUS_CPPWRAPPERS_H

#include "header_verify.h"
#include "interfaces.h"
#include "pow.h"

#include <stdint.h>

class CBlockHeader;
class CBlockIndex;
class CValidationState;
namespace Consensus { struct Params; };

inline unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& consensusParams)
{
return PowGetNextWorkRequired(pindexLast, CreateCoreIndexInterface(), pblock, consensusParams);
}

inline unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& consensusParams)
{
return PowCalculateNextWorkRequired(pindexLast, CreateCoreIndexInterface(), nFirstBlockTime, consensusParams);
}

inline bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
{
return ContextualCheckHeader(block, state, consensusParams, pindexPrev, CreateCoreIndexInterface(), nAdjustedTime);
}

#endif // BITCOIN_CONSENSUS_CPPWRAPPERS_H
57 changes: 57 additions & 0 deletions src/consensus/header_verify.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2016 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 "consensus.h"

#include "interfaces.h"
#include "pow.h"
#include "primitives/block.h"
#include "tinyformat.h"
#include "validation.h"

bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW)
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed");

return true;
}

bool ContextualCheckHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const void* indexObject, const BlockIndexInterface& iBlockIndex, int64_t nAdjustedTime)
{
const int nHeight = indexObject == NULL ? 0 : iBlockIndex.GetHeight(indexObject) + 1;
// Check proof of work
if (block.nBits != PowGetNextWorkRequired(indexObject, iBlockIndex, &block, consensusParams))
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");

// Check timestamp against prev
if (block.GetBlockTime() <= iBlockIndex.GetMedianTime(indexObject))
return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");

// Check timestamp
if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60)
return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");

// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
// check for version 2, 3 and 4 upgrades
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
(block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
(block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));

return true;
}

bool VerifyHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const void* indexObject, const BlockIndexInterface& iBlockIndex, int64_t nAdjustedTime)
{
if (!CheckBlockHeader(block, state, consensusParams, true))
return false;

if (!ContextualCheckHeader(block, state, consensusParams, indexObject, iBlockIndex, nAdjustedTime))
return false;

return true;
}
26 changes: 26 additions & 0 deletions src/consensus/header_verify.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2016-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_CONSENSUS_HEADER_VERIFY_H
#define BITCOIN_CONSENSUS_HEADER_VERIFY_H

#include <stdint.h>

class CBlockHeader;
class CBlockIndex;
class CValidationState;
namespace Consensus { struct Params; };
struct BlockIndexInterface;

/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true);

/** Context-dependent validity checks.
* By "context", we mean only the previous block headers, but not the UTXO
* set; UTXO-related validity checks are done in ConnectBlock(). */
bool ContextualCheckHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const void* indexObject, const BlockIndexInterface& iBlockIndex, int64_t nAdjustedTime);

bool VerifyHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const void* indexObject, const BlockIndexInterface& iBlockIndex, int64_t nAdjustedTime);

#endif // BITCOIN_CONSENSUS_HEADER_VERIFY_H
67 changes: 67 additions & 0 deletions src/consensus/interfaces.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2016-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_CONSENSUS_INTERFACES_H
#define BITCOIN_CONSENSUS_INTERFACES_H

#include <stdint.h>

typedef const unsigned char* (*GetHashFn)(const void* indexObject);
typedef const void* (*GetAncestorFn)(const void* indexObject, int64_t height);
typedef int64_t (*GetHeightFn)(const void* indexObject);
typedef int32_t (*GetVersionFn)(const void* indexObject);
typedef uint32_t (*GetTimeFn)(const void* indexObject);
typedef uint32_t (*GetBitsFn)(const void* indexObject);

// Potential optimizations:

/**
* Some implementations may chose to store a pointer to the previous
* block instead of calling AncestorFn, trading memory for
* validation speed.
*/
typedef const void* (*GetPrevFn)(const void* indexObject);
/**
* Some implementations may chose to cache the Median Time Past.
*/
typedef int64_t (*GetMedianTimeFn)(const void* indexObject);
/**
* While not using this, it is assumed that the caller - who is
* responsible for all the new allocations - will free all the memory
* (or not) of the things that have been newly created in memory (or
* not) after the call to the exposed libbitcoinconsenus function.
* This function is mostly here to document the fact that some storage
* optimizations are only possible if there's a fast signaling from
* libbitcoinconsenus when data resources that have been asked for as
* part of the validation are no longer needed.
*/
typedef void (*IndexDeallocatorFn)(void* indexObject);


/**
* Collection of function pointers to interface with block index storage.
*/
struct BlockIndexInterface
{
GetHashFn GetHash;
GetAncestorFn GetAncestor;
GetHeightFn GetHeight;
GetVersionFn GetVersion;
GetTimeFn GetTime;
GetBitsFn GetBits;
/**
* Just for optimization: If this is set to NULL, Ancestor() and
* Height() will be called instead.
*/
GetPrevFn GetPrev;
/**
* Just for optimization: If this is set to NULL, Prev() and
* Time() will be called instead.
*/
GetMedianTimeFn GetMedianTime;
//! TODO This is mostly here for discussion, but not used yet.
IndexDeallocatorFn DeleteIndex;
};

#endif // BITCOIN_CONSENSUS_INTERFACES_H
1 change: 1 addition & 0 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "chainparams.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "consensus/cppwrappers.h"
#include "consensus/merkle.h"
#include "consensus/validation.h"
#include "hash.h"
Expand Down
Loading