From a07fe6fffb25803c1d8382c7db831339dfdcc26b Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 23 Oct 2014 15:04:28 -0700 Subject: [PATCH] prevblock work. --- example/index.js | 4 +- src/bitcoindjs.cc | 230 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 190 insertions(+), 44 deletions(-) diff --git a/example/index.js b/example/index.js index 5cf98a61..d5a382bd 100755 --- a/example/index.js +++ b/example/index.js @@ -161,7 +161,7 @@ bitcoind.on('open', function(status) { //bitcoind.log('block.getHash("hex"): %s', obj.getHash('hex')); //bitcoind.log('block.hash === block.getHash("hex"): %s', obj.hash === obj.getHash('hex')); // XXX block hash is not equal - //assert.equal(obj.hash, obj.getHash('hex')); + assert.equal(obj.hash, obj.getHash('hex')); } // Hex @@ -175,7 +175,7 @@ bitcoind.on('open', function(status) { //bitcoind.log('block.toHex(): %s', obj.toHex()); //bitcoind.log('block.hex === block.toHex(): %s', obj.hex === obj.toHex()); // XXX block hex is not equal - //assert.equal(obj.hex, obj.toHex()); + assert.equal(obj.hex, obj.toHex()); } } diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index 7ee4e174..88c3d773 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -254,7 +254,7 @@ static void async_import_key_after(uv_work_t *req); static inline void -cblock_to_jsblock(const CBlock& cblock, const CBlockIndex* cblock_index, Local jsblock); +cblock_to_jsblock(const CBlock& cblock, CBlockIndex* cblock_index, Local jsblock, bool isNew); static inline void ctx_to_jstx(const CTransaction& ctx, uint256 block_hash, Local jstx); @@ -834,7 +834,7 @@ async_get_block_after(uv_work_t *req) { const CBlockIndex* cblock_index = data->result_blockindex; Local jsblock = NanNew(); - cblock_to_jsblock(cblock, cblock_index, jsblock); + cblock_to_jsblock(cblock, cblock_index, jsblock, false); const unsigned argc = 2; Local argv[argc] = { @@ -1483,7 +1483,7 @@ NAN_METHOD(BlockFromHex) { } Local jsblock = NanNew(); - cblock_to_jsblock(cblock, NULL, jsblock); + cblock_to_jsblock(cblock, NULL, jsblock, false); NanReturnValue(jsblock); } @@ -2771,7 +2771,7 @@ async_import_key_after(uv_work_t *req) { /** * Conversions - * cblock_to_jsblock(cblock, cblock_index, jsblock) + * cblock_to_jsblock(cblock, cblock_index, jsblock, isNew) * ctx_to_jstx(ctx, block_hash, jstx) * jsblock_to_cblock(jsblock, cblock) * jstx_to_ctx(jstx, ctx) @@ -2780,20 +2780,185 @@ async_import_key_after(uv_work_t *req) { * CTransactions), and vice versa. */ +/* + // header + static const int32_t CURRENT_VERSION=2; + int32_t nVersion; + uint256 hashPrevBlock; + uint256 hashMerkleRoot; + uint32_t nTime; + uint32_t nBits; + uint32_t nNonce; + + utils.writeU32(res, this.version, 0); // SHOULD BE int32_t + utils.copy(utils.toArray(this.prevBlock, 'hex'), res, 4); + utils.copy(utils.toArray(this.merkleRoot, 'hex'), res, 36); + utils.writeU32(res, this.ts, 68); + utils.writeU32(res, this.bits, 72); + utils.writeU32(res, this.nonce, 76); +*/ + +CBlockIndex * +find_new_block_index(CBlockHeader& header) { + // Check for duplicate + uint256 hash = header.GetHash(); + BlockMap::iterator it = mapBlockIndex.find(hash); + if (it != mapBlockIndex.end()) { + return it->second; + } + + // Construct new block index object + CBlockIndex* pindexNew = new CBlockIndex(header); + assert(pindexNew); + //{ + // LOCK(cs_nBlockSequenceId); + // pindexNew->nSequenceId = nBlockSequenceId++; + //} + //BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; + //pindexNew->phashBlock = &((*mi).first); + BlockMap::iterator miPrev = mapBlockIndex.find(header.hashPrevBlock); + if (miPrev != mapBlockIndex.end()) { + pindexNew->pprev = (*miPrev).second; + pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + //pindexNew->BuildSkip(); + } + //pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork(); + //pindexNew->RaiseValidity(BLOCK_VALID_TREE); + + return pindexNew; +} + +CBlockIndex * +find_new_block_index_(uint256 hash, uint256 hashPrevBlock) { + // Check for duplicate + BlockMap::iterator it = mapBlockIndex.find(hash); + if (it != mapBlockIndex.end()) { + return it->second; + } + + // Construct new block index object + CBlockIndex* pindexNew = new CBlockIndex(); + assert(pindexNew); + BlockMap::iterator miPrev = mapBlockIndex.find(hashPrevBlock); + if (miPrev != mapBlockIndex.end()) { + pindexNew->pprev = (*miPrev).second; + pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + } + + return pindexNew; +} + static inline void -cblock_to_jsblock(const CBlock& cblock, const CBlockIndex* cblock_index, Local jsblock) { +cblock_to_jsblock(const CBlock& cblock, CBlockIndex* cblock_index, Local jsblock, bool isNew) { + bool index_alloc = false; + if (!cblock_index && isNew) { +#if 0 + CBlockHeader block; + block.nVersion = nVersion; + block.hashPrevBlock = hashPrevBlock; + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; +#endif +#if 0 + CBlockHeader& header =(const CBlockHeader&) *(cblock.GetBlockHeader()); + cblock_index = (CBlockIndex *)new CBlockIndex(header); + index_alloc = true; +#endif +#if 0 + CBlockHeader _header; + CBlockHeader& header = _header; + header.nVersion = cblock.nVersion; + header.hashPrevBlock = cblock.hashPrevBlock; + header.hashMerkleRoot = cblock.hashMerkleRoot; + header.nTime = cblock.nTime; + header.nBits = cblock.nBits; + header.nNonce = cblock.nNonce; + cblock_index = (CBlockIndex *)new CBlockIndex(header); + index_alloc = true; +#endif +#if 0 + cblock_index = chainActive[chainActive.Tip()->nHeight]; + index_alloc = true; +#endif +// WORKS: +#if 0 + CBlockHeader _header; + CBlockHeader& header = _header; + header.nVersion = cblock.nVersion; + header.hashPrevBlock = cblock.hashPrevBlock; + header.hashMerkleRoot = cblock.hashMerkleRoot; + header.nTime = cblock.nTime; + header.nBits = cblock.nBits; + header.nNonce = cblock.nNonce; + cblock_index = find_new_block_index(header); + cblock_index = AddToBlockIndex(header); // will not add if there's a duplicate + index_alloc = true; +#endif +// WORKS: +#if 0 + cblock_index = find_new_block_index_(cblock.GetHash(), cblock.hashPrevBlock); + index_alloc = true; +#endif +#if 1 + CBlockHeader _header; + CBlockHeader& header = _header; + header.nVersion = cblock.nVersion; + header.hashPrevBlock = cblock.hashPrevBlock; + header.hashMerkleRoot = cblock.hashMerkleRoot; + header.nTime = cblock.nTime; + header.nBits = cblock.nBits; + header.nNonce = cblock.nNonce; + cblock_index = AddToBlockIndex(header); // will not add if there's a duplicate + index_alloc = true; +#endif + } + jsblock->Set(NanNew("hash"), NanNew(cblock.GetHash().GetHex().c_str())); CMerkleTx txGen(cblock.vtx[0]); txGen.SetMerkleBranch(cblock); jsblock->Set(NanNew("confirmations"), NanNew((int)txGen.GetDepthInMainChain())->ToInt32()); jsblock->Set(NanNew("size"), NanNew((int)::GetSerializeSize(cblock, SER_NETWORK, PROTOCOL_VERSION))->ToInt32()); + if (cblock_index) { jsblock->Set(NanNew("height"), NanNew(cblock_index->nHeight)); } + + // + // Headers + // jsblock->Set(NanNew("version"), NanNew(cblock.nVersion)); + + // XXX Why hash check is failing: + if (cblock_index && cblock_index->pprev) { + jsblock->Set(NanNew("previousblockhash"), NanNew(cblock_index->pprev->GetBlockHash().GetHex())); + } else { + // genesis + jsblock->Set(NanNew("previousblockhash"), + NanNew("0000000000000000000000000000000000000000000000000000000000000000")); + } + jsblock->Set(NanNew("merkleroot"), NanNew(cblock.hashMerkleRoot.GetHex())); + jsblock->Set(NanNew("time"), NanNew((unsigned int)cblock.GetBlockTime())->ToUint32()); + jsblock->Set(NanNew("bits"), NanNew((unsigned int)cblock.nBits)->ToUint32()); + jsblock->Set(NanNew("nonce"), NanNew((unsigned int)cblock.nNonce)->ToUint32()); + + if (cblock_index) { + jsblock->Set(NanNew("difficulty"), NanNew(GetDifficulty(cblock_index))); + jsblock->Set(NanNew("chainwork"), NanNew(cblock_index->nChainWork.GetHex())); + } + + if (cblock_index) { + CBlockIndex *pnext = chainActive.Next(cblock_index); + if (pnext) { + jsblock->Set(NanNew("nextblockhash"), NanNew(pnext->GetBlockHash().GetHex())); + } + } + // Build merkle tree if (cblock.vMerkleTree.empty()) { cblock.BuildMerkleTree(); @@ -2817,33 +2982,14 @@ cblock_to_jsblock(const CBlock& cblock, const CBlockIndex* cblock_index, LocalSet(NanNew("tx"), txs); - jsblock->Set(NanNew("time"), NanNew((unsigned int)cblock.GetBlockTime())->ToUint32()); - jsblock->Set(NanNew("nonce"), NanNew((unsigned int)cblock.nNonce)->ToUint32()); - jsblock->Set(NanNew("bits"), NanNew((unsigned int)cblock.nBits)->ToUint32()); - if (cblock_index) { - jsblock->Set(NanNew("difficulty"), NanNew(GetDifficulty(cblock_index))); - jsblock->Set(NanNew("chainwork"), NanNew(cblock_index->nChainWork.GetHex())); - } - - if (cblock_index && cblock_index->pprev) { - jsblock->Set(NanNew("previousblockhash"), NanNew(cblock_index->pprev->GetBlockHash().GetHex())); - } else { - // genesis - jsblock->Set(NanNew("previousblockhash"), - NanNew("0000000000000000000000000000000000000000000000000000000000000000")); - } - - if (cblock_index) { - CBlockIndex *pnext = chainActive.Next(cblock_index); - if (pnext) { - jsblock->Set(NanNew("nextblockhash"), NanNew(pnext->GetBlockHash().GetHex())); - } - } - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); ssBlock << cblock; std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); jsblock->Set(NanNew("hex"), NanNew(strHex)); + + if (index_alloc) { + //delete cblock_index; + } } static inline void @@ -2958,27 +3104,27 @@ ctx_to_jstx(const CTransaction& ctx, uint256 block_hash, Local jstx) { static inline void jsblock_to_cblock(const Local jsblock, CBlock& cblock) { - cblock.nVersion = (int)jsblock->Get(NanNew("version"))->Int32Value(); - - String::AsciiValue mhash__(jsblock->Get(NanNew("merkleroot"))->ToString()); - std::string mhash_ = *mhash__; - uint256 mhash(mhash_); - - cblock.hashMerkleRoot = mhash; - cblock.nTime = (unsigned int)jsblock->Get(NanNew("time"))->Uint32Value(); - cblock.nNonce = (unsigned int)jsblock->Get(NanNew("nonce"))->Uint32Value(); - cblock.nBits = (unsigned int)jsblock->Get(NanNew("bits"))->Uint32Value(); + cblock.nVersion = (int32_t)jsblock->Get(NanNew("version"))->Int32Value(); if (jsblock->Get(NanNew("previousblockhash"))->IsString()) { String::AsciiValue hash__(jsblock->Get(NanNew("previousblockhash"))->ToString()); std::string hash_ = *hash__; uint256 hash(hash_); - cblock.hashPrevBlock = hash; + cblock.hashPrevBlock = (uint256)hash; } else { // genesis block - cblock.hashPrevBlock = uint256(0); + cblock.hashPrevBlock = (uint256)uint256(0); } + String::AsciiValue mhash__(jsblock->Get(NanNew("merkleroot"))->ToString()); + std::string mhash_ = *mhash__; + uint256 mhash(mhash_); + cblock.hashMerkleRoot = (uint256)mhash; + + cblock.nTime = (uint32_t)jsblock->Get(NanNew("time"))->Uint32Value(); + cblock.nBits = (uint32_t)jsblock->Get(NanNew("bits"))->Uint32Value(); + cblock.nNonce = (uint32_t)jsblock->Get(NanNew("nonce"))->Uint32Value(); + Local txs = Local::Cast(jsblock->Get(NanNew("tx"))); for (unsigned int ti = 0; ti < txs->Length(); ti++) { Local jstx = Local::Cast(txs->Get(ti)); @@ -3342,8 +3488,8 @@ NAN_METHOD(HookPackets) { CBlock block; vRecv >> block; Local jsblock = NanNew(); - cblock_to_jsblock(block, NULL, jsblock); - // cblock_to_jsblock(block, NULL, o); + cblock_to_jsblock(block, NULL, jsblock, true); + // cblock_to_jsblock(block, NULL, o, true); o->Set(NanNew("block"), jsblock); } else if (strCommand == "getaddr") { ; // not much other information in getaddr as long as we know we got a getaddr