示例#1
0
int CInterpreter::GetCamera( void )
{
	CBlock	block;
	char	typeName[MAX_STRING_SIZE];
	int		type;

	block.Create( ID_CAMERA );

	if (!Match( TK_OPEN_PARENTHESIS ))
		return Error("syntax error : '(' not found");

	if ( GetType( (char *) typeName ) == false )
		return false;

	type = FindSymbol( typeName, m_typeKeywords);

	switch ( type )
	{
	case TYPE_PAN:		//PAN  ( ANGLES, DURATION )

		block.Write( TK_FLOAT, (float) type );

		if ( GetVector( &block ) == false )
			return false;

		if ( GetVector( &block ) == false )
			return false;

		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_ZOOM:		//ZOOM ( FOV, DURATION )
		
		block.Write( TK_FLOAT, (float) type );

		if ( GetFloat( &block ) == false )
			return false;
		
		if ( GetFloat( &block ) == false )
			return false;

		break;
	
	case TYPE_MOVE:		//MOVE ( ORIGIN, DURATION )

		block.Write( TK_FLOAT, (float) type );

		if ( GetVector( &block ) == false )
			return false;

		if ( GetFloat( &block ) == false )
			return false;

		break;
	
	case TYPE_FADE:		//FADE ( SOURCE(R,G,B,A), DEST(R,G,B,A), DURATION )
		
		block.Write( TK_FLOAT, (float) type );

		//Source color
		if ( GetVector( &block ) == false )
			return false;
		if ( GetFloat( &block ) == false )
			return false;

		//Dest color
		if ( GetVector( &block ) == false )
			return false;
		if ( GetFloat( &block ) == false )
			return false;

		//Duration
		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_PATH:		//PATH ( FILENAME )

		block.Write( TK_FLOAT, (float) type );

		//Filename
		if ( GetString( &block ) == false )
			return false;

		break;

	case TYPE_ENABLE:
	case TYPE_DISABLE:

		block.Write( TK_FLOAT, (float) type );
		break;

	case TYPE_SHAKE:	//SHAKE ( INTENSITY, DURATION )

		block.Write( TK_FLOAT, (float) type );

		//Intensity
		if ( GetFloat( &block ) == false )
			return false;

		//Duration
		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_ROLL:		//ROLL ( ANGLE, TIME )

		block.Write( TK_FLOAT, (float) type );

		//Angle
		if ( GetFloat( &block ) == false )
			return false;

		//Time
		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_TRACK:	//TRACK ( TARGETNAME, SPEED, INITLERP )

		block.Write( TK_FLOAT, (float) type );

		//Target name
		if ( GetString( &block ) == false )
			return false;

		//Speed
		if ( GetFloat( &block ) == false )
			return false;

		//Init lerp
		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_FOLLOW:	//FOLLOW ( CAMERAGROUP, SPEED, INITLERP )

		block.Write( TK_FLOAT, (float) type );

		//Camera group
		if ( GetString( &block ) == false )
			return false;

		//Speed
		if ( GetFloat( &block ) == false )
			return false;

		//Init lerp
		if ( GetFloat( &block ) == false )
			return false;

		break;

	case TYPE_DISTANCE:	//DISTANCE ( DISTANCE, INITLERP )

		block.Write( TK_FLOAT, (float) type );

		//Distance
		if ( GetFloat( &block ) == false )
			return false;

		//Init lerp
		if ( GetFloat( &block ) == false )
			return false;

		break;
	}

	if (!Match( TK_CLOSED_PARENTHESIS ))
		return Error("camera : too many parameters");

	m_blockStream->WriteBlock( &block );

	return true;
}
示例#2
0
bool CTxDB::LoadBlockIndex()
{
    if (mapBlockIndex.size() > 0) {
        // Already loaded once in this session. It can happen during migration
        // from BDB.
        return true;
    }
    // The block index is an in-memory structure that maps hashes to on-disk
    // locations where the contents of the block can be found. Here, we scan it
    // out of the DB and into mapBlockIndex.
    leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions());
    // Seek to start key.
    CDataStream ssStartKey(SER_DISK, CLIENT_VERSION);
    ssStartKey << make_pair(string("blockindex"), uint256(0));
    iterator->Seek(ssStartKey.str());
    // Now read each entry.
    while (iterator->Valid())
    {
        // Unpack keys and values.
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.write(iterator->key().data(), iterator->key().size());
        CDataStream ssValue(SER_DISK, CLIENT_VERSION);
        ssValue.write(iterator->value().data(), iterator->value().size());
        string strType;
        ssKey >> strType;
        // Did we reach the end of the data to read?
        if (fRequestShutdown || strType != "blockindex")
            break;
        CDiskBlockIndex diskindex;
        ssValue >> diskindex;

        uint256 blockHash = diskindex.GetBlockHash();

        // Construct block index object
        CBlockIndex* pindexNew    = InsertBlockIndex(blockHash);
        pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
        pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
        pindexNew->nFile          = diskindex.nFile;
        pindexNew->nBlockPos      = diskindex.nBlockPos;
        pindexNew->nHeight        = diskindex.nHeight;
        pindexNew->nMint          = diskindex.nMint;
        pindexNew->nMoneySupply   = diskindex.nMoneySupply;
        pindexNew->nFlags         = diskindex.nFlags;
        pindexNew->nStakeModifier = diskindex.nStakeModifier;
        pindexNew->prevoutStake   = diskindex.prevoutStake;
        pindexNew->nStakeTime     = diskindex.nStakeTime;
        pindexNew->hashProof      = diskindex.hashProof;
        pindexNew->nVersion       = diskindex.nVersion;
        pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
        pindexNew->nTime          = diskindex.nTime;
        pindexNew->nBits          = diskindex.nBits;
        pindexNew->nNonce         = diskindex.nNonce;

        // Watch for genesis block
        if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))
            pindexGenesisBlock = pindexNew;

        if (!pindexNew->CheckIndex()) {
            delete iterator;
            return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
        }

        // ARbit: build setStakeSeen
        if (pindexNew->IsProofOfStake())
            setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));

        iterator->Next();
    }
    delete iterator;

    if (fRequestShutdown)
        return true;

    // Calculate nChainTrust
    vector<pair<int, CBlockIndex*> > vSortedByHeight;
    vSortedByHeight.reserve(mapBlockIndex.size());
    BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
    {
        CBlockIndex* pindex = item.second;
        vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
    }
    sort(vSortedByHeight.begin(), vSortedByHeight.end());
    BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
    {
        CBlockIndex* pindex = item.second;
        pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust();
        // ARbit: calculate stake modifier checksum
        pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
        if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
            return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRIx64, pindex->nHeight, pindex->nStakeModifier);
    }

    // Load hashBestChain pointer to end of best chain
    if (!ReadHashBestChain(hashBestChain))
    {
        if (pindexGenesisBlock == NULL)
            return true;
        return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
    }
    if (!mapBlockIndex.count(hashBestChain))
        return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
    pindexBest = mapBlockIndex[hashBestChain];
    nBestHeight = pindexBest->nHeight;
    nBestChainTrust = pindexBest->nChainTrust;

    printf("LoadBlockIndex(): hashBestChain=%s  height=%d  trust=%s  date=%s\n",
      hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(),
      DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());

    // ARbit: load hashSyncCheckpoint
    if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
        return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
    printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());

    // Load bnBestInvalidTrust, OK if it doesn't exist
    CBigNum bnBestInvalidTrust;
    ReadBestInvalidTrust(bnBestInvalidTrust);
    nBestInvalidTrust = bnBestInvalidTrust.getuint256();

    // Verify blocks in the best chain
    int nCheckLevel = GetArg("-checklevel", 1);
    int nCheckDepth = GetArg( "-checkblocks", 2500);
    if (nCheckDepth == 0)
        nCheckDepth = 1000000000; // suffices until the year 19000
    if (nCheckDepth > nBestHeight)
        nCheckDepth = nBestHeight;
    printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
    CBlockIndex* pindexFork = NULL;
    map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
    for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
    {
        if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
            break;
        CBlock block;
        if (!block.ReadFromDisk(pindex))
            return error("LoadBlockIndex() : block.ReadFromDisk failed");
        // check level 1: verify block validity
        // check level 7: verify block signature too
        if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6)))
        {
            printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
            pindexFork = pindex->pprev;
        }
        // check level 2: verify transaction index validity
        if (nCheckLevel>1)
        {
            pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
            mapBlockPos[pos] = pindex;
            BOOST_FOREACH(const CTransaction &tx, block.vtx)
            {
                uint256 hashTx = tx.GetHash();
                CTxIndex txindex;
                if (ReadTxIndex(hashTx, txindex))
                {
                    // check level 3: checker transaction hashes
                    if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
                    {
                        // either an error or a duplicate transaction
                        CTransaction txFound;
                        if (!txFound.ReadFromDisk(txindex.pos))
                        {
                            printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
                            pindexFork = pindex->pprev;
                        }
                        else
                            if (txFound.GetHash() != hashTx) // not a duplicate tx
                            {
                                printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
                                pindexFork = pindex->pprev;
                            }
                    }
                    // check level 4: check whether spent txouts were spent within the main chain
                    unsigned int nOutput = 0;
                    if (nCheckLevel>3)
                    {
                        BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
                        {
                            if (!txpos.IsNull())
                            {
                                pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
                                if (!mapBlockPos.count(posFind))
                                {
                                    printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
                                    pindexFork = pindex->pprev;
                                }
                                // check level 6: check whether spent txouts were spent by a valid transaction that consume them
                                if (nCheckLevel>5)
                                {
                                    CTransaction txSpend;
                                    if (!txSpend.ReadFromDisk(txpos))
                                    {
                                        printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
                                        pindexFork = pindex->pprev;
                                    }
                                    else if (!txSpend.CheckTransaction())
                                    {
                                        printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
                                        pindexFork = pindex->pprev;
                                    }
                                    else
                                    {
                                        bool fFound = false;
                                        BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
                                            if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
                                                fFound = true;
                                        if (!fFound)
                                        {
                                            printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
                                            pindexFork = pindex->pprev;
                                        }
                                    }
                                }
                            }
                            nOutput++;
                        }
                    }
                }
示例#3
0
int CInterpreter::GetSet( void )
{
	CBlock		block;

	block.Create( ID_SET );

	if (!Match( TK_OPEN_PARENTHESIS ))
		return Error("syntax error : '(' not found");

	if ( GetString( &block ) == false )
		return false;

	//Check for get placement
	if ( MatchGet() )
	{
		if ( GetGet( &block ) == false )
			return false;
	}
	else
	{
		switch( GetNextType() )
		{
		case TK_INT:
			
			if ( GetInteger( &block ) == false )
				return false;

			break;

		case TK_FLOAT:

			if ( GetFloat( &block ) == false )
				return false;

			break;

		case TK_STRING:
			
			if ( GetString( &block ) == false )
				return false;

			break;

		case TK_VECTOR_START:

			if ( GetVector( &block ) == false )
				return false;

			break;
		
		default:

			if ( MatchTag() )
			{
				GetTag( &block );
				break;
			}
			
			if ( MatchRandom() )
			{
				GetRandom( &block );
				break;
			}

			return Error("unknown parameter type");
			break;
		}
	}

	if (!Match( TK_CLOSED_PARENTHESIS ))
		return Error("set : too many parameters");

	m_blockStream->WriteBlock( &block );

	return true;
}
示例#4
0
UniValue generate(const UniValue& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 1)
        throw runtime_error(
            "generate numblocks\n"
            "\nMine blocks immediately (before the RPC call returns)\n"
            "\nNote: this function can only be used on the regtest network\n"
            "\nArguments:\n"
            "1. numblocks    (numeric, required) How many blocks are generated immediately.\n"
            "\nResult\n"
            "[ blockhashes ]     (array) hashes of blocks generated\n"
            "\nExamples:\n"
            "\nGenerate 11 blocks\n"
            + HelpExampleCli("generate", "11")
        );

    if (!Params().MineBlocksOnDemand())
        throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");

    int nHeightStart = 0;
    int nHeightEnd = 0;
    int nHeight = 0;
    int nGenerate = params[0].get_int();

    boost::shared_ptr<CReserveScript> coinbaseScript;
    GetMainSignals().ScriptForMining(coinbaseScript);

    // If the keypool is exhausted, no script is returned at all.  Catch this.
    if (!coinbaseScript)
        throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");

    //throw an error if no script was provided
    if (coinbaseScript->reserveScript.empty())
        throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");

    {   // Don't keep cs_main locked
        LOCK(cs_main);
        nHeightStart = chainActive.Height();
        nHeight = nHeightStart;
        nHeightEnd = nHeightStart+nGenerate;
    }
    unsigned int nExtraNonce = 0;
    UniValue blockHashes(UniValue::VARR);
    while (nHeight < nHeightEnd)
    {
        auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript));
        if (!pblocktemplate.get())
            throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
        CBlock *pblock = &pblocktemplate->block;
        {
            LOCK(cs_main);
            IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
        }
        while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
            // Yes, there is a chance every nonce could fail to satisfy the -regtest
            // target -- 1 in 2^(2^32). That ain't gonna happen.
            ++pblock->nNonce;
        }
        CValidationState state;
        if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
            throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
        ++nHeight;
        blockHashes.push_back(pblock->GetHash().GetHex());

        //mark script as important because it was used at least for one coinbase output
        coinbaseScript->KeepScript();
    }
    return blockHashes;
}
示例#5
0
UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
    if (fHelp || params.size() > 1)
        throw runtime_error(
            "getblocktemplate ( \"jsonrequestobject\" )\n"
            "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
            "It returns data needed to construct a block to work on.\n"
            "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"

            "\nArguments:\n"
            "1. \"jsonrequestobject\"       (string, optional) A json object in the following spec\n"
            "     {\n"
            "       \"mode\":\"template\"    (string, optional) This must be set to \"template\" or omitted\n"
            "       \"capabilities\":[       (array, optional) A list of strings\n"
            "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
            "           ,...\n"
            "         ]\n"
            "     }\n"
            "\n"

            "\nResult:\n"
            "{\n"
            "  \"version\" : n,                    (numeric) The block version\n"
            "  \"previousblockhash\" : \"xxxx\",    (string) The hash of current highest block\n"
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
            "      {\n"
            "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
            "         \"hash\" : \"xxxx\",          (string) hash/id encoded in little-endian hexadecimal\n"
            "         \"depends\" : [              (array) array of numbers \n"
            "             n                        (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
            "             ,...\n"
            "         ],\n"
            "         \"fee\": n,                   (numeric) difference in value between transaction inputs and outputs (in duffs); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
            "         \"sigops\" : n,               (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
            "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
            "      \"flags\" : \"flags\"            (string) \n"
            "  },\n"
            "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in duffs)\n"
            "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
            "  \"target\" : \"xxxx\",               (string) The hash target\n"
            "  \"mintime\" : xxx,                   (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
            "     \"value\"                         (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
            "     ,...\n"
            "  ],\n"
            "  \"noncerange\" : \"00000000ffffffff\",   (string) A range of valid nonces\n"
            "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
            "  \"height\" : n                      (numeric) The height of the next block\n"
            "  \"masternode\" : {                  (json object) required masternode payee that must be included in the next block\n"
            "      \"payee\" : \"xxxx\",             (string) payee address\n"
            "      \"script\" : \"xxxx\",            (string) payee scriptPubKey\n"
            "      \"amount\": n                   (numeric) required amount to pay\n"
            "  },\n"
            "  \"masternode_payments_started\" :  true|false, (boolean) true, if masternode payments started\n"
            "  \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n"
            "  \"superblock\" : [                  (array) required superblock payees that must be included in the next block\n"
            "      {\n"
            "         \"payee\" : \"xxxx\",          (string) payee address\n"
            "         \"script\" : \"xxxx\",         (string) payee scriptPubKey\n"
            "         \"amount\": n                (numeric) required amount to pay\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"superblocks_started\" : true|false, (boolean) true, if superblock payments started\n"
            "  \"superblocks_enabled\" : true|false  (boolean) true, if superblock payments are enabled\n"
            "}\n"

            "\nExamples:\n"
            + HelpExampleCli("getblocktemplate", "")
            + HelpExampleRpc("getblocktemplate", "")
         );

    LOCK(cs_main);

    std::string strMode = "template";
    UniValue lpval = NullUniValue;
    if (params.size() > 0)
    {
        const UniValue& oparam = params[0].get_obj();
        const UniValue& modeval = find_value(oparam, "mode");
        if (modeval.isStr())
            strMode = modeval.get_str();
        else if (modeval.isNull())
        {
            /* Do nothing */
        }
        else
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
        lpval = find_value(oparam, "longpollid");

        if (strMode == "proposal")
        {
            const UniValue& dataval = find_value(oparam, "data");
            if (!dataval.isStr())
                throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");

            CBlock block;
            if (!DecodeHexBlk(block, dataval.get_str()))
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");

            uint256 hash = block.GetHash();
            BlockMap::iterator mi = mapBlockIndex.find(hash);
            if (mi != mapBlockIndex.end()) {
                CBlockIndex *pindex = mi->second;
                if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
                    return "duplicate";
                if (pindex->nStatus & BLOCK_FAILED_MASK)
                    return "duplicate-invalid";
                return "duplicate-inconclusive";
            }

            CBlockIndex* const pindexPrev = chainActive.Tip();
            // TestBlockValidity only supports blocks built on the current Tip
            if (block.hashPrevBlock != pindexPrev->GetBlockHash())
                return "inconclusive-not-best-prevblk";
            CValidationState state;
            TestBlockValidity(state, Params(), block, pindexPrev, false, true);
            return BIP22ValidationResult(state);
        }
    }

    if (strMode != "template")
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");

    if (vNodes.empty())
        throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "H2O Core is not connected!");

    if (IsInitialBlockDownload())
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "H2O Core is downloading blocks...");

    if (!masternodeSync.IsSynced())
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "H2O Core is syncing with network...");

    static unsigned int nTransactionsUpdatedLast;

    if (!lpval.isNull())
    {
        // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
        uint256 hashWatchedChain;
        boost::system_time checktxtime;
        unsigned int nTransactionsUpdatedLastLP;

        if (lpval.isStr())
        {
            // Format: <hashBestChain><nTransactionsUpdatedLast>
            std::string lpstr = lpval.get_str();

            hashWatchedChain.SetHex(lpstr.substr(0, 64));
            nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
        }
        else
        {
            // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
            hashWatchedChain = chainActive.Tip()->GetBlockHash();
            nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
        }

        // Release the wallet and main lock while waiting
        LEAVE_CRITICAL_SECTION(cs_main);
        {
            checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);

            boost::unique_lock<boost::mutex> lock(csBestBlock);
            while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
            {
                if (!cvBlockChange.timed_wait(lock, checktxtime))
                {
                    // Timeout: Check transactions for update
                    if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
                        break;
                    checktxtime += boost::posix_time::seconds(10);
                }
            }
        }
        ENTER_CRITICAL_SECTION(cs_main);

        if (!IsRPCRunning())
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
        // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
    }

    // Update block
    static CBlockIndex* pindexPrev;
    static int64_t nStart;
    static CBlockTemplate* pblocktemplate;
    if (pindexPrev != chainActive.Tip() ||
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
    {
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
        pindexPrev = NULL;

        // Store the chainActive.Tip() used before CreateNewBlock, to avoid races
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
        CBlockIndex* pindexPrevNew = chainActive.Tip();
        nStart = GetTime();

        // Create new block
        if(pblocktemplate)
        {
            delete pblocktemplate;
            pblocktemplate = NULL;
        }
        CScript scriptDummy = CScript() << OP_TRUE;
        pblocktemplate = CreateNewBlock(Params(), scriptDummy);
        if (!pblocktemplate)
            throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");

        // Need to update only after we know CreateNewBlock succeeded
        pindexPrev = pindexPrevNew;
    }
    CBlock* pblock = &pblocktemplate->block; // pointer for convenience

    // Update nTime
    UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
    pblock->nNonce = 0;

    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

    UniValue transactions(UniValue::VARR);
    map<uint256, int64_t> setTxIndex;
    int i = 0;
    BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
        uint256 txHash = tx.GetHash();
        setTxIndex[txHash] = i++;

        if (tx.IsCoinBase())
            continue;

        UniValue entry(UniValue::VOBJ);

        entry.push_back(Pair("data", EncodeHexTx(tx)));

        entry.push_back(Pair("hash", txHash.GetHex()));

        UniValue deps(UniValue::VARR);
        BOOST_FOREACH (const CTxIn &in, tx.vin)
        {
            if (setTxIndex.count(in.prevout.hash))
                deps.push_back(setTxIndex[in.prevout.hash]);
        }
        entry.push_back(Pair("depends", deps));

        int index_in_template = i - 1;
        entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
        entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));

        transactions.push_back(entry);
    }

    UniValue aux(UniValue::VOBJ);
    aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));

    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);

    static UniValue aMutable(UniValue::VARR);
    if (aMutable.empty())
    {
        aMutable.push_back("time");
        aMutable.push_back("transactions");
        aMutable.push_back("prevblock");
    }

    UniValue result(UniValue::VOBJ);
    result.push_back(Pair("capabilities", aCaps));
    result.push_back(Pair("version", pblock->nVersion));
    result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
    result.push_back(Pair("transactions", transactions));
    result.push_back(Pair("coinbaseaux", aux));
    result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].GetValueOut()));
    result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
    result.push_back(Pair("target", hashTarget.GetHex()));
    result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
    result.push_back(Pair("mutable", aMutable));
    result.push_back(Pair("noncerange", "00000000ffffffff"));
    result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
    result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
    result.push_back(Pair("curtime", pblock->GetBlockTime()));
    result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
    result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));

    UniValue masternodeObj(UniValue::VOBJ);
    if(pblock->txoutMasternode != CTxOut()) {
        CTxDestination address1;
        ExtractDestination(pblock->txoutMasternode.scriptPubKey, address1);
        CBitcoinAddress address2(address1);
        masternodeObj.push_back(Pair("payee", address2.ToString().c_str()));
        masternodeObj.push_back(Pair("script", HexStr(pblock->txoutMasternode.scriptPubKey.begin(), pblock->txoutMasternode.scriptPubKey.end())));
        masternodeObj.push_back(Pair("amount", pblock->txoutMasternode.nValue));
    }
    result.push_back(Pair("masternode", masternodeObj));
    result.push_back(Pair("masternode_payments_started", pindexPrev->nHeight + 1 > Params().GetConsensus().nMasternodePaymentsStartBlock));
    result.push_back(Pair("masternode_payments_enforced", sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)));

    UniValue superblockObjArray(UniValue::VARR);
    if(pblock->voutSuperblock.size()) {
        BOOST_FOREACH (const CTxOut& txout, pblock->voutSuperblock) {
            UniValue entry(UniValue::VOBJ);
            CTxDestination address1;
            ExtractDestination(txout.scriptPubKey, address1);
            CBitcoinAddress address2(address1);
            entry.push_back(Pair("payee", address2.ToString().c_str()));
            entry.push_back(Pair("script", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end())));
            entry.push_back(Pair("amount", txout.nValue));
            superblockObjArray.push_back(entry);
        }
    }
示例#6
0
// max_nonce is not used by this function
int scanhash_hodl( int threadNumber, struct work* work, uint32_t max_nonce,
                   uint64_t *hashes_done )
{
    unsigned char *mainMemoryPsuedoRandomData = hodl_scratchbuf;
    uint32_t *pdata = work->data;
    uint32_t *ptarget = work->target;

    //retreive target
    std::stringstream s;
    for (int i = 7; i>=0; i--)
      s << strprintf("%08x", ptarget[i]);

    //retreive preveios hash
    std::stringstream p;
    for (int i = 0; i < 8; i++) 
      p << strprintf("%08x", swab32(pdata[8 - i]));

    //retreive merkleroot
    std::stringstream m;
    for (int i = 0; i < 8; i++) 
      m << strprintf("%08x", swab32(pdata[16 - i]));

    CBlock pblock;
    pblock.SetNull();

    pblock.nVersion=swab32(pdata[0]);
    pblock.nNonce=swab32(pdata[19]);
    pblock.nTime=swab32(pdata[17]);
    pblock.nBits=swab32(pdata[18]);
    pblock.hashPrevBlock=uint256S(p.str());
    pblock.hashMerkleRoot=uint256S(m.str());
    uint256 hashTarget=uint256S(s.str());
    int collisions=0;
    uint256 hash;

		//Begin AES Search
	        //Allocate temporary memory
		uint32_t cacheMemorySize = (1<<L2CACHE_TARGET); //2^12 = 4096 bytes
    		uint32_t comparisonSize=(1<<(PSUEDORANDOM_DATA_SIZE-L2CACHE_TARGET)); //2^(30-12) = 256K
                unsigned char *cacheMemoryOperatingData;
                unsigned char *cacheMemoryOperatingData2;
                cacheMemoryOperatingData=new unsigned char[cacheMemorySize+16];
                cacheMemoryOperatingData2=new unsigned char[cacheMemorySize];
                //Create references to data as 32 bit arrays
                uint32_t* cacheMemoryOperatingData32 = (uint32_t*)cacheMemoryOperatingData;
                uint32_t* cacheMemoryOperatingData322 = (uint32_t*)cacheMemoryOperatingData2;

                //Search for pattern in psuedorandom data
                unsigned char key[32] = {0};
                unsigned char iv[AES_BLOCK_SIZE];
                int outlen1, outlen2;

                //Iterate over the data
//                int searchNumber=comparisonSize/totalThreads;
                int searchNumber = comparisonSize / opt_n_threads;
                int startLoc=threadNumber*searchNumber;
		EVP_CIPHER_CTX ctx;
                  for(int32_t k = startLoc;k<startLoc+searchNumber && !work_restart[threadNumber].restart;k++){
                    //copy data to first l2 cache
                    memcpy((char*)&cacheMemoryOperatingData[0], (char*)&mainMemoryPsuedoRandomData[k*cacheMemorySize], cacheMemorySize);
                    for(int j=0;j<AES_ITERATIONS;j++){
                        //use last 4 bytes of first cache as next location
                        uint32_t nextLocation = cacheMemoryOperatingData32[(cacheMemorySize/4)-1]%comparisonSize;
                        //Copy data from indicated location to second l2 cache -
                        memcpy((char*)&cacheMemoryOperatingData2[0], (char*)&mainMemoryPsuedoRandomData[nextLocation*cacheMemorySize], cacheMemorySize);
                        //XOR location data into second cache
                        for(uint32_t i = 0; i < cacheMemorySize/4; i++)
                            cacheMemoryOperatingData322[i] = cacheMemoryOperatingData32[i] ^ cacheMemoryOperatingData322[i];
                        memcpy(key,(unsigned char*)&cacheMemoryOperatingData2[cacheMemorySize-32],32);
                        memcpy(iv,(unsigned char*)&cacheMemoryOperatingData2[cacheMemorySize-AES_BLOCK_SIZE],AES_BLOCK_SIZE);
                        EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), key, iv);
                        EVP_EncryptUpdate(&ctx, cacheMemoryOperatingData, &outlen1, cacheMemoryOperatingData2, cacheMemorySize);
                        EVP_EncryptFinal(&ctx, cacheMemoryOperatingData + outlen1, &outlen2);
                        EVP_CIPHER_CTX_cleanup(&ctx);
                    }
                    //use last X bits as solution
                    uint32_t solution=cacheMemoryOperatingData32[(cacheMemorySize/4)-1]%comparisonSize;
                    if(solution<1000){
                        uint32_t proofOfCalculation=cacheMemoryOperatingData32[(cacheMemorySize/4)-2];
			pblock.nStartLocation = k;
                        pblock.nFinalCalculation = proofOfCalculation;
                        hash = Hash(BEGIN(pblock.nVersion), END(pblock.nFinalCalculation));
			collisions++;
			if (UintToArith256(hash) <= UintToArith256(hashTarget) && !work_restart[threadNumber].restart){
        		  pdata[21] = swab32(pblock.nFinalCalculation);
        		  pdata[20] = swab32(pblock.nStartLocation);
        		  *hashes_done = collisions;
			  //free memory
			  delete [] cacheMemoryOperatingData;
                	  delete [] cacheMemoryOperatingData2;
        		  return 1;
    			}
                    }
                  }

    //free memory
    delete [] cacheMemoryOperatingData;
    delete [] cacheMemoryOperatingData2;
    *hashes_done = collisions;
    return 0;
}
示例#7
0
bool CTxDB::LoadBlockIndex()
{
    if (!LoadBlockIndexGuts())
        return false;

    if (fRequestShutdown)
        return true;

    // Calculate bnChainTrust
    vector<pair<int, CBlockIndex*> > vSortedByHeight;
    vSortedByHeight.reserve(mapBlockIndex.size());
    BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
    {
        CBlockIndex* pindex = item.second;
        vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
    }
    sort(vSortedByHeight.begin(), vSortedByHeight.end());
    BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
    {
        CBlockIndex* pindex = item.second;
        pindex->bnChainTrust = (pindex->pprev ? pindex->pprev->bnChainTrust : 0) + pindex->GetBlockTrust();
        // ppcoin: calculate stake modifier checksum
        pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
        if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
            return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier);
    }

    // Load hashBestChain pointer to end of best chain
    if (!ReadHashBestChain(hashBestChain))
    {
        if (pindexGenesisBlock == NULL)
            return true;
        return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
    }
    if (!mapBlockIndex.count(hashBestChain))
        return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
    pindexBest = mapBlockIndex[hashBestChain];
    nBestHeight = pindexBest->nHeight;
    bnBestChainTrust = pindexBest->bnChainTrust;
    printf("LoadBlockIndex(): hashBestChain=%s  height=%d  trust=%s  date=%s\n",
      hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(),
      DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());

    // ppcoin: load hashSyncCheckpoint
    if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
        return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
    printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());

    // Load bnBestInvalidTrust, OK if it doesn't exist
    ReadBestInvalidTrust(bnBestInvalidTrust);

    // Verify blocks in the best chain
    int nCheckLevel = GetArg("-checklevel", 1);
    int nCheckDepth = GetArg( "-checkblocks", 2500);
    if (nCheckDepth == 0)
        nCheckDepth = 1000000000; // suffices until the year 19000
    if (nCheckDepth > nBestHeight)
        nCheckDepth = nBestHeight;
    printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
    CBlockIndex* pindexFork = NULL;
    map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
    for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
    {
        if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
            break;
        CBlock block;
        if (!block.ReadFromDisk(pindex))
            return error("LoadBlockIndex() : block.ReadFromDisk failed");
        // check level 1: verify block validity
        if (nCheckLevel>0 && !block.CheckBlock())
        {
            printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
            pindexFork = pindex->pprev;
        }
        // check level 2: verify transaction index validity
        if (nCheckLevel>1)
        {
            pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
            mapBlockPos[pos] = pindex;
            BOOST_FOREACH(const CTransaction &tx, block.vtx)
            {
                uint256 hashTx = tx.GetHash();
                CTxIndex txindex;
                if (ReadTxIndex(hashTx, txindex))
                {
                    // check level 3: checker transaction hashes
                    if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
                    {
                        // either an error or a duplicate transaction
                        CTransaction txFound;
                        if (!txFound.ReadFromDisk(txindex.pos))
                        {
                            printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
                            pindexFork = pindex->pprev;
                        }
                        else
                            if (txFound.GetHash() != hashTx) // not a duplicate tx
                            {
                                printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
                                pindexFork = pindex->pprev;
                            }
                    }
                    // check level 4: check whether spent txouts were spent within the main chain
                    unsigned int nOutput = 0;
                    if (nCheckLevel>3)
                    {
                        BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
                        {
                            if (!txpos.IsNull())
                            {
                                pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
                                if (!mapBlockPos.count(posFind))
                                {
                                    printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
                                    pindexFork = pindex->pprev;
                                }
                                // check level 6: check whether spent txouts were spent by a valid transaction that consume them
                                if (nCheckLevel>5)
                                {
                                    CTransaction txSpend;
                                    if (!txSpend.ReadFromDisk(txpos))
                                    {
                                        printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
                                        pindexFork = pindex->pprev;
                                    }
                                    else if (!txSpend.CheckTransaction())
                                    {
                                        printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
                                        pindexFork = pindex->pprev;
                                    }
                                    else
                                    {
                                        bool fFound = false;
                                        BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
                                            if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
                                                fFound = true;
                                        if (!fFound)
                                        {
                                            printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
                                            pindexFork = pindex->pprev;
                                        }
                                    }
                                }
                            }
                            nOutput++;
                        }
                    }
                }
示例#8
0
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const uint32_t nMode = 0)
{
    UniValue result(UniValue::VOBJ);
    result.push_back(Pair("hash", block.GetHash().GetHex()));
    int confirmations = -1;
    // Only report confirmations if the block is on the main chain
    if (chainActive.Contains(blockindex))
        confirmations = chainActive.Height() - blockindex->nHeight + 1;
    result.push_back(Pair("confirmations", confirmations));
    result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
    result.push_back(Pair("height", blockindex->nHeight));
    result.push_back(Pair("version", block.nVersion));
    result.push_back(Pair("payload", blockindex->GetPayloadString()));
    result.push_back(Pair("payloadhash", blockindex->hashPayload.ToString()));
    result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
    result.push_back(Pair("time", block.GetBlockTime()));
    result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
    result.push_back(Pair("creator", strprintf("0x%08x", blockindex->nCreatorId)));
    result.push_back(Pair("creatorSignature", block.creatorSignature.ToString()));
    result.push_back(Pair("nSignatures", (uint64_t)GetNumChainSigs(blockindex)));
    result.push_back(Pair("nAdminSignatures", (uint64_t)block.vAdminIds.size()));
    result.push_back(Pair("chainSignature", block.chainMultiSig.ToString()));
    result.push_back(Pair("adminMultiSig", block.adminMultiSig.IsNull() ? "" : block.adminMultiSig.ToString()));

    ///////// MISSING CHAIN SIGNERS
    UniValue missingSigners(UniValue::VARR);
    BOOST_FOREACH(const uint32_t& signerId, block.vMissingSignerIds)
    {
        missingSigners.push_back(strprintf("0x%08x", signerId));
    }
    result.push_back(Pair("missingCreatorIds", missingSigners));

    ///////// ADMIN SIGNERS
    UniValue adminSigners(UniValue::VARR);
    BOOST_FOREACH(const uint32_t& signerId, block.vAdminIds)
    {
        adminSigners.push_back(strprintf("0x%08x", signerId));
    }
    result.push_back(Pair("adminSignerIds", adminSigners));

    ///////// TRANSACTIONS
    UniValue txs(UniValue::VARR);
    BOOST_FOREACH(const CTransaction& tx, block.vtx)
    {
        if (nMode >= 5)
        {
            UniValue objTx(UniValue::VOBJ);
            TxToJSON(tx, uint256(), objTx);
            txs.push_back(objTx);
        }
        else
            txs.push_back(tx.GetHash().GetHex());
    }
    result.push_back(Pair("tx", txs));

    if (blockindex->pprev)
        result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
    CBlockIndex *pnext = chainActive.Next(blockindex);
    if (pnext)
        result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));

    if (nMode < 2)
        return result;

    ///////// CVN INFO
    UniValue cvns(UniValue::VARR);
    BOOST_FOREACH(const CCvnInfo& cvn, block.vCvns)
    {
        UniValue objCvn(UniValue::VOBJ);
        objCvn.push_back(Pair("nodeId", strprintf("0x%08x", cvn.nNodeId)));
        objCvn.push_back(Pair("heightAdded", (int) cvn.nHeightAdded));
        if (nMode >= 3)
            objCvn.push_back(Pair("pubKey", cvn.pubKey.ToString()));

        cvns.push_back(objCvn);
    }
    result.push_back(Pair("cvnInfo", cvns));

    ///////// DYNAMIC CHAIN PARAMETERS
    UniValue dParams(UniValue::VOBJ);
    if (block.HasChainParameters()) {
        DynamicChainparametersToJSON(block.dynamicChainParams, dParams);
    }

    result.push_back(Pair("chainParameters", dParams));

    ///////// ADMIN INFO
    UniValue admins(UniValue::VARR);
    BOOST_FOREACH(const CChainAdmin& admin, block.vChainAdmins)
    {
        UniValue objAdmin(UniValue::VOBJ);
        objAdmin.push_back(Pair("adminId", strprintf("0x%08x", admin.nAdminId)));
        objAdmin.push_back(Pair("heightAdded", (int) admin.nHeightAdded));
        if (nMode >= 3)
            objAdmin.push_back(Pair("pubKey", admin.pubKey.ToString()));

        admins.push_back(objAdmin);
    }
    result.push_back(Pair("chainAdmins", admins));

    ///////// COINS SUPPLY
    UniValue coinSupply(UniValue::VOBJ);
    if (block.HasCoinSupplyPayload()) {
        CoinSupplyToJSON(block.coinSupply, coinSupply);
    }

    result.push_back(Pair("coinSupply", coinSupply));

    return result;
}
示例#9
0
std::string BlockToString(CBlockIndex* pBlock)
{
    if (!pBlock)
        return "";

    CBlock block;
    ReadBlockFromDisk(block, pBlock);

    CAmount Fees = 0;
    CAmount OutVolume = 0;
    CAmount Reward = 0;

    std::string TxLabels[] = {_("Hash"), _("From"), _("Amount"), _("To"), _("Amount")};

    std::string TxContent = table + makeHTMLTableRow(TxLabels, sizeof(TxLabels) / sizeof(std::string));
    for (unsigned int i = 0; i < block.vtx.size(); i++) {
        const CTransaction& tx = block.vtx[i];
        TxContent += TxToRow(tx);

        CAmount In = getTxIn(tx);
        CAmount Out = tx.GetValueOut();
        if (tx.IsCoinBase())
            Reward += Out;
        else if (In < 0)
            Fees = -Params().MaxMoneyOut();
        else {
            Fees += In - Out;
            OutVolume += Out;
        }
    }
    TxContent += "</table>";

    CAmount Generated;
    if (pBlock->nHeight == 0)
        Generated = OutVolume;
    else
        Generated = GetBlockValue(pBlock->nHeight - 1);

    std::string BlockContentCells[] =
        {
            _("Height"), itostr(pBlock->nHeight),
            _("Size"), itostr(GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)),
            _("Number of Transactions"), itostr(block.vtx.size()),
            _("Value Out"), ValueToString(OutVolume),
            _("Fees"), ValueToString(Fees),
            _("Generated"), ValueToString(Generated),
            _("Timestamp"), TimeToString(block.nTime),
            _("Difficulty"), strprintf("%.4f", GetDifficulty(pBlock)),
            _("Bits"), utostr(block.nBits),
            _("Nonce"), utostr(block.nNonce),
            _("Version"), itostr(block.nVersion),
            _("Hash"), "<pre>" + block.GetHash().GetHex() + "</pre>",
            _("Merkle Root"), "<pre>" + block.hashMerkleRoot.GetHex() + "</pre>",
            // _("Hash Whole Block"), "<pre>" + block.hashWholeBlock.GetHex() + "</pre>"
            // _("Miner Signature"), "<pre>" + block.MinerSignature.ToString() + "</pre>"
        };

    std::string BlockContent = makeHTMLTable(BlockContentCells, sizeof(BlockContentCells) / (2 * sizeof(std::string)), 2);

    std::string Content;
    Content += "<h2><a class=\"nav\" href=";
    Content += itostr(pBlock->nHeight - 1);
    Content += ">◄&nbsp;</a>";
    Content += _("Block");
    Content += " ";
    Content += itostr(pBlock->nHeight);
    Content += "<a class=\"nav\" href=";
    Content += itostr(pBlock->nHeight + 1);
    Content += ">&nbsp;►</a></h2>";
    Content += BlockContent;
    Content += "</br>";
    /*
    if (block.nHeight > getThirdHardforkBlock())
    {
        std::vector<std::string> votes[2];
        for (int i = 0; i < 2; i++)
        {
            for (unsigned int j = 0; j < block.vvotes[i].size(); j++)
            {
                votes[i].push_back(block.vvotes[i][j].hash.ToString() + ':' + itostr(block.vvotes[i][j].n));
            }
        }
        Content += "<h3>" + _("Votes +") + "</h3>";
        Content += makeHTMLTable(&votes[1][0], votes[1].size(), 1);
        Content += "</br>";
        Content += "<h3>" + _("Votes -") + "</h3>";
        Content += makeHTMLTable(&votes[0][0], votes[0].size(), 1);
        Content += "</br>";
    }
    */
    Content += "<h2>" + _("Transactions") + "</h2>";
    Content += TxContent;

    return Content;
}
示例#10
0
 virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
     if (block.GetHash() != hash)
         return;
     found = true;
     state = stateIn;
 };
Value scaninput(const Array& params, bool fHelp)
{
    if (fHelp || params.size() > 4 || params.size() < 2)
        throw runtime_error(
            "scaninput <txid> <nout> [difficulty] [days]\n"
            "Scan specified input for suitable kernel solutions.\n"
            "    [difficulty] - upper limit for difficulty, current difficulty by default;\n"
            "    [days] - time window, 365 days by default.\n"
        );


    uint256 hash;
    hash.SetHex(params[0].get_str());

    uint32_t nOut = params[1].get_int(), nBits = GetNextTargetRequired(pindexBest, true), nDays = 365;

    if (params.size() > 2)
    {
        CBigNum bnTarget(nPoWBase);
        bnTarget *= 1000;
        bnTarget /= (int) (params[2].get_real() * 1000);
        nBits = bnTarget.GetCompact();
    }

    if (params.size() > 3)
    {
        nDays = params[3].get_int();
    }

    CTransaction tx;
    uint256 hashBlock = 0;
    if (GetTransaction(hash, tx, hashBlock))
    {
        if (nOut > tx.vout.size())
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Incorrect output number");

        if (hashBlock == 0)
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to find transaction in the blockchain");

        CTxDB txdb("r");

        CBlock block;
        CTxIndex txindex;

        // Load transaction index item
        if (!txdb.ReadTxIndex(tx.GetHash(), txindex))
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to read block index item");

        // Read block header
        if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "CBlock::ReadFromDisk() failed");

        uint64_t nStakeModifier = 0;
        if (!GetKernelStakeModifier(block.GetHash(), nStakeModifier))
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No kernel stake modifier generated yet");

        std::pair<uint32_t, uint32_t> interval;
        interval.first = GetTime();
        // Only count coins meeting min age requirement
        if (nStakeMinAge + block.nTime > interval.first)
            interval.first += (nStakeMinAge + block.nTime - interval.first);
        interval.second = interval.first + nDays * 86400;

        SHA256_CTX ctx;
        GetKernelMidstate(nStakeModifier, block.nTime, txindex.pos.nTxPos - txindex.pos.nBlockPos, tx.nTime, nOut, ctx);

        std::pair<uint256, uint32_t> solution;
        if (ScanMidstateForward(ctx, nBits, tx.nTime, tx.vout[nOut].nValue, interval, solution))
        {
            Object r;
            r.push_back(Pair("hash", solution.first.GetHex()));
            r.push_back(Pair("time", DateTimeStrFormat(solution.second)));

            return r;
        }
    }
    else
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");

    return Value::null;
}
示例#12
0
UniValue getblocktemplate(const JSONRPCRequest& request)
{
    if (request.fHelp || request.params.size() > 1)
        throw std::runtime_error(
            "getblocktemplate ( TemplateRequest )\n"
            "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
            "It returns data needed to construct a block to work on.\n"
            "For full specification, see BIPs 22, 23, 9, and 145:\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n"

            "\nArguments:\n"
            "1. template_request         (json object, optional) A json object in the following spec\n"
            "     {\n"
            "       \"mode\":\"template\"    (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n"
            "       \"capabilities\":[     (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
            "           ,...\n"
            "       ],\n"
            "       \"rules\":[            (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported softfork deployment\n"
            "           ,...\n"
            "       ]\n"
            "     }\n"
            "\n"

            "\nResult:\n"
            "{\n"
            "  \"version\" : n,                    (numeric) The preferred block version\n"
            "  \"rules\" : [ \"rulename\", ... ],    (array of strings) specific block rules that are to be enforced\n"
            "  \"vbavailable\" : {                 (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
            "      \"rulename\" : bitnumber          (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
            "      ,...\n"
            "  },\n"
            "  \"vbrequired\" : n,                 (numeric) bit mask of versionbits the server requires set in submissions\n"
            "  \"previousblockhash\" : \"xxxx\",     (string) The hash of current highest block\n"
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
            "      {\n"
            "         \"data\" : \"xxxx\",             (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
            "         \"txid\" : \"xxxx\",             (string) transaction id encoded in little-endian hexadecimal\n"
            "         \"hash\" : \"xxxx\",             (string) hash encoded in little-endian hexadecimal (including witness data)\n"
            "         \"depends\" : [                (array) array of numbers \n"
            "             n                          (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
            "             ,...\n"
            "         ],\n"
            "         \"fee\": n,                    (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
            "         \"sigops\" : n,                (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
            "         \"weight\" : n,                (numeric) total transaction weight, as counted for purposes of block limits\n"
            "         \"required\" : true|false      (boolean) if provided and true, this transaction must be in the final block\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"coinbaseaux\" : {                 (json object) data that should be included in the coinbase's scriptSig content\n"
            "      \"flags\" : \"xx\"                  (string) key name is to be ignored, and value included in scriptSig\n"
            "  },\n"
            "  \"coinbasevalue\" : n,              (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
            "  \"coinbasetxn\" : { ... },          (json object) information for coinbase transaction\n"
            "  \"target\" : \"xxxx\",                (string) The hash target\n"
            "  \"mintime\" : xxx,                  (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"mutable\" : [                     (array of string) list of ways the block template may be changed \n"
            "     \"value\"                          (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
            "     ,...\n"
            "  ],\n"
            "  \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n"
            "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
            "  \"weightlimit\" : n,                (numeric) limit of block weight\n"
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"bits\" : \"xxxxxxxx\",              (string) compressed target of next block\n"
            "  \"height\" : n                      (numeric) The height of the next block\n"
            "}\n"

            "\nExamples:\n"
            + HelpExampleCli("getblocktemplate", "")
            + HelpExampleRpc("getblocktemplate", "")
         );

    LOCK(cs_main);

    std::string strMode = "template";
    UniValue lpval = NullUniValue;
    std::set<std::string> setClientRules;
    int64_t nMaxVersionPreVB = -1;
    if (!request.params[0].isNull())
    {
        const UniValue& oparam = request.params[0].get_obj();
        const UniValue& modeval = find_value(oparam, "mode");
        if (modeval.isStr())
            strMode = modeval.get_str();
        else if (modeval.isNull())
        {
            /* Do nothing */
        }
        else
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
        lpval = find_value(oparam, "longpollid");

        if (strMode == "proposal")
        {
            const UniValue& dataval = find_value(oparam, "data");
            if (!dataval.isStr())
                throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");

            CBlock block;
            if (!DecodeHexBlk(block, dataval.get_str()))
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");

            uint256 hash = block.GetHash();
            BlockMap::iterator mi = mapBlockIndex.find(hash);
            if (mi != mapBlockIndex.end()) {
                CBlockIndex *pindex = mi->second;
                if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
                    return "duplicate";
                if (pindex->nStatus & BLOCK_FAILED_MASK)
                    return "duplicate-invalid";
                return "duplicate-inconclusive";
            }

            CBlockIndex* const pindexPrev = chainActive.Tip();
            // TestBlockValidity only supports blocks built on the current Tip
            if (block.hashPrevBlock != pindexPrev->GetBlockHash())
                return "inconclusive-not-best-prevblk";
            CValidationState state;
            TestBlockValidity(state, Params(), block, pindexPrev, false, true);
            return BIP22ValidationResult(state);
        }

        const UniValue& aClientRules = find_value(oparam, "rules");
        if (aClientRules.isArray()) {
            for (unsigned int i = 0; i < aClientRules.size(); ++i) {
                const UniValue& v = aClientRules[i];
                setClientRules.insert(v.get_str());
            }
        } else {
            // NOTE: It is important that this NOT be read if versionbits is supported
            const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
            if (uvMaxVersion.isNum()) {
                nMaxVersionPreVB = uvMaxVersion.get_int64();
            }
        }
    }

    if (strMode != "template")
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");

    if(!g_connman)
        throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

    if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
        throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Litecoin is not connected!");

    if (IsInitialBlockDownload())
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Litecoin is downloading blocks...");

    static unsigned int nTransactionsUpdatedLast;

    if (!lpval.isNull())
    {
        // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
        uint256 hashWatchedChain;
        boost::system_time checktxtime;
        unsigned int nTransactionsUpdatedLastLP;

        if (lpval.isStr())
        {
            // Format: <hashBestChain><nTransactionsUpdatedLast>
            std::string lpstr = lpval.get_str();

            hashWatchedChain.SetHex(lpstr.substr(0, 64));
            nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
        }
        else
        {
            // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
            hashWatchedChain = chainActive.Tip()->GetBlockHash();
            nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
        }

        // Release the wallet and main lock while waiting
        LEAVE_CRITICAL_SECTION(cs_main);
        {
            checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);

            boost::unique_lock<boost::mutex> lock(csBestBlock);
            while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
            {
                if (!cvBlockChange.timed_wait(lock, checktxtime))
                {
                    // Timeout: Check transactions for update
                    if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
                        break;
                    checktxtime += boost::posix_time::seconds(10);
                }
            }
        }
        ENTER_CRITICAL_SECTION(cs_main);

        if (!IsRPCRunning())
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
        // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
    }

    const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
    // If the caller is indicating segwit support, then allow CreateNewBlock()
    // to select witness transactions, after segwit activates (otherwise
    // don't).
    bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end();

    // Update block
    static CBlockIndex* pindexPrev;
    static int64_t nStart;
    static std::unique_ptr<CBlockTemplate> pblocktemplate;
    // Cache whether the last invocation was with segwit support, to avoid returning
    // a segwit-block to a non-segwit caller.
    static bool fLastTemplateSupportsSegwit = true;
    if (pindexPrev != chainActive.Tip() ||
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
        fLastTemplateSupportsSegwit != fSupportsSegwit)
    {
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
        pindexPrev = nullptr;

        // Store the pindexBest used before CreateNewBlock, to avoid races
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
        CBlockIndex* pindexPrevNew = chainActive.Tip();
        nStart = GetTime();
        fLastTemplateSupportsSegwit = fSupportsSegwit;

        // Create new block
        CScript scriptDummy = CScript() << OP_TRUE;
        pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit);
        if (!pblocktemplate)
            throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");

        // Need to update only after we know CreateNewBlock succeeded
        pindexPrev = pindexPrevNew;
    }
    CBlock* pblock = &pblocktemplate->block; // pointer for convenience
    const Consensus::Params& consensusParams = Params().GetConsensus();

    // Update nTime
    UpdateTime(pblock, consensusParams, pindexPrev);
    pblock->nNonce = 0;

    // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
    const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));

    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

    UniValue transactions(UniValue::VARR);
    std::map<uint256, int64_t> setTxIndex;
    int i = 0;
    for (const auto& it : pblock->vtx) {
        const CTransaction& tx = *it;
        uint256 txHash = tx.GetHash();
        setTxIndex[txHash] = i++;

        if (tx.IsCoinBase())
            continue;

        UniValue entry(UniValue::VOBJ);

        entry.push_back(Pair("data", EncodeHexTx(tx)));
        entry.push_back(Pair("txid", txHash.GetHex()));
        entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));

        UniValue deps(UniValue::VARR);
        for (const CTxIn &in : tx.vin)
        {
            if (setTxIndex.count(in.prevout.hash))
                deps.push_back(setTxIndex[in.prevout.hash]);
        }
        entry.push_back(Pair("depends", deps));

        int index_in_template = i - 1;
        entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
        int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
        if (fPreSegWit) {
            assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
            nTxSigOps /= WITNESS_SCALE_FACTOR;
        }
        entry.push_back(Pair("sigops", nTxSigOps));
        entry.push_back(Pair("weight", GetTransactionWeight(tx)));

        transactions.push_back(entry);
    }

    UniValue aux(UniValue::VOBJ);
    aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));

    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);

    UniValue aMutable(UniValue::VARR);
    aMutable.push_back("time");
    aMutable.push_back("transactions");
    aMutable.push_back("prevblock");

    UniValue result(UniValue::VOBJ);
    result.push_back(Pair("capabilities", aCaps));

    UniValue aRules(UniValue::VARR);
    UniValue vbavailable(UniValue::VOBJ);
    for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
        Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
        ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
        switch (state) {
            case THRESHOLD_DEFINED:
            case THRESHOLD_FAILED:
                // Not exposed to GBT at all
                break;
            case THRESHOLD_LOCKED_IN:
                // Ensure bit is set in block version
                pblock->nVersion |= VersionBitsMask(consensusParams, pos);
                // FALL THROUGH to get vbavailable set...
            case THRESHOLD_STARTED:
            {
                const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    if (!vbinfo.gbt_force) {
                        // If the client doesn't support this, don't indicate it in the [default] version
                        pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
                    }
                }
                break;
            }
            case THRESHOLD_ACTIVE:
            {
                // Add to rules only
                const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                aRules.push_back(gbt_vb_name(pos));
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    // Not supported by the client; make sure it's safe to proceed
                    if (!vbinfo.gbt_force) {
                        // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
                        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
                    }
                }
                break;
            }
        }
    }
    result.push_back(Pair("version", pblock->nVersion));
    result.push_back(Pair("rules", aRules));
    result.push_back(Pair("vbavailable", vbavailable));
    result.push_back(Pair("vbrequired", int(0)));

    if (nMaxVersionPreVB >= 2) {
        // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
        // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks
        // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
        // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
        aMutable.push_back("version/force");
    }

    result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
    result.push_back(Pair("transactions", transactions));
    result.push_back(Pair("coinbaseaux", aux));
    result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue));
    result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
    result.push_back(Pair("target", hashTarget.GetHex()));
    result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
    result.push_back(Pair("mutable", aMutable));
    result.push_back(Pair("noncerange", "00000000ffffffff"));
    int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
    int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
    if (fPreSegWit) {
        assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
        nSigOpLimit /= WITNESS_SCALE_FACTOR;
        assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
        nSizeLimit /= WITNESS_SCALE_FACTOR;
    }
    result.push_back(Pair("sigoplimit", nSigOpLimit));
    result.push_back(Pair("sizelimit", nSizeLimit));
    if (!fPreSegWit) {
        result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
    }
    result.push_back(Pair("curtime", pblock->GetBlockTime()));
    result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
    result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));

    if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
        result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())));
    }

    return result;
}
示例#13
0
		bool CRenderManager::update()
		{
			glColor3f(1.0f,1.0f,1.0f);

			// get camera
			CCamera *camera = CV_GAME_MANAGER->getControlManager()->getCamera();

			// transform view
			camera->transformView();			

			// Draw the map and items that fall into view frustum. 								

			// 1. extract approximate logical location of camera in the level map.
			vector2i center = CConversions::realToLogical(camera->getPosition());

			GLint centerX = center[0];
			GLint centerY = center[1];

			bool isFPS = CV_GAME_MANAGER->getControlManager()->isFPS();

			if (isFPS)
			{
				// fog only in FPS mode
				glEnable(GL_FOG);
			}

			/*
				In FPS mode we can't use height to determine visible offset. 
				We have to use some extent read from config (CV_CAMERA_FPS_EXTENT).
			*/
			GLint diff = (GLint)(isFPS?cameraFPSExtent:camera->getPosition()[1]*10.0f);

			// 2. create a bounding square making its center logical position calculate above.
			GLint minX = (centerX-diff>=0?centerX-diff:0);
			GLint minY = (centerY-diff>=0?centerY-diff:0);
			GLint maxX = (centerX+diff<(GLint)CV_LEVEL_MAP_SIZE?centerX+diff:CV_LEVEL_MAP_SIZE-1);
			GLint maxY = (centerY+diff<(GLint)CV_LEVEL_MAP_SIZE?centerY+diff:CV_LEVEL_MAP_SIZE-1);			

			// 3. go through all block that fall into this bounding square and check if they fall
			//    int out view frustum. If not then just exclude them.

			CBlock *block;

			GLint	blockVisible = 0,
					allVerticesCount = 0,
					creaturesVisible = 0,
					maxVertInput = 0,
					maxTexInput  = 0;

			tmpVboVertexBufferSize = 0;
			tmpVboTexCoordBufferSize = 0;

			vector3f	vertA,
						vertB,
						vertC;

			GLfloat **verts,
					*texCoords;

			CLevelManager			*lManager = CV_GAME_MANAGER->getLevelManager();
			CAnimatedTerrainManager	*atManager = CV_GAME_MANAGER->getAnimatedTerrainManager();
			CFrustum				*frustum = CV_GAME_MANAGER->getControlManager()->getViewFrustum();

			bool lavaWater = false;

			GLfloat delta = CV_GAME_MANAGER->getDeltaTime();	

			renderedBlocks.clear();

			for (GLint y=minY; y<=maxY; y++)
			{
				for (GLint x=minX; x<=maxX; x++)
				{
					block = lManager->getBlock(x,y);

					if (block)
					{
						//block->getBoundingBox()->draw(); // just for testing
						if (frustum->containsBBOX(block->getBoundingBox()))
						{
							blockVisible++;

							block->updateTexture(delta);

							lavaWater = (block->isLava() || block->isWater());

							if (lavaWater)
							{
								atManager->updateBlock(block);
							}

							renderedBlocks.push_back(block);

							// draw block objects
							if (block->getBlockObjects()->size()>0)
							{
								for (std::vector<CBlockObject*>::iterator rmIter = block->getBlockObjects()->begin(); rmIter != block->getBlockObjects()->end(); rmIter++)
								{
									CBlockObject *bObj = *rmIter;

									bObj->moveTo();
									glRotatef(bObj->getRotateY(),0.0f,1.0f,0.0f);
									bObj->drawModel(delta);
									glRotatef(-bObj->getRotateY(),0.0f,1.0f,0.0f);
									bObj->moveBack();
								}
							}

							bool isRoom = block->isRoom();

							if (isRoom)
							{
								std::vector<GLuint> *dls = block->getDisplayLists();
								if (dls->size()!=0)
								{			
									glEnable(GL_TEXTURE_2D);
									glBindTexture(GL_TEXTURE_2D,textureAtlasColor);
									glBegin(GL_QUADS);
									{
										for (std::vector<GLuint>::iterator dlIter = dls->begin(); dlIter != dls->end(); dlIter++)
										{
											glCallList(*dlIter);									
										}
									}
									glEnd();
									glDisable(GL_TEXTURE_2D);									
								}
							}							

							for (GLint f=CBlock::BFS_FRONT; f<=CBlock::BFS_CEILING; f++)
							{
								if ((!isFPS && f==CBlock::BFS_CEILING) || (isFPS && f==CBlock::BFS_TOP) || (isRoom && f!=CBlock::BFS_CEILING))
								{
									continue;
								}

								if (block->isFaceVisible((CBlock::BLOCK_FACE_SELECTOR)f))
								{		
									verts = block->getVertices();
									texCoords = block->getTextureCoordinates((CBlock::BLOCK_FACE_SELECTOR)f);

									if (lavaWater && f<=CBlock::BFS_RIGHT)
									{
										/* 
											Lava and water have only lowers row of wall sections drawn. 
											If they are drawn at all.
										*/
										maxVertInput = CV_FBLR_W_L_FACE_VERT_FLOATS;
										maxTexInput = CV_FBLR_W_L_FACE_TEX_FLOATS;
									}
									else
									{
										maxVertInput = f>=CBlock::BFS_TOP?CV_TBWLC_FACE_VERT_FLOATS:CV_FBLR_FACE_VERT_FLOATS;
										maxTexInput = f>=CBlock::BFS_TOP?CV_TBWLC_FACE_TEX_FLOATS:CV_FBLR_FACE_TEX_FLOATS;
									}

									if (tmpVboVertexBufferSize+maxVertInput>CV_MAX_VERTEX_BUFFER*3)
									{		
										vbo->setElementsCount(CVBO::IDT_vertex,tmpVboVertexBufferSize/3);
										vbo->setElementsCount(CVBO::IDT_texture0,tmpVboTexCoordBufferSize/2);
										vbo->setElementsCount(CVBO::IDT_texture1,tmpVboTexCoordBufferSize/2);
										vbo->draw();
										allVerticesCount+=tmpVboVertexBufferSize;
										tmpVboVertexBufferSize=0;
										tmpVboTexCoordBufferSize=0;						
									}

									memcpy(tmpVboVertexBuffer+tmpVboVertexBufferSize, verts[f], sizeof(GLfloat)*maxVertInput);
									tmpVboVertexBufferSize+=maxVertInput;

									memcpy(tmpVboTexCoordBuffer+tmpVboTexCoordBufferSize, texCoords, sizeof(GLfloat)*maxTexInput);						
									tmpVboTexCoordBufferSize+=maxTexInput;
																	
								}
							}
						}
					}
				}
			}

			if (tmpVboVertexBufferSize>0)
			{		
				vbo->setElementsCount(CVBO::IDT_vertex,tmpVboVertexBufferSize/3);
				vbo->setElementsCount(CVBO::IDT_texture0,tmpVboTexCoordBufferSize/2);
				vbo->setElementsCount(CVBO::IDT_texture1,tmpVboTexCoordBufferSize/2);
				vbo->draw();
				allVerticesCount+=tmpVboVertexBufferSize;
			}	

			// draw creatures
			CCreatureManager *cManager = CV_GAME_MANAGER->getCreatureManager();
			GLint cCount = cManager->getCreatureVector()->size();
			if (cCount>0)
			{		
				CCreature *creature = NULL;
				for (std::vector<CCreature*>::iterator cIter = cManager->getCreatureVector()->begin(); cIter != cManager->getCreatureVector()->end(); cIter++)
				{
					creature = (*cIter);

					if (creature)
					{
						sBoundingBox *cBBOX = creature->getModel()->getBoundingBox();
						cBBOX->translate(creature->getPosition());
						if (frustum->containsBBOX(cBBOX))
						{
							creature->draw(delta);
							creaturesVisible++;
						}
						cBBOX->translate(-creature->getPosition());
					}
				}
			}

			// draw transparent block objects
			for (std::vector<CBlock*>::iterator vbIter = renderedBlocks.begin(); vbIter != renderedBlocks.end(); vbIter++)
			{
				block = *vbIter;
				if (block->getBlockObjects()->size()>0)
				{
					for (std::vector<CBlockObject*>::iterator rmIter = block->getBlockObjects()->begin(); rmIter != block->getBlockObjects()->end(); rmIter++)
					{
						CBlockObject *bObj = *rmIter;

						bObj->moveTo();
						glRotatef(bObj->getRotateY(),0.0f,1.0f,0.0f);
						bObj->drawEffect();
						glRotatef(-bObj->getRotateY(),0.0f,1.0f,0.0f);
						bObj->moveBack();
					}
				}
			}

			glDisable(GL_FOG);
			
			if (!isFPS)
			{
				handlePickedObjects();
			}

			CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15*3),"Visible blocks: %d",blockVisible);
			CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15*2),"Visible creatures: %d",creaturesVisible);
			CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15),"Triangles drawn: %d",(allVerticesCount/4)*2);

			// render the lights representations. usefull for debugging
			CV_GAME_MANAGER->getLightingManager()->drawLightSources(frustum);
            
			return true;
		}
示例#14
0
		GLvoid CRenderManager::handlePickedObjects()
		{
			// if we are ower the menu we do not have to proccess things under the cursor
			if (CV_GAME_MANAGER->getGUIManager()->getPlayGUI()->is_mouse_over_gui())
			{
				return;
			}

			// if we are not selling or buying we don't have to process blocks (just objects TODO)
			ACTION_EVENT *ae = CV_GAME_MANAGER->getGUIManager()->getLastActionEvent();
			
			// get the block we have our cousor on
			CBlock *pickedBlock = CV_GAME_MANAGER->getPickingManager()->getLastPickedBlock();

			if (pickedBlock)
			{
				GLint type = pickedBlock->getType();

				/*if (!pickedBlock->isSellable())
				{
					return;
				}*/

				sBoundingBox *bbox = pickedBlock->getBoundingBox();

				vector3f a(bbox->A);
				vector3f b(bbox->B);
				vector3f c(bbox->C);
				vector3f d(bbox->D);
				vector3f e(bbox->E);
				vector3f f(bbox->F);
				vector3f g(bbox->G);
				vector3f h(bbox->H);

				a[1]=b[1]=c[1]=d[1]=CV_BLOCK_HEIGHT+CV_BLOCK_HEIGHT/4.0f+CV_BLOCK_HEIGHT/32.0f;
				e[1]=f[1]=g[1]=h[1]=CV_BLOCK_HEIGHT/4.0f+CV_BLOCK_HEIGHT/32.0f;

				glLineWidth(4.0f);

				if (pickedBlock->isLow())
				{
					if (!(ae->message_group==AEMG_BUILD_ROOMS || ae->message_group==AEMG_BUILD_DOORS || ae->message_group==AEMG_BUILD_TRAPS))
					{
						return;
					}

					// draw the selection box					

					if (pickedBlock->isSellable(CV_CURRENT_PLAYER_ID) && ae->message == AEM_SELL)
					{
						glColor3f(0.0f,1.0f,0.0f);
					}
					else if (pickedBlock->isBuildable(CV_CURRENT_PLAYER_ID) && ae->message != AEM_SELL)
					{
						glColor3f(0.0f,1.0f,0.0f);
					}
					else
					{
						glColor3f(1.0f,0.0f,0.0f);
					}
					
					glBegin(GL_LINES);
					{
						/*glVertex3fv(&a[0]); glVertex3fv(&b[0]);
						glVertex3fv(&b[0]); glVertex3fv(&c[0]);
						glVertex3fv(&c[0]); glVertex3fv(&d[0]);
						glVertex3fv(&d[0]); glVertex3fv(&a[0]);*/

						glVertex3fv(&e[0]); glVertex3fv(&f[0]);
						glVertex3fv(&f[0]); glVertex3fv(&g[0]);
						glVertex3fv(&g[0]); glVertex3fv(&h[0]);
						glVertex3fv(&h[0]); glVertex3fv(&e[0]);

						/*glVertex3fv(&a[0]); glVertex3fv(&e[0]);
						glVertex3fv(&b[0]); glVertex3fv(&f[0]);
						glVertex3fv(&c[0]); glVertex3fv(&g[0]);
						glVertex3fv(&d[0]); glVertex3fv(&h[0]);*/
					}
					glEnd();
				}
				else
				{		
					if (!(ae->message_group==AEMG_BUILD_ROOMS || ae->message_group==AEMG_BUILD_DOORS || ae->message_group==AEMG_BUILD_TRAPS))
						glColor3f(type==CV_BLOCK_TYPE_ROCK_ID?1.0f:0.0f,type==CV_BLOCK_TYPE_ROCK_ID?0.0f:1.0f,0.0f);
					else
						glColor3f(1.0f,0.0f,0.0f);
			
					glBegin(GL_LINES);
					{
						glVertex3fv(&a[0]); glVertex3fv(&b[0]);
						glVertex3fv(&b[0]); glVertex3fv(&c[0]);
						glVertex3fv(&c[0]); glVertex3fv(&d[0]);
						glVertex3fv(&d[0]); glVertex3fv(&a[0]);

						glVertex3fv(&e[0]); glVertex3fv(&f[0]);
						glVertex3fv(&f[0]); glVertex3fv(&g[0]);
						glVertex3fv(&g[0]); glVertex3fv(&h[0]);
						glVertex3fv(&h[0]); glVertex3fv(&e[0]);

						glVertex3fv(&a[0]); glVertex3fv(&e[0]);
						glVertex3fv(&b[0]); glVertex3fv(&f[0]);
						glVertex3fv(&c[0]); glVertex3fv(&g[0]);
						glVertex3fv(&d[0]); glVertex3fv(&h[0]);
					}
					glEnd();
				}

				glLineWidth(1.0f);
			}
		}
示例#15
0
// note new return type, this now returns the bad block number, else 0 for success.
//
//  I also return -ve block numbers for errors between blocks. Eg if you read 3 good blocks, then find an unexpected
//		float in the script between blocks 3 & 4 then I return -3 to indicate the error is after that, but not block 4
//
int	CInterpreter::Interpret( CTokenizer *Tokenizer, CBlockStream *BlockStream, char *filename )
{
	CBlock		block;
	CToken		*token;
	int			type, blockLevel = 0, parenthesisLevel = 0;

	m_sCurrentFile	= filename;		// used during error reporting because you can't ask tokenizer for pushed streams
	
	m_tokenizer		= Tokenizer;
	m_blockStream	= BlockStream;

	m_iCurrentLine = m_tokenizer->GetCurLine();
	token = m_tokenizer->GetToEndOfLine(TK_STRING);		
	m_sCurrentLine = token->GetStringValue();	
	m_tokenizer->PutBackToken(token, false, NULL, true);
	
	m_iBadCBlockNumber = 0;

	while (m_tokenizer->GetRemainingSize() > 0)
	{
		token = m_tokenizer->GetToken( TKF_USES_EOL, 0 );
		type = token->GetType();

		switch ( type )
		{
		case TK_UNDEFINED:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("%d : undefined token", type);
			return m_iBadCBlockNumber;
			break;

		case TK_EOF:
			break;

		case TK_EOL:
			// read the next line, then put it back
			token->Delete();
			m_iCurrentLine = m_tokenizer->GetCurLine();
			token = m_tokenizer->GetToEndOfLine(TK_STRING);			
			m_sCurrentLine = token->GetStringValue();				
			m_tokenizer->PutBackToken(token, false, NULL, true);
			break;
		
		case TK_CHAR:
		case TK_STRING:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected string");
			return m_iBadCBlockNumber;
			break;
		
		case TK_INT:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;		
			Error("syntax error : unexpected integer");
			return m_iBadCBlockNumber;
			break;
		
		case TK_FLOAT:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected float");
			return m_iBadCBlockNumber;
			break;
		
		case TK_IDENTIFIER:
			m_iBadCBlockNumber++;
			if (!GetID( (char *) token->GetStringValue() ))
			{
				token->Delete();
				return m_iBadCBlockNumber;
			}
			token->Delete();
			break;
		
		case TK_BLOCK_START:
			token->Delete();
			if (parenthesisLevel)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : brace inside parenthesis");
				return m_iBadCBlockNumber;
			}

			blockLevel++;
			break;

		case TK_BLOCK_END:
			token->Delete();
			if (parenthesisLevel)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : brace inside parenthesis");
				return m_iBadCBlockNumber;
			}
			
			block.Create( ID_BLOCK_END );
			m_blockStream->WriteBlock( &block );
			block.Free();

			blockLevel--;
			break;

		case TK_OPEN_PARENTHESIS:
			token->Delete();
			blockLevel++;
			parenthesisLevel++;
			break;

		case TK_CLOSED_PARENTHESIS:
			token->Delete();
			blockLevel--;
			parenthesisLevel--;

			if (parenthesisLevel<0)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : closed parenthesis with no opening match");
				return m_iBadCBlockNumber;
			}
			break;

		case TK_VECTOR_START:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected vector");
			return m_iBadCBlockNumber;
			break;

		case TK_VECTOR_END:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected vector");
			return m_iBadCBlockNumber;
			break;
		}
	}

	if ( blockLevel )
	{
		m_iBadCBlockNumber = -m_iBadCBlockNumber;
		Error("error : open brace was not closed");
		return m_iBadCBlockNumber;
	}

	if ( parenthesisLevel )
	{
		m_iBadCBlockNumber = -m_iBadCBlockNumber;
		Error("error: open parenthesis");
		return m_iBadCBlockNumber;
	}

	//Release all the variable information, because it's already been written out
	FreeVars();

	m_iBadCBlockNumber = 0;
	return m_iBadCBlockNumber;	//true;
}
示例#16
0
bool CreateCoinStake( CBlock &blocknew, CKey &key,
    vector<const CWalletTx*> &StakeInputs, uint64_t &CoinAge,
    CWallet &wallet, CBlockIndex* pindexPrev )
{
    int64_t CoinWeight;
    CBigNum StakeKernelHash;
    CTxDB txdb("r");
    int64_t StakeWeightSum = 0;
    double StakeValueSum = 0;
    int64_t StakeWeightMin=MAX_MONEY;
    int64_t StakeWeightMax=0;
    uint64_t StakeCoinAgeSum=0;
    double StakeDiffSum = 0;
    double StakeDiffMax = 0;
    CTransaction &txnew = blocknew.vtx[1]; // second tx is coinstake

    //initialize the transaction
    txnew.nTime = blocknew.nTime & (~STAKE_TIMESTAMP_MASK);
    txnew.vin.clear();
    txnew.vout.clear();

    // Choose coins to use
    set <pair <const CWalletTx*,unsigned int> > CoinsToStake;

    int64_t BalanceToStake = wallet.GetBalance();
    int64_t nValueIn = 0;
    //Request all the coins here, check reserve later

    if ( BalanceToStake<=0
        || !wallet.SelectCoinsForStaking(BalanceToStake*2, txnew.nTime, CoinsToStake, nValueIn) )
    {
        LOCK(MinerStatus.lock);
        MinerStatus.ReasonNotStaking+=_("No coins; ");
        if (fDebug) LogPrintf("CreateCoinStake: %s",MinerStatus.ReasonNotStaking);
        return false;
    }
    BalanceToStake -= nReserveBalance;

    if(fDebug2) LogPrintf("\nCreateCoinStake: Staking nTime/16= %d Bits= %u",
    txnew.nTime/16,blocknew.nBits);

    for(const auto& pcoin : CoinsToStake)
    {
        const CTransaction &CoinTx =*pcoin.first; //transaction that produced this coin
        unsigned int CoinTxN =pcoin.second; //index of this coin inside it

        CTxIndex txindex;
        {
            LOCK2(cs_main, wallet.cs_wallet);
            if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
                continue; //error?
        }

        CBlock CoinBlock; //Block which contains CoinTx
        {
            LOCK2(cs_main, wallet.cs_wallet);
            if (!CoinBlock.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
                continue;
        }

        // only count coins meeting min age requirement
        if (CoinBlock.GetBlockTime() + nStakeMinAge > txnew.nTime)
            continue;

        if (CoinTx.vout[CoinTxN].nValue > BalanceToStake)
            continue;

        {
            int64_t nStakeValue= CoinTx.vout[CoinTxN].nValue;
            StakeValueSum += nStakeValue /(double)COIN;
            //crazy formula...
            // todo: clean this
            // todo reuse calculated value for interst
            CBigNum bn = CBigNum(nStakeValue) * (blocknew.nTime-CoinTx.nTime) / CENT;
            bn = bn * CENT / COIN / (24 * 60 * 60);
            StakeCoinAgeSum += bn.getuint64();
        }

        if(blocknew.nVersion==7)
        {
            NetworkTimer();
            CoinWeight = CalculateStakeWeightV3(CoinTx,CoinTxN,GlobalCPUMiningCPID);
            StakeKernelHash= CalculateStakeHashV3(CoinBlock,CoinTx,CoinTxN,txnew.nTime,GlobalCPUMiningCPID,mdPORNonce);
        }
        else
        {
            uint64_t StakeModifier = 0;
            if(!FindStakeModifierRev(StakeModifier,pindexPrev))
                continue;
            CoinWeight = CalculateStakeWeightV8(CoinTx,CoinTxN,GlobalCPUMiningCPID);
            StakeKernelHash= CalculateStakeHashV8(CoinBlock,CoinTx,CoinTxN,txnew.nTime,StakeModifier,GlobalCPUMiningCPID);
        }

        CBigNum StakeTarget;
        StakeTarget.SetCompact(blocknew.nBits);
        StakeTarget*=CoinWeight;
        StakeWeightSum += CoinWeight;
        StakeWeightMin=std::min(StakeWeightMin,CoinWeight);
        StakeWeightMax=std::max(StakeWeightMax,CoinWeight);
        double StakeKernelDiff = GetBlockDifficulty(StakeKernelHash.GetCompact())*CoinWeight;
        StakeDiffSum += StakeKernelDiff;
        StakeDiffMax = std::max(StakeDiffMax,StakeKernelDiff);

        if (fDebug2) {
            int64_t RSA_WEIGHT = GetRSAWeightByBlock(GlobalCPUMiningCPID);
            LogPrintf(
"CreateCoinStake: V%d Time %.f, Por_Nonce %.f, Bits %jd, Weight %jd\n"
" RSA_WEIGHT %.f\n"
" Stk %72s\n"
" Trg %72s\n"
" Diff %0.7f of %0.7f\n",
            blocknew.nVersion,
            (double)txnew.nTime, mdPORNonce,
            (intmax_t)blocknew.nBits,(intmax_t)CoinWeight,
            (double)RSA_WEIGHT,
            StakeKernelHash.GetHex().c_str(), StakeTarget.GetHex().c_str(),
            StakeKernelDiff, GetBlockDifficulty(blocknew.nBits)
            );
        }

        if( StakeKernelHash <= StakeTarget )
        {
            // Found a kernel
            LogPrintf("\nCreateCoinStake: Found Kernel;\n");
            blocknew.nNonce= mdPORNonce;
            vector<valtype> vSolutions;
            txnouttype whichType;
            CScript scriptPubKeyOut;
            CScript scriptPubKeyKernel;
            scriptPubKeyKernel = CoinTx.vout[CoinTxN].scriptPubKey;
            if (!Solver(scriptPubKeyKernel, whichType, vSolutions))
            {
                LogPrintf("CreateCoinStake: failed to parse kernel\n");
                break;
            }
            if (whichType == TX_PUBKEYHASH) // pay to address type
            {
                // convert to pay to public key type
                if (!wallet.GetKey(uint160(vSolutions[0]), key))
                {
                    LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType);
                    break;  // unable to find corresponding public key
                }
                scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG;
            }
            else if (whichType == TX_PUBKEY)  // pay to public key type
            {
                valtype& vchPubKey = vSolutions[0];
                if (!wallet.GetKey(Hash160(vchPubKey), key)
                    || key.GetPubKey() != vchPubKey)
                {
                    LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType);
                    break;  // unable to find corresponding public key
                }

                scriptPubKeyOut = scriptPubKeyKernel;
            }
            else
            {
                LogPrintf("CreateCoinStake: no support for kernel type=%d\n", whichType);
                break;  // only support pay to public key and pay to address
            }

            txnew.vin.push_back(CTxIn(CoinTx.GetHash(), CoinTxN));
            StakeInputs.push_back(pcoin.first);
            if (!txnew.GetCoinAge(txdb, CoinAge))
                return error("CreateCoinStake: failed to calculate coin age");
            int64_t nCredit = CoinTx.vout[CoinTxN].nValue;

            txnew.vout.push_back(CTxOut(0, CScript())); // First Must be empty
            txnew.vout.push_back(CTxOut(nCredit, scriptPubKeyOut));
            //txnew.vout.push_back(CTxOut(0, scriptPubKeyOut));

            LogPrintf("CreateCoinStake: added kernel type=%d credit=%f\n", whichType,CoinToDouble(nCredit));

            LOCK(MinerStatus.lock);
            MinerStatus.KernelsFound++;
            MinerStatus.KernelDiffMax = 0;
            MinerStatus.KernelDiffSum = StakeDiffSum;
            return true;
        }
    }

    LOCK(MinerStatus.lock);
    MinerStatus.WeightSum = StakeWeightSum;
    MinerStatus.ValueSum = StakeValueSum;
    MinerStatus.WeightMin=StakeWeightMin;
    MinerStatus.WeightMax=StakeWeightMax;
    MinerStatus.CoinAgeSum=StakeCoinAgeSum;
    MinerStatus.KernelDiffMax = std::max(MinerStatus.KernelDiffMax,StakeDiffMax);
    MinerStatus.KernelDiffSum = StakeDiffSum;
    MinerStatus.nLastCoinStakeSearchInterval= txnew.nTime;
    return false;
}
示例#17
0
Value getworkex(const Array& params, bool fHelp)
{
    if (fHelp || params.size() > 2)
        throw runtime_error(
            "getworkex [data, coinbase]\n"
            "If [data, coinbase] is not specified, returns extended work data.\n"
        );

    if (vNodes.empty())
        throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Gytecoin is not connected!");

    if (IsInitialBlockDownload())
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Gytecoin is downloading blocks...");

    typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
    static mapNewBlock_t mapNewBlock;    // FIXME: thread safety
    static vector<CBlockTemplate*> vNewBlockTemplate;
    static CReserveKey reservekey(pwalletMain);

    if (params.size() == 0)
    {
        // Update block
        static unsigned int nTransactionsUpdatedLast;
        static CBlockIndex* pindexPrev;
        static int64 nStart;
        static CBlockTemplate* pblocktemplate;
        if (pindexPrev != pindexBest ||
            (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
        {
            if (pindexPrev != pindexBest)
            {
                // Deallocate old blocks since they're obsolete now
                mapNewBlock.clear();
                BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate)
                    delete pblocktemplate;
                vNewBlockTemplate.clear();
            }

            // Clear pindexPrev so future getworks make a new block, despite any failures from here on
            pindexPrev = NULL;

            // Store the pindexBest used before CreateNewBlock, to avoid races
            nTransactionsUpdatedLast = nTransactionsUpdated;
            CBlockIndex* pindexPrevNew = pindexBest;
            nStart = GetTime();

            // Create new block
            pblocktemplate = CreateNewBlockWithKey(*pMiningKey);
            if (!pblocktemplate)
                throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
            vNewBlockTemplate.push_back(pblocktemplate);

            // Need to update only after we know CreateNewBlock succeeded
            pindexPrev = pindexPrevNew;
        }
        CBlock* pblock = &pblocktemplate->block; // pointer for convenience

        // Update nTime
        pblock->UpdateTime(pindexPrev);
        pblock->nNonce = 0;

        // Update nExtraNonce
        static unsigned int nExtraNonce = 0;
        IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);

        // Save
        mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);

        // Pre-build hash buffers
        char pmidstate[32];
        char pdata[128];
        char phash1[64];
        FormatHashBuffers(pblock, pmidstate, pdata, phash1);

        uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();

        CTransaction coinbaseTx = pblock->vtx[0];
        std::vector<uint256> merkle = pblock->GetMerkleBranch(0);

        Object result;
        result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
        result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));

        CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
        ssTx << coinbaseTx;
        result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end())));

        Array merkle_arr;

        BOOST_FOREACH(uint256 merkleh, merkle) {
            printf("%s\n", merkleh.ToString().c_str());
            merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh)));
        }

        result.push_back(Pair("merkle", merkle_arr));

        return result;
    }
示例#18
0
		GLvoid CRoomManager::addRoomTile(CBlock *block)
		{
			CLevelManager *lManager = CV_GAME_MANAGER->getLevelManager();

			vector2i pos = block->getLogicalPosition();

			vector2i posses[] = {vector2i(-1,0),vector2i(1,0),vector2i(0,-1),vector2i(0,1)};

			bool nbrs[4];

			nbrs[0] = lManager->isSameTypeAndOwner(pos[0]-1,pos[1],block);
			nbrs[1] = lManager->isSameTypeAndOwner(pos[0]+1,pos[1],block);
			nbrs[2] = lManager->isSameTypeAndOwner(pos[0],pos[1]-1,block);
			nbrs[3] = lManager->isSameTypeAndOwner(pos[0],pos[1]+1,block);

			GLint cnt = 0;

			cnt+=nbrs[0]?1:0;
			cnt+=nbrs[1]?1:0;
			cnt+=nbrs[2]?1:0;
			cnt+=nbrs[3]?1:0;

			if (cnt==0)
			{
				// create a new room
				CRoom *newRoom = new CRoom();
				newRoom->getRoomTilesVector()->push_back(block);
				newRoom->reownTiles();
				allRooms[newRoom->getIndex()] = newRoom;
				roomColors[newRoom->getIndex()] = vector3f((GLfloat)(rand()%101)/100.0f,(GLfloat)(rand()%101)/100.0f,(GLfloat)(rand()%101)/100.0f);

				CV_GAME_MANAGER->getConsole()->writeLine("A new room!");
			}
			else
			{
				GLint owner = -1;
				GLint roomIndex = -1;
				GLint type = -1;
				bool set = false;

				bool ok[] = {true, true, true};

				CBlock *testBlock = NULL;

				for (int i=0; i<4; i++)
				{
					if (nbrs[i])
					{
						testBlock = lManager->getBlock(pos+posses[i]);
						if (!set)
						{
							set = true;
							owner = testBlock->getOwner();
							roomIndex = testBlock->getRoomIndex();
							type = testBlock->getType();
						}
						else
						{
							ok[0] &= (owner == testBlock->getOwner());
							ok[1] &= (roomIndex == testBlock->getRoomIndex());
							ok[2] &= (type == testBlock->getType());
						}
					}
				}

				if (ok[0]&&ok[1]&&ok[2])
				{
					// all of same type, owner and room. just add this tile to this existing room
					allRooms[testBlock->getRoomIndex()]->getRoomTilesVector()->push_back(block);
					allRooms[testBlock->getRoomIndex()]->reownTiles();

					CV_GAME_MANAGER->getConsole()->writeLine("Tile added to the existing room.");
				}
				else
				{
					std::map<GLint, CBlock*> blockPerRoom;

					// we must make some merging
					for (int i=0; i<4; i++)
					{
						if (nbrs[i])
						{
							testBlock = lManager->getBlock(pos+posses[i]);
							blockPerRoom[testBlock->getRoomIndex()] = testBlock;
						}
					}

					// on this stage there are at least 2 elements in blockPerRoom.
					// take the first room and add it it all other room tiles.
					// then delete other rooms

					std::map<GLint, CBlock*>::iterator irIter = blockPerRoom.begin();

					CRoom *targetRoom = allRooms[irIter->first];

					irIter++;

					for (irIter; irIter!=blockPerRoom.end(); irIter++)
					{
						CRoom *room = allRooms[irIter->first];

						for (GLuint t=0; t<room->getRoomTilesVector()->size(); t++)
						{
							targetRoom->getRoomTilesVector()->push_back((*room->getRoomTilesVector())[t]);
						}

						// delete the unwanted room
						allRooms.erase(allRooms.find(irIter->first));
					}

					targetRoom->getRoomTilesVector()->push_back(block);

					targetRoom->reownTiles();

					CV_GAME_MANAGER->getConsole()->writeLine("Rooms merged.");
				}
			}
		}