mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
6edbc9cebd
* Merge #9956: Reorganise qa directory63d66ba
Move src/test/bitcoin-util-test.py to test/util/bitcoin-util-test.py (John Newbery)5b0bff4
Rename --enable-extended-rpc-tests to --enable-extended-functional-tests (John Newbery)a9bd622
Rename test/pull-tester/rpc-tests.py to test/functional/test_runner.py (John Newbery)c28ee91
Rename rpc-tests directory to functional (John Newbery)00902c4
Rename qa directory to test (John Newbery) Tree-SHA512: ee7125c0c647d81590177beef2c8852c4ef76fdcf888096d9d4d360562a01d8d3b453345c3040487b2a043935bd1e7e80018f34462d6e02262bedbe23edcc576 resolve build errors Signed-off-by: Pasta <Pasta@dash.org> update test_runner.py in testintegrations.sh Signed-off-by: Pasta <Pasta@dash.org> * moved dash specific tests Signed-off-by: Pasta <Pasta@dash.org> * dashify README.md Signed-off-by: Pasta <Pasta@dash.org> * removed autoix*.py Signed-off-by: Pasta <Pasta@dash.org> * change back file perms * dedashify Signed-off-by: Pasta <Pasta@dash.org>
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
|