mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 05:23:01 +01:00
dad8c67d38
64c0800
Use logging in individual tests (John Newbery)38ad281
Use logging in test_framework/comptool.py (John Newbery)ff19073
Use logging in test_framework/blockstore.py (John Newbery)2a9c7c7
Use logging in test_framework/util.py (John Newbery)b0dec4a
Remove manual debug settings in qa tests. (John Newbery)af1363c
Always enable debug log and microsecond logging for test nodes. (John Newbery)6d0e325
Use logging in mininode.py (John Newbery)553a976
Add logging to p2p-segwit.py (John Newbery)0e6d23d
Add logging to test_framework.py (John Newbery) Tree-SHA512: 42ee2acbf444ec32d796f930f9f6e272da03c75e93d974a126d4ea9b2dbaa77cc57ab5e63ce3fd33d609049d884eb8d9f65272c08922d10f8db69d4a60ad05a3
171 lines
5.4 KiB
Python
171 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
"""BlockStore and TxStore helper classes."""
|
|
|
|
from .mininode import *
|
|
from io import BytesIO
|
|
import dbm.dumb as dbmd
|
|
|
|
logger = logging.getLogger("TestFramework.blockstore")
|
|
|
|
class BlockStore(object):
|
|
"""BlockStore helper class.
|
|
|
|
BlockStore keeps a map of blocks and implements helper functions for
|
|
responding to getheaders and getdata, and for constructing a getheaders
|
|
message.
|
|
"""
|
|
|
|
def __init__(self, datadir):
|
|
self.blockDB = dbmd.open(datadir + "/blocks", 'c')
|
|
self.currentBlock = 0
|
|
self.headers_map = dict()
|
|
|
|
def close(self):
|
|
self.blockDB.close()
|
|
|
|
def erase(self, blockhash):
|
|
del self.blockDB[repr(blockhash)]
|
|
|
|
# lookup an entry and return the item as raw bytes
|
|
def get(self, blockhash):
|
|
value = None
|
|
try:
|
|
value = self.blockDB[repr(blockhash)]
|
|
except KeyError:
|
|
return None
|
|
return value
|
|
|
|
# lookup an entry and return it as a CBlock
|
|
def get_block(self, blockhash):
|
|
ret = None
|
|
serialized_block = self.get(blockhash)
|
|
if serialized_block is not None:
|
|
f = BytesIO(serialized_block)
|
|
ret = CBlock()
|
|
ret.deserialize(f)
|
|
ret.calc_sha256()
|
|
return ret
|
|
|
|
def get_header(self, blockhash):
|
|
try:
|
|
return self.headers_map[blockhash]
|
|
except KeyError:
|
|
return None
|
|
|
|
# Note: this pulls full blocks out of the database just to retrieve
|
|
# the headers -- perhaps we could keep a separate data structure
|
|
# to avoid this overhead.
|
|
def headers_for(self, locator, hash_stop, current_tip=None):
|
|
if current_tip is None:
|
|
current_tip = self.currentBlock
|
|
current_block_header = self.get_header(current_tip)
|
|
if current_block_header is None:
|
|
return None
|
|
|
|
response = msg_headers()
|
|
headersList = [ current_block_header ]
|
|
maxheaders = 2000
|
|
while (headersList[0].sha256 not in locator.vHave):
|
|
prevBlockHash = headersList[0].hashPrevBlock
|
|
prevBlockHeader = self.get_header(prevBlockHash)
|
|
if prevBlockHeader is not None:
|
|
headersList.insert(0, prevBlockHeader)
|
|
else:
|
|
break
|
|
headersList = headersList[:maxheaders] # truncate if we have too many
|
|
hashList = [x.sha256 for x in headersList]
|
|
index = len(headersList)
|
|
if (hash_stop in hashList):
|
|
index = hashList.index(hash_stop)+1
|
|
response.headers = headersList[:index]
|
|
return response
|
|
|
|
def add_block(self, block):
|
|
block.calc_sha256()
|
|
try:
|
|
self.blockDB[repr(block.sha256)] = bytes(block.serialize())
|
|
except TypeError as e:
|
|
logger.exception("Unexpected error")
|
|
self.currentBlock = block.sha256
|
|
self.headers_map[block.sha256] = CBlockHeader(block)
|
|
|
|
def add_header(self, header):
|
|
self.headers_map[header.sha256] = header
|
|
|
|
# lookup the hashes in "inv", and return p2p messages for delivering
|
|
# blocks found.
|
|
def get_blocks(self, inv):
|
|
responses = []
|
|
for i in inv:
|
|
if (i.type == 2): # MSG_BLOCK
|
|
data = self.get(i.hash)
|
|
if data is not None:
|
|
# Use msg_generic to avoid re-serialization
|
|
responses.append(msg_generic(b"block", data))
|
|
return responses
|
|
|
|
def get_locator(self, current_tip=None):
|
|
if current_tip is None:
|
|
current_tip = self.currentBlock
|
|
r = []
|
|
counter = 0
|
|
step = 1
|
|
lastBlock = self.get_block(current_tip)
|
|
while lastBlock is not None:
|
|
r.append(lastBlock.hashPrevBlock)
|
|
for i in range(step):
|
|
lastBlock = self.get_block(lastBlock.hashPrevBlock)
|
|
if lastBlock is None:
|
|
break
|
|
counter += 1
|
|
if counter > 10:
|
|
step *= 2
|
|
locator = CBlockLocator()
|
|
locator.vHave = r
|
|
return locator
|
|
|
|
class TxStore(object):
|
|
def __init__(self, datadir):
|
|
self.txDB = dbmd.open(datadir + "/transactions", 'c')
|
|
|
|
def close(self):
|
|
self.txDB.close()
|
|
|
|
# lookup an entry and return the item as raw bytes
|
|
def get(self, txhash):
|
|
value = None
|
|
try:
|
|
value = self.txDB[repr(txhash)]
|
|
except KeyError:
|
|
return None
|
|
return value
|
|
|
|
def get_transaction(self, txhash):
|
|
ret = None
|
|
serialized_tx = self.get(txhash)
|
|
if serialized_tx is not None:
|
|
f = BytesIO(serialized_tx)
|
|
ret = CTransaction()
|
|
ret.deserialize(f)
|
|
ret.calc_sha256()
|
|
return ret
|
|
|
|
def add_transaction(self, tx):
|
|
tx.calc_sha256()
|
|
try:
|
|
self.txDB[repr(tx.sha256)] = bytes(tx.serialize())
|
|
except TypeError as e:
|
|
logger.exception("Unexpected error")
|
|
|
|
def get_transactions(self, inv):
|
|
responses = []
|
|
for i in inv:
|
|
if (i.type == 1): # MSG_TX
|
|
tx = self.get(i.hash)
|
|
if tx is not None:
|
|
responses.append(msg_generic(b"tx", tx))
|
|
return responses
|