Commit 21a8e23d authored by Ashot's avatar Ashot

Merge branch 'Current-dev' into 'calculate-score-unit-tests'

# Conflicts:
#   src/Makefile.test.include
parents 5706246c 5f8d0935
......@@ -149,3 +149,11 @@ Osx-snapshot:
<<: *osx_definition
<<: *job_definition
<<: *snapshot_definition
# Trigger the docker build and delivery
trigger_docker_build:
stage: deploy
script:
- curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master --form "variables[VERSION_TAG]=$CI_COMMIT_TAG" https://gitlab.crown.tech/api/v4/projects/17/trigger/pipeline
only:
- tags
......@@ -6,7 +6,7 @@ define(_CLIENT_VERSION_REVISION, 5)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2018)
AC_INIT([Crown Test-Alpha3],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@crown.tech],[crown])
AC_INIT([Crown Test-Alpha4],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@crown.tech],[crown])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADERS([src/config/crown-config.h])
AC_CONFIG_AUX_DIR([build-aux])
......
......@@ -167,7 +167,9 @@ BITCOIN_CORE_H = \
compat/byteswap.h \
compat/endian.h \
compat/sanity.h \
updater.h
updater.h \
dbdetails.h \
dbmanager.h
JSON_H = \
json/json_spirit.h \
......@@ -218,6 +220,7 @@ libbitcoin_server_a_SOURCES = \
timedata.cpp \
txdb.cpp \
txmempool.cpp \
dbdetails.cpp \
$(JSON_H) \
$(BITCOIN_CORE_H)
......
......@@ -74,7 +74,8 @@ BITCOIN_TESTS =\
test/transaction_tests.cpp \
test/univalue_tests.cpp \
test/util_tests.cpp \
test/score_tests.cpp
test/score_tests.cpp \
test/db_tests.cpp
if ENABLE_WALLET
BITCOIN_TESTS += \
......
......@@ -119,26 +119,14 @@ int CMerkleTx::GetTransactionLockSignatures() const
if(!IsSporkActive(SPORK_2_INSTANTX)) return -3;
if(!fEnableInstantX) return -1;
//compile consessus vote
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(GetHash());
if (i != mapTxLocks.end()){
return (*i).second.CountSignatures();
}
return -1;
return GetInstantSend().GetSignaturesCount(GetHash());
}
bool CMerkleTx::IsTransactionLockTimedOut() const
{
if(!fEnableInstantX) return 0;
//compile consessus vote
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(GetHash());
if (i != mapTxLocks.end()){
return GetTime() > (*i).second.nTimeout;
}
return false;
return GetInstantSend().IsLockTimedOut(GetHash());
}
bool
......@@ -244,4 +232,4 @@ CAuxPow::getExpectedIndex (uint32_t nNonce, int nChainId, unsigned h)
rand = rand * 1103515245 + 12345;
return rand % (1 << h);
}
\ No newline at end of file
}
......@@ -13,7 +13,7 @@
* for both crownd and crown-qt, to make it harder for attackers to
* target servers or GUI users specifically.
*/
const std::string CLIENT_NAME("Crown Test-Alpha3");
const std::string CLIENT_NAME("Crown Test-Alpha4");
/**
* Client version number
......
// Copyright (c) 2014-2018 The Crown developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "dbdetails.h"
namespace details
{
ReadResult ReadStream(CDataStream& stream, const std::string& filename)
{
boost::filesystem::path pathDb = GetDataDir() / filename;
// open input file, and associate with CAutoFile
FILE *file = fopen(pathDb.string().c_str(), "rb");
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
if (filein.IsNull())
{
error("%s: Failed to open file %s", __func__, pathDb.string());
return FileError;
}
// use file size to size memory buffer
int fileSize = boost::filesystem::file_size(pathDb);
int dataSize = fileSize - sizeof(uint256);
// Don't try to resize to a negative number if file is small
if (dataSize < 0)
dataSize = 0;
std::vector<unsigned char> vchData(dataSize);
uint256 hashIn;
// read data and checksum from file
try
{
filein.read((char *)&vchData[0], dataSize);
filein >> hashIn;
}
catch (const std::exception &e)
{
error("%s: Deserialize or I/O error - %s", __func__, e.what());
return HashReadError;
}
filein.fclose();
stream = CDataStream(vchData, SER_DISK, CLIENT_VERSION);
// verify stored checksum matches input data
uint256 hashTmp = Hash(stream.begin(), stream.end());
if (hashIn != hashTmp)
{
error("%s: Checksum mismatch, data corrupted", __func__);
return IncorrectHash;
}
return Ok;
}
}
// Copyright (c) 2014-2018 The Crown developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef DB_DETAILS_H
#define DB_DETAILS_H
#include "chainparams.h"
#include "clientversion.h"
#include "hash.h"
#include "streams.h"
#include "util.h"
#include <boost/filesystem.hpp>
namespace details
{
enum ReadResult
{
Ok,
FileError,
HashReadError,
IncorrectHash,
IncorrectMagicMessage,
IncorrectMagicNumber,
IncorrectFormat
};
ReadResult ReadStream(CDataStream& stream, const std::string& filename);
template <typename T>
ReadResult DeserializeStream(CDataStream& stream, const std::string& magicMessage, T& objToLoad)
{
unsigned char pchMsgTmp[4];
std::string strMagicMessageTmp;
// de-serialize file header (file specific magic message) and ..
stream >> strMagicMessageTmp;
// ... verify the message matches predefined one
if (magicMessage != strMagicMessageTmp)
{
error("%s: Invalid magic message", __func__);
return IncorrectMagicMessage;
}
// de-serialize file header (network specific magic number) and ..
stream >> FLATDATA(pchMsgTmp);
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
{
error("%s: Invalid network magic number", __func__);
return IncorrectMagicNumber;
}
// de-serialize data into T object
stream >> objToLoad;
return Ok;
}
template <typename T>
ReadResult Read(T& objToLoad, const std::string& filename, const std::string& magicMessage, bool fDryRun = false)
{
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
ReadResult result = ReadStream(ssObj, filename);
if (result != Ok)
return result;
try
{
result = DeserializeStream(ssObj, magicMessage, objToLoad);
if (result != Ok)
return result;
}
catch (const std::exception &e)
{
objToLoad.Clear();
error("%s: Deserialize or I/O error - %s", __func__, e.what());
return IncorrectFormat;
}
int64_t nStart = GetTimeMillis();
LogPrintf("Loaded info from %s %dms\n", filename, GetTimeMillis() - nStart);
LogPrintf(" %s\n", objToLoad.ToString());
if(!fDryRun)
{
LogPrintf("%s: Cleaning....\n", __func__);
objToLoad.CheckAndRemove();
LogPrintf(" %s\n", objToLoad.ToString());
}
return Ok;
}
template <typename T>
bool Write(const T& objToSave, const std::string& filename, const std::string& magicMessage)
{
int64_t nStart = GetTimeMillis();
// serialize, checksum data up to that point, then append checksum
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
ssObj << magicMessage; // specific magic message for this type of object
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
ssObj << objToSave;
uint256 hash = Hash(ssObj.begin(), ssObj.end());
ssObj << hash;
// open output file, and associate with CAutoFile
boost::filesystem::path pathDb = GetDataDir() / filename;
FILE *file = fopen(pathDb.string().c_str(), "wb");
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
return error("%s: Failed to open file %s", __func__, pathDb.string());
// Write and commit header, data
try
{
fileout << ssObj;
}
catch (const std::exception &e)
{
return error("%s: Serialize or I/O error - %s", __func__, e.what());
}
fileout.fclose();
LogPrintf("Written info to %s %dms\n", filename, GetTimeMillis() - nStart);
LogPrintf(" %s\n", objToSave.ToString());
return true;
}
}
#endif
// Copyright (c) 2014-2018 The Crown developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef DB_MANAGER_H
#define DB_MANAGER_H
#include "dbdetails.h"
template <typename T>
bool Load(T& objToLoad, const std::string& filename, const std::string& magicMessage, bool fDryRun = false)
{
LogPrintf("Reading info from %s...\n", filename);
::details::ReadResult readResult = ::details::Read(objToLoad, filename, magicMessage, fDryRun);
switch(readResult)
{
case ::details::Ok:
return true;
case ::details::FileError:
LogPrintf("Missing file %s, will try to recreate\n", filename);
break;
case ::details::IncorrectFormat:
LogPrintf("Error reading %s: ", filename);
LogPrintf("%s: Magic is ok but data has invalid format, will try to recreate\n", __func__);
break;
default:
LogPrintf("Error reading %s: ", filename);
LogPrintf("%s: File format is unknown or invalid, please fix it manually\n", __func__);
return false;
}
return true;
}
template <typename T>
bool Dump(const T& objToSave, const std::string& filename, const std::string& magicMessage)
{
int64_t nStart = GetTimeMillis();
LogPrintf("Verifying %s format...\n", filename);
T tmpObjToLoad;
if (!Load(tmpObjToLoad, filename, magicMessage, true))
return false;
LogPrintf("Writing info to %s...\n", filename);
::details::Write(objToSave, filename, magicMessage);
LogPrintf("%s dump finished %dms\n", filename, GetTimeMillis() - nStart);
return true;
}
#endif
......@@ -37,6 +37,8 @@
#include "systemnodeconfig.h"
#include "spork.h"
#include "utilmoneystr.h"
#include "dbmanager.h"
#include "instantx.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
......@@ -160,6 +162,8 @@ static CCoinsViewDB *pcoinsdbview = NULL;
static CCoinsViewErrorCatcher *pcoinscatcher = NULL;
static boost::scoped_ptr<ECCVerifyHandle> globalVerifyHandle;
void DumpData();
/** Preparing steps before shutting down or restarting the wallet */
void PrepareShutdown()
{
......@@ -185,11 +189,7 @@ void PrepareShutdown()
GenerateBitcoins(false, NULL, 0);
#endif
StopNode();
DumpMasternodes();
DumpBudgets();
DumpMasternodePayments();
DumpSystemnodes();
DumpSystemnodePayments();
DumpData();
UnregisterNodeSignals(GetNodeSignals());
if (fFeeEstimatesInitialized)
......@@ -586,7 +586,64 @@ bool InitSanityCheck(void)
return true;
}
bool LoadData()
{
std::string strDBName;
boost::filesystem::path pathDB = GetDataDir();
uiInterface.InitMessage(_("Loading masternode cache..."));
if (!Load(mnodeman, "mncache.dat", "MasternodeCache"))
{
return InitError(_("Failed to load masternode cache from") + "\n" + (pathDB / strDBName).string());
}
uiInterface.InitMessage(_("Loading systemnode cache..."));
if (!Load(snodeman, "sncache.dat", "SystemnodeCache"))
{
return InitError(_("Failed to load systemnode cache from") + "\n" + (pathDB / strDBName).string());
}
uiInterface.InitMessage(_("Loading instant send cache..."));
if (!Load(GetInstantSend(), "ixcache.dat", "InstantSend"))
{
return InitError(_("Failed to load systemnode cache from") + "\n" + (pathDB / strDBName).string());
}
uiInterface.InitMessage(_("Loading budget cache..."));
if (!Load(budget, "budget.dat", "MasternodeBudget"))
{
return InitError(_("Failed to load systemnode cache from") + "\n" + (pathDB / strDBName).string());
}
//flag our cached items so we send them to our peers
budget.ResetSync();
budget.ClearSeen();
uiInterface.InitMessage(_("Loading masternode payment cache..."));
if (!Load(masternodePayments, "mnpayments.dat", "MasternodePayments"))
{
return InitError(_("Failed to load systemnode cache from") + "\n" + (pathDB / strDBName).string());
}
uiInterface.InitMessage(_("Loading systemnode payment cache..."));
if (!Load(systemnodePayments, "snpayments.dat", "SystemnodePayments"))
{
return InitError(_("Failed to load systemnode cache from") + "\n" + (pathDB / strDBName).string());
}
return true;
}
void DumpData()
{
Dump(mnodeman, "mncache.dat", "MasternodeCache");
Dump(budget, "budget.dat", "MasternodeBudget");
Dump(masternodePayments, "mnpayments.dat", "MasternodePayments");
Dump(snodeman, "sncache.dat", "SystemnodeCache");
Dump(systemnodePayments, "snpayments.dat", "SystemnodePayments");
Dump(GetInstantSend(), "ixcache.dat", "InstantSend");
}
/** Initialize crown.
* @pre Parameters should be parsed and config file should be read.
......@@ -1439,89 +1496,8 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 10: setup Budgets
uiInterface.InitMessage(_("Loading masternode cache..."));
CMasternodeDB mndb;
CMasternodeDB::ReadResult readResult = mndb.Read(mnodeman);
if (readResult == CMasternodeDB::FileError)
LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
else if (readResult != CMasternodeDB::Ok)
{
LogPrintf("Error reading mncache.dat: ");
if(readResult == CMasternodeDB::IncorrectFormat)
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
else
LogPrintf("file format is unknown or invalid, please fix it manually\n");
}
uiInterface.InitMessage(_("Loading systemnode cache..."));
CSystemnodeDB sndb;
CSystemnodeDB::ReadResult readResultS = sndb.Read(snodeman);
if (readResultS == CSystemnodeDB::FileError)
LogPrintf("Missing systemnode cache file - sncache.dat, will try to recreate\n");
else if (readResultS != CSystemnodeDB::Ok)
{
LogPrintf("Error reading sncache.dat: ");
if(readResultS == CSystemnodeDB::IncorrectFormat)
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
else
LogPrintf("file format is unknown or invalid, please fix it manually\n");
}
uiInterface.InitMessage(_("Loading budget cache..."));
CBudgetDB budgetdb;
CBudgetDB::ReadResult readResult2 = budgetdb.Read(budget);
if (readResult2 == CBudgetDB::FileError)
LogPrintf("Missing budget cache - budget.dat, will try to recreate\n");
else if (readResult2 != CBudgetDB::Ok)
{
LogPrintf("Error reading budget.dat: ");
if(readResult2 == CBudgetDB::IncorrectFormat)
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
else
LogPrintf("file format is unknown or invalid, please fix it manually\n");
}
//flag our cached items so we send them to our peers
budget.ResetSync();
budget.ClearSeen();
uiInterface.InitMessage(_("Loading masternode payment cache..."));
CMasternodePaymentDB mnpayments;
CMasternodePaymentDB::ReadResult readResult3 = mnpayments.Read(masternodePayments);
if (readResult3 == CMasternodePaymentDB::FileError)
LogPrintf("Missing masternode payment cache - mnpayments.dat, will try to recreate\n");
else if (readResult3 != CMasternodePaymentDB::Ok)
{
LogPrintf("Error reading mnpayments.dat: ");
if(readResult3 == CMasternodePaymentDB::IncorrectFormat)
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
else
LogPrintf("file format is unknown or invalid, please fix it manually\n");
}
uiInterface.InitMessage(_("Loading systemnode payment cache..."));
CSystemnodePaymentDB snpayments;
CSystemnodePaymentDB::ReadResult readResult4 = snpayments.Read(systemnodePayments);
if (readResult4 == CSystemnodePaymentDB::FileError)
LogPrintf("Missing systemnode payment cache - snpayments.dat, will try to recreate\n");
else if (readResult4 != CSystemnodePaymentDB::Ok)
{
LogPrintf("Error reading snpayments.dat: ");
if(readResult4 == CSystemnodePaymentDB::IncorrectFormat)
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
else
LogPrintf("file format is unknown or invalid, please fix it manually\n");
}
if (!LoadData())
return false;
fMasterNode = GetBoolArg("-masternode", false);
fSystemNode = GetBoolArg("-systemnode", false);
......
This diff is collapsed.
......@@ -25,54 +25,68 @@
#define INSTANTX_SIGNATURES_REQUIRED 6
#define INSTANTX_SIGNATURES_TOTAL 10
using namespace std;
using namespace boost;
class CConsensusVote;
class CTransaction;
class CTransactionLock;
class InstantSend;
static const int MIN_INSTANTX_PROTO_VERSION = 70040;
extern map<uint256, CTransaction> mapTxLockReq;
extern map<uint256, CTransaction> mapTxLockReqRejected;
extern map<uint256, CConsensusVote> mapTxLockVote;
extern map<uint256, CTransactionLock> mapTxLocks;
extern std::map<COutPoint, uint256> mapLockedInputs;
extern int nCompleteTXLocks;
int64_t CreateNewLock(CTransaction tx);
bool IsIXTXValid(const CTransaction& txCollateral);
// if two conflicting locks are approved by the network, they will cancel out
bool CheckForConflictingLocks(CTransaction& tx);
extern std::auto_ptr<InstantSend> g_instantSend;
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
InstantSend& GetInstantSend();
//check if we need to vote on this transaction
void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight);
class InstantSend
{
public:
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv);
void CheckAndRemove();
void Clear();
int64_t CreateNewLock(const CTransaction& tx);
int GetSignaturesCount(uint256 txHash) const;
int GetCompleteLocksCount() const;
bool IsLockTimedOut(uint256 txHash) const;
bool TxLockRequested(uint256 txHash) const;
bool AlreadyHave(uint256 txHash) const;
std::string ToString() const;
boost::optional<uint256> GetLockedTx(const COutPoint& out) const;
boost::optional<CConsensusVote> GetLockVote(uint256 txHash) const;
boost::optional<CTransaction> GetLockReq(uint256 txHash) const;
//process consensus vote message
bool ProcessConsensusVote(CNode *pnode, CConsensusVote& ctx);
ADD_SERIALIZE_METHODS;
// keep transaction locks in memory for an hour
void CleanTransactionLocksList();
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(m_lockedInputs);
READWRITE(m_txLockVote);
READWRITE(m_txLockReq);
READWRITE(m_txLocks);
READWRITE(m_unknownVotes);
READWRITE(m_txLockReqRejected);
READWRITE(m_completeTxLocks);
}
int64_t GetAverageVoteTime();
private:
void DoConsensusVote(const CTransaction& tx, int64_t nBlockHeight);
bool IsIxTxValid(const CTransaction& txCollateral) const;
bool ProcessConsensusVote(CNode* pnode, const CConsensusVote& ctx);
bool CheckForConflictingLocks(const CTransaction& tx);
int64_t GetAverageVoteTime() const;
private:
std::map<COutPoint, uint256> m_lockedInputs;
std::map<uint256, CConsensusVote> m_txLockVote;
std::map<uint256, CTransaction> m_txLockReq;
std::map<uint256, CTransactionLock> m_txLocks;
std::map<uint256, int64_t> m_unknownVotes; //track votes with no tx for DOS
std::map<uint256, CTransaction> m_txLockReqRejected;
int m_completeTxLocks;
};
class CConsensusVote
{
public:
CTxIn vinMasternode;
uint256 txHash;
int nBlockHeight;
std::vector<unsigned char> vchMasterNodeSignature;
uint256 GetHash() const;
bool SignatureValid();
bool SignatureValid() const;
bool Sign();
ADD_SERIALIZE_METHODS;
......@@ -84,26 +98,39 @@ public:
READWRITE(vchMasterNodeSignature);
READWRITE(nBlockHeight);
}
public:
CTxIn vinMasternode;
uint256 txHash;
int nBlockHeight;
std::vector<unsigned char> vchMasterNodeSignature;
};
class CTransactionLock
{
public:
bool SignaturesValid() const;
int CountSignatures() const;
void AddSignature(const CConsensusVote& cv);
uint256 GetHash() const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(nBlockHeight);
READWRITE(txHash);
READWRITE(vecConsensusVotes);
READWRITE(nExpiration);
READWRITE(nTimeout);
}
public:
int nBlockHeight;
uint256 txHash;
std::vector<CConsensusVote> vecConsensusVotes;
int nExpiration;
int nTimeout;
bool SignaturesValid();
int CountSignatures();
void AddSignature(CConsensusVote& cv);
uint256 GetHash()
{
return txHash;
}
};
#endif
......@@ -139,8 +139,8 @@ void ThreadCheckLegacySigner()
{
mnodeman.CheckAndRemove();
mnodeman.ProcessMasternodeConnections();
masternodePayments.CleanPaymentList();
CleanTransactionLocksList();
masternodePayments.CheckAndRemove();
GetInstantSend().CheckAndRemove();
}
//if(c1 % MASTERNODES_DUMP_SECONDS == 0) DumpMasternodes();
......@@ -158,8 +158,8 @@ void ThreadCheckLegacySigner()
{
snodeman.CheckAndRemove();
snodeman.ProcessSystemnodeConnections();
systemnodePayments.CleanPaymentList();
CleanTransactionLocksList();
systemnodePayments.CheckAndRemove();
GetInstantSend().CheckAndRemove();
}
//if(c2 % SYSTEMNODES_DUMP_SECONDS == 0) DumpSystemnodes();
......
......@@ -898,15 +898,11 @@ int GetInputAge(const CTxIn& vin)
int GetInputAgeIX(uint256 nTXHash, const CTxIn& vin)
{
int sigs = 0;
int nResult = GetInputAge(vin);
if(nResult < 0) nResult = 0;
if (nResult < 6){
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()){
sigs = (*i).second.CountSignatures();
}
int sigs = GetInstantSend().GetSignaturesCount(nTXHash);
if(sigs >= INSTANTX_SIGNATURES_REQUIRED){
return nInstantXDepth+nResult;
}
......@@ -917,12 +913,8 @@ int GetInputAgeIX(uint256 nTXHash, const CTxIn& vin)
int GetIXConfirmations(uint256 nTXHash)
{
int sigs = 0;
int sigs = GetInstantSend().GetSignaturesCount(nTXHash);
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()){
sigs = (*i).second.CountSignatures();
}
if(sigs >= INSTANTX_SIGNATURES_REQUIRED){
return nInstantXDepth;
}
......@@ -1047,13 +1039,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// ----------- instantX transaction scanning -----------
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(mapLockedInputs.count(in.prevout)){
if(mapLockedInputs[in.prevout] != tx.GetHash()){
return state.DoS(