Update to Core 0.12.2
This commit is contained in:
@@ -61,7 +61,7 @@ class JSONRPCException(Exception):
|
||||
|
||||
def EncodeDecimal(o):
|
||||
if isinstance(o, decimal.Decimal):
|
||||
return round(o, 8)
|
||||
return str(o)
|
||||
raise TypeError(repr(o) + " is not JSON serializable")
|
||||
|
||||
class AuthServiceProxy(object):
|
||||
@@ -94,11 +94,10 @@ class AuthServiceProxy(object):
|
||||
self.__conn = connection
|
||||
elif self.__url.scheme == 'https':
|
||||
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
|
||||
None, None, False,
|
||||
timeout)
|
||||
timeout=timeout)
|
||||
else:
|
||||
self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
|
||||
False, timeout)
|
||||
timeout=timeout)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith('__') and name.endswith('__'):
|
||||
@@ -157,6 +156,11 @@ class AuthServiceProxy(object):
|
||||
raise JSONRPCException({
|
||||
'code': -342, 'message': 'missing HTTP response from server'})
|
||||
|
||||
content_type = http_response.getheader('Content-Type')
|
||||
if content_type != 'application/json':
|
||||
raise JSONRPCException({
|
||||
'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)})
|
||||
|
||||
responsedata = http_response.read().decode('utf8')
|
||||
response = json.loads(responsedata, parse_float=decimal.Decimal)
|
||||
if "error" in response and response["error"] is None:
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# bignum.py
|
||||
#
|
||||
# This file is copied from python-bitcoinlib.
|
||||
#
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
"""Bignum routines"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
# BlockStore: a helper class that keeps a map of blocks and implements
|
||||
# helper functions for responding to getheaders and getdata,
|
||||
# and for constructing a getheaders message
|
||||
#
|
||||
|
||||
from .mininode import *
|
||||
import dbm
|
||||
from io import BytesIO
|
||||
import dbm.dumb as dbmd
|
||||
|
||||
class BlockStore(object):
|
||||
def __init__(self, datadir):
|
||||
self.blockDB = dbm.open(datadir + "/blocks", 'c')
|
||||
self.currentBlock = 0L
|
||||
self.blockDB = dbmd.open(datadir + "/blocks", 'c')
|
||||
self.currentBlock = 0
|
||||
self.headers_map = dict()
|
||||
|
||||
def close(self):
|
||||
@@ -67,7 +68,7 @@ class BlockStore(object):
|
||||
try:
|
||||
self.blockDB[repr(block.sha256)] = bytes(block.serialize())
|
||||
except TypeError as e:
|
||||
print "Unexpected error: ", sys.exc_info()[0], e.args
|
||||
print("Unexpected error: ", sys.exc_info()[0], e.args)
|
||||
self.currentBlock = block.sha256
|
||||
self.headers_map[block.sha256] = CBlockHeader(block)
|
||||
|
||||
@@ -105,7 +106,7 @@ class BlockStore(object):
|
||||
|
||||
class TxStore(object):
|
||||
def __init__(self, datadir):
|
||||
self.txDB = dbm.open(datadir + "/transactions", 'c')
|
||||
self.txDB = dbmd.open(datadir + "/transactions", 'c')
|
||||
|
||||
def close(self):
|
||||
self.txDB.close()
|
||||
@@ -127,7 +128,7 @@ class TxStore(object):
|
||||
try:
|
||||
self.txDB[repr(tx.sha256)] = bytes(tx.serialize())
|
||||
except TypeError as e:
|
||||
print "Unexpected error: ", sys.exc_info()[0], e.args
|
||||
print("Unexpected error: ", sys.exc_info()[0], e.args)
|
||||
|
||||
def get_transactions(self, inv):
|
||||
responses = []
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
# blocktools.py - utilities for manipulating blocks and transactions
|
||||
#
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# 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.
|
||||
#
|
||||
|
||||
from .mininode import *
|
||||
from .script import CScript, OP_TRUE, OP_CHECKSIG
|
||||
@@ -29,7 +29,7 @@ def serialize_script_num(value):
|
||||
neg = value < 0
|
||||
absvalue = -value if neg else value
|
||||
while (absvalue):
|
||||
r.append(chr(absvalue & 0xff))
|
||||
r.append(int(absvalue & 0xff))
|
||||
absvalue >>= 8
|
||||
if r[-1] & 0x80:
|
||||
r.append(0x80 if neg else 0)
|
||||
@@ -45,7 +45,7 @@ def create_coinbase(height, pubkey = None):
|
||||
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
|
||||
ser_string(serialize_script_num(height)), 0xffffffff))
|
||||
coinbaseoutput = CTxOut()
|
||||
coinbaseoutput.nValue = 50*100000000
|
||||
coinbaseoutput.nValue = 50 * COIN
|
||||
halvings = int(height/150) # regtest
|
||||
coinbaseoutput.nValue >>= halvings
|
||||
if (pubkey != None):
|
||||
@@ -62,6 +62,6 @@ def create_transaction(prevtx, n, sig, value):
|
||||
tx = CTransaction()
|
||||
assert(n < len(prevtx.vout))
|
||||
tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff))
|
||||
tx.vout.append(CTxOut(value, ""))
|
||||
tx.vout.append(CTxOut(value, b""))
|
||||
tx.calc_sha256()
|
||||
return tx
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
#
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
#!/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.
|
||||
#
|
||||
|
||||
from .mininode import *
|
||||
from .blockstore import BlockStore, TxStore
|
||||
@@ -31,7 +30,7 @@ class RejectResult(object):
|
||||
'''
|
||||
Outcome that expects rejection of a transaction or block.
|
||||
'''
|
||||
def __init__(self, code, reason=''):
|
||||
def __init__(self, code, reason=b''):
|
||||
self.code = code
|
||||
self.reason = reason
|
||||
def match(self, other):
|
||||
@@ -97,9 +96,9 @@ class TestNode(NodeConnCB):
|
||||
raise AssertionError("Got pong for unknown ping [%s]" % repr(message))
|
||||
|
||||
def on_reject(self, conn, message):
|
||||
if message.message == 'tx':
|
||||
if message.message == b'tx':
|
||||
self.tx_reject_map[message.data] = RejectResult(message.code, message.reason)
|
||||
if message.message == 'block':
|
||||
if message.message == b'block':
|
||||
self.block_reject_map[message.data] = RejectResult(message.code, message.reason)
|
||||
|
||||
def send_inv(self, obj):
|
||||
@@ -259,10 +258,10 @@ class TestManager(object):
|
||||
if c.cb.bestblockhash == blockhash:
|
||||
return False
|
||||
if blockhash not in c.cb.block_reject_map:
|
||||
print 'Block not in reject map: %064x' % (blockhash)
|
||||
print('Block not in reject map: %064x' % (blockhash))
|
||||
return False
|
||||
if not outcome.match(c.cb.block_reject_map[blockhash]):
|
||||
print 'Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash)
|
||||
print('Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash))
|
||||
return False
|
||||
elif ((c.cb.bestblockhash == blockhash) != outcome):
|
||||
# print c.cb.bestblockhash, blockhash, outcome
|
||||
@@ -287,10 +286,10 @@ class TestManager(object):
|
||||
if txhash in c.cb.lastInv:
|
||||
return False
|
||||
if txhash not in c.cb.tx_reject_map:
|
||||
print 'Tx not in reject map: %064x' % (txhash)
|
||||
print('Tx not in reject map: %064x' % (txhash))
|
||||
return False
|
||||
if not outcome.match(c.cb.tx_reject_map[txhash]):
|
||||
print 'Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash)
|
||||
print('Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash))
|
||||
return False
|
||||
elif ((txhash in c.cb.lastInv) != outcome):
|
||||
# print c.rpc.getrawmempool(), c.cb.lastInv
|
||||
@@ -393,7 +392,7 @@ class TestManager(object):
|
||||
if (not self.check_mempool(tx.sha256, tx_outcome)):
|
||||
raise AssertionError("Mempool test failed at test %d" % test_number)
|
||||
|
||||
print "Test %d: PASS" % test_number, [ c.rpc.getblockcount() for c in self.connections ]
|
||||
print("Test %d: PASS" % test_number, [ c.rpc.getblockcount() for c in self.connections ])
|
||||
test_number += 1
|
||||
|
||||
[ c.disconnect_node() for c in self.connections ]
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#!/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.
|
||||
|
||||
"""
|
||||
This module contains utilities for doing coverage analysis on the RPC
|
||||
interface.
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# mininode.py - Bitcoin P2P network half-a-node
|
||||
#
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2010 ArtForz -- public domain half-a-node
|
||||
# Copyright (c) 2012 Jeff Garzik
|
||||
# Copyright (c) 2010-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.
|
||||
|
||||
#
|
||||
# mininode.py - Bitcoin P2P network half-a-node
|
||||
#
|
||||
# This python code was modified from ArtForz' public domain half-a-node, as
|
||||
# found in the mini-node branch of http://github.com/jgarzik/pynode.
|
||||
@@ -20,10 +25,10 @@
|
||||
import struct
|
||||
import socket
|
||||
import asyncore
|
||||
import binascii
|
||||
import time
|
||||
import sys
|
||||
import random
|
||||
from binascii import hexlify, unhexlify
|
||||
from io import BytesIO
|
||||
from codecs import encode
|
||||
import hashlib
|
||||
@@ -34,11 +39,13 @@ import copy
|
||||
|
||||
BIP0031_VERSION = 60000
|
||||
MY_VERSION = 60001 # past bip-31 for ping/pong
|
||||
MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
|
||||
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
|
||||
|
||||
MAX_INV_SZ = 50000
|
||||
MAX_BLOCK_SIZE = 1000000
|
||||
|
||||
COIN = 100000000 # 1 btc in satoshis
|
||||
|
||||
# Keep our own socket map for asyncore, so that we can track disconnects
|
||||
# ourselves (to workaround an issue with closing an asyncore socket when
|
||||
# using select)
|
||||
@@ -71,44 +78,42 @@ def deser_string(f):
|
||||
nit = struct.unpack("<Q", f.read(8))[0]
|
||||
return f.read(nit)
|
||||
|
||||
|
||||
def ser_string(s):
|
||||
if len(s) < 253:
|
||||
return struct.pack("B", len(s)) + s
|
||||
elif len(s) < 0x10000:
|
||||
return struct.pack("B", 253) + struct.pack("<H", len(s)) + s
|
||||
elif len(s) < 0x100000000L:
|
||||
return struct.pack("B", 254) + struct.pack("<I", len(s)) + s
|
||||
return struct.pack("B", 255) + struct.pack("<Q", len(s)) + s
|
||||
|
||||
return struct.pack("<BH", 253, len(s)) + s
|
||||
elif len(s) < 0x100000000:
|
||||
return struct.pack("<BI", 254, len(s)) + s
|
||||
return struct.pack("<BQ", 255, len(s)) + s
|
||||
|
||||
def deser_uint256(f):
|
||||
r = 0L
|
||||
for i in xrange(8):
|
||||
r = 0
|
||||
for i in range(8):
|
||||
t = struct.unpack("<I", f.read(4))[0]
|
||||
r += t << (i * 32)
|
||||
return r
|
||||
|
||||
|
||||
def ser_uint256(u):
|
||||
rs = ""
|
||||
for i in xrange(8):
|
||||
rs += struct.pack("<I", u & 0xFFFFFFFFL)
|
||||
rs = b""
|
||||
for i in range(8):
|
||||
rs += struct.pack("<I", u & 0xFFFFFFFF)
|
||||
u >>= 32
|
||||
return rs
|
||||
|
||||
|
||||
def uint256_from_str(s):
|
||||
r = 0L
|
||||
r = 0
|
||||
t = struct.unpack("<IIIIIIII", s[:32])
|
||||
for i in xrange(8):
|
||||
for i in range(8):
|
||||
r += t[i] << (i * 32)
|
||||
return r
|
||||
|
||||
|
||||
def uint256_from_compact(c):
|
||||
nbytes = (c >> 24) & 0xFF
|
||||
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
|
||||
v = (c & 0xFFFFFF) << (8 * (nbytes - 3))
|
||||
return v
|
||||
|
||||
|
||||
@@ -121,7 +126,7 @@ def deser_vector(f, c):
|
||||
elif nit == 255:
|
||||
nit = struct.unpack("<Q", f.read(8))[0]
|
||||
r = []
|
||||
for i in xrange(nit):
|
||||
for i in range(nit):
|
||||
t = c()
|
||||
t.deserialize(f)
|
||||
r.append(t)
|
||||
@@ -129,15 +134,15 @@ def deser_vector(f, c):
|
||||
|
||||
|
||||
def ser_vector(l):
|
||||
r = ""
|
||||
r = b""
|
||||
if len(l) < 253:
|
||||
r = struct.pack("B", len(l))
|
||||
elif len(l) < 0x10000:
|
||||
r = struct.pack("B", 253) + struct.pack("<H", len(l))
|
||||
elif len(l) < 0x100000000L:
|
||||
r = struct.pack("B", 254) + struct.pack("<I", len(l))
|
||||
r = struct.pack("<BH", 253, len(l))
|
||||
elif len(l) < 0x100000000:
|
||||
r = struct.pack("<BI", 254, len(l))
|
||||
else:
|
||||
r = struct.pack("B", 255) + struct.pack("<Q", len(l))
|
||||
r = struct.pack("<BQ", 255, len(l))
|
||||
for i in l:
|
||||
r += i.serialize()
|
||||
return r
|
||||
@@ -152,22 +157,22 @@ def deser_uint256_vector(f):
|
||||
elif nit == 255:
|
||||
nit = struct.unpack("<Q", f.read(8))[0]
|
||||
r = []
|
||||
for i in xrange(nit):
|
||||
for i in range(nit):
|
||||
t = deser_uint256(f)
|
||||
r.append(t)
|
||||
return r
|
||||
|
||||
|
||||
def ser_uint256_vector(l):
|
||||
r = ""
|
||||
r = b""
|
||||
if len(l) < 253:
|
||||
r = struct.pack("B", len(l))
|
||||
elif len(l) < 0x10000:
|
||||
r = struct.pack("B", 253) + struct.pack("<H", len(l))
|
||||
elif len(l) < 0x100000000L:
|
||||
r = struct.pack("B", 254) + struct.pack("<I", len(l))
|
||||
r = struct.pack("<BH", 253, len(l))
|
||||
elif len(l) < 0x100000000:
|
||||
r = struct.pack("<BI", 254, len(l))
|
||||
else:
|
||||
r = struct.pack("B", 255) + struct.pack("<Q", len(l))
|
||||
r = struct.pack("<BQ", 255, len(l))
|
||||
for i in l:
|
||||
r += ser_uint256(i)
|
||||
return r
|
||||
@@ -182,22 +187,22 @@ def deser_string_vector(f):
|
||||
elif nit == 255:
|
||||
nit = struct.unpack("<Q", f.read(8))[0]
|
||||
r = []
|
||||
for i in xrange(nit):
|
||||
for i in range(nit):
|
||||
t = deser_string(f)
|
||||
r.append(t)
|
||||
return r
|
||||
|
||||
|
||||
def ser_string_vector(l):
|
||||
r = ""
|
||||
r = b""
|
||||
if len(l) < 253:
|
||||
r = struct.pack("B", len(l))
|
||||
elif len(l) < 0x10000:
|
||||
r = struct.pack("B", 253) + struct.pack("<H", len(l))
|
||||
elif len(l) < 0x100000000L:
|
||||
r = struct.pack("B", 254) + struct.pack("<I", len(l))
|
||||
r = struct.pack("<BH", 253, len(l))
|
||||
elif len(l) < 0x100000000:
|
||||
r = struct.pack("<BI", 254, len(l))
|
||||
else:
|
||||
r = struct.pack("B", 255) + struct.pack("<Q", len(l))
|
||||
r = struct.pack("<BQ", 255, len(l))
|
||||
for sv in l:
|
||||
r += ser_string(sv)
|
||||
return r
|
||||
@@ -212,41 +217,41 @@ def deser_int_vector(f):
|
||||
elif nit == 255:
|
||||
nit = struct.unpack("<Q", f.read(8))[0]
|
||||
r = []
|
||||
for i in xrange(nit):
|
||||
for i in range(nit):
|
||||
t = struct.unpack("<i", f.read(4))[0]
|
||||
r.append(t)
|
||||
return r
|
||||
|
||||
|
||||
def ser_int_vector(l):
|
||||
r = ""
|
||||
r = b""
|
||||
if len(l) < 253:
|
||||
r = struct.pack("B", len(l))
|
||||
elif len(l) < 0x10000:
|
||||
r = struct.pack("B", 253) + struct.pack("<H", len(l))
|
||||
elif len(l) < 0x100000000L:
|
||||
r = struct.pack("B", 254) + struct.pack("<I", len(l))
|
||||
r = struct.pack("<BH", 253, len(l))
|
||||
elif len(l) < 0x100000000:
|
||||
r = struct.pack("<BI", 254, len(l))
|
||||
else:
|
||||
r = struct.pack("B", 255) + struct.pack("<Q", len(l))
|
||||
r = struct.pack("<BQ", 255, len(l))
|
||||
for i in l:
|
||||
r += struct.pack("<i", i)
|
||||
return r
|
||||
|
||||
# Deserialize from a hex string representation (eg from RPC)
|
||||
def FromHex(obj, hex_string):
|
||||
obj.deserialize(BytesIO(binascii.unhexlify(hex_string)))
|
||||
obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii'))))
|
||||
return obj
|
||||
|
||||
# Convert a binary-serializable object to hex (eg for submission via RPC)
|
||||
def ToHex(obj):
|
||||
return binascii.hexlify(obj.serialize()).decode('utf-8')
|
||||
return hexlify(obj.serialize()).decode('ascii')
|
||||
|
||||
# Objects that map to bitcoind objects, which can be serialized/deserialized
|
||||
|
||||
class CAddress(object):
|
||||
def __init__(self):
|
||||
self.nServices = 1
|
||||
self.pchReserved = "\x00" * 10 + "\xff" * 2
|
||||
self.pchReserved = b"\x00" * 10 + b"\xff" * 2
|
||||
self.ip = "0.0.0.0"
|
||||
self.port = 0
|
||||
|
||||
@@ -257,7 +262,7 @@ class CAddress(object):
|
||||
self.port = struct.unpack(">H", f.read(2))[0]
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<Q", self.nServices)
|
||||
r += self.pchReserved
|
||||
r += socket.inet_aton(self.ip)
|
||||
@@ -275,7 +280,7 @@ class CInv(object):
|
||||
1: "TX",
|
||||
2: "Block"}
|
||||
|
||||
def __init__(self, t=0, h=0L):
|
||||
def __init__(self, t=0, h=0):
|
||||
self.type = t
|
||||
self.hash = h
|
||||
|
||||
@@ -284,7 +289,7 @@ class CInv(object):
|
||||
self.hash = deser_uint256(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.type)
|
||||
r += ser_uint256(self.hash)
|
||||
return r
|
||||
@@ -304,7 +309,7 @@ class CBlockLocator(object):
|
||||
self.vHave = deser_uint256_vector(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += ser_uint256_vector(self.vHave)
|
||||
return r
|
||||
@@ -324,7 +329,7 @@ class COutPoint(object):
|
||||
self.n = struct.unpack("<I", f.read(4))[0]
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += ser_uint256(self.hash)
|
||||
r += struct.pack("<I", self.n)
|
||||
return r
|
||||
@@ -334,7 +339,7 @@ class COutPoint(object):
|
||||
|
||||
|
||||
class CTxIn(object):
|
||||
def __init__(self, outpoint=None, scriptSig="", nSequence=0):
|
||||
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
|
||||
if outpoint is None:
|
||||
self.prevout = COutPoint()
|
||||
else:
|
||||
@@ -349,7 +354,7 @@ class CTxIn(object):
|
||||
self.nSequence = struct.unpack("<I", f.read(4))[0]
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += self.prevout.serialize()
|
||||
r += ser_string(self.scriptSig)
|
||||
r += struct.pack("<I", self.nSequence)
|
||||
@@ -357,12 +362,12 @@ class CTxIn(object):
|
||||
|
||||
def __repr__(self):
|
||||
return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \
|
||||
% (repr(self.prevout), binascii.hexlify(self.scriptSig),
|
||||
% (repr(self.prevout), hexlify(self.scriptSig),
|
||||
self.nSequence)
|
||||
|
||||
|
||||
class CTxOut(object):
|
||||
def __init__(self, nValue=0, scriptPubKey=""):
|
||||
def __init__(self, nValue=0, scriptPubKey=b""):
|
||||
self.nValue = nValue
|
||||
self.scriptPubKey = scriptPubKey
|
||||
|
||||
@@ -371,15 +376,15 @@ class CTxOut(object):
|
||||
self.scriptPubKey = deser_string(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<q", self.nValue)
|
||||
r += ser_string(self.scriptPubKey)
|
||||
return r
|
||||
|
||||
def __repr__(self):
|
||||
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
|
||||
% (self.nValue // 100000000, self.nValue % 100000000,
|
||||
binascii.hexlify(self.scriptPubKey))
|
||||
% (self.nValue // COIN, self.nValue % COIN,
|
||||
hexlify(self.scriptPubKey))
|
||||
|
||||
|
||||
class CTransaction(object):
|
||||
@@ -408,7 +413,7 @@ class CTransaction(object):
|
||||
self.hash = None
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += ser_vector(self.vin)
|
||||
r += ser_vector(self.vout)
|
||||
@@ -422,12 +427,12 @@ class CTransaction(object):
|
||||
def calc_sha256(self):
|
||||
if self.sha256 is None:
|
||||
self.sha256 = uint256_from_str(hash256(self.serialize()))
|
||||
self.hash = encode(hash256(self.serialize())[::-1], 'hex')
|
||||
self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii')
|
||||
|
||||
def is_valid(self):
|
||||
self.calc_sha256()
|
||||
for tout in self.vout:
|
||||
if tout.nValue < 0 or tout.nValue > 21000000L * 100000000L:
|
||||
if tout.nValue < 0 or tout.nValue > 21000000 * COIN:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -472,7 +477,7 @@ class CBlockHeader(object):
|
||||
self.hash = None
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += ser_uint256(self.hashPrevBlock)
|
||||
r += ser_uint256(self.hashMerkleRoot)
|
||||
@@ -483,7 +488,7 @@ class CBlockHeader(object):
|
||||
|
||||
def calc_sha256(self):
|
||||
if self.sha256 is None:
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += ser_uint256(self.hashPrevBlock)
|
||||
r += ser_uint256(self.hashMerkleRoot)
|
||||
@@ -491,7 +496,7 @@ class CBlockHeader(object):
|
||||
r += struct.pack("<I", self.nBits)
|
||||
r += struct.pack("<I", self.nNonce)
|
||||
self.sha256 = uint256_from_str(hash256(r))
|
||||
self.hash = encode(hash256(r)[::-1], 'hex')
|
||||
self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii')
|
||||
|
||||
def rehash(self):
|
||||
self.sha256 = None
|
||||
@@ -514,7 +519,7 @@ class CBlock(CBlockHeader):
|
||||
self.vtx = deser_vector(f, CTransaction)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += super(CBlock, self).serialize()
|
||||
r += ser_vector(self.vtx)
|
||||
return r
|
||||
@@ -526,7 +531,7 @@ class CBlock(CBlockHeader):
|
||||
hashes.append(ser_uint256(tx.sha256))
|
||||
while len(hashes) > 1:
|
||||
newhashes = []
|
||||
for i in xrange(0, len(hashes), 2):
|
||||
for i in range(0, len(hashes), 2):
|
||||
i2 = min(i+1, len(hashes)-1)
|
||||
newhashes.append(hash256(hashes[i] + hashes[i2]))
|
||||
hashes = newhashes
|
||||
@@ -569,9 +574,9 @@ class CUnsignedAlert(object):
|
||||
self.nMaxVer = 0
|
||||
self.setSubVer = []
|
||||
self.nPriority = 0
|
||||
self.strComment = ""
|
||||
self.strStatusBar = ""
|
||||
self.strReserved = ""
|
||||
self.strComment = b""
|
||||
self.strStatusBar = b""
|
||||
self.strReserved = b""
|
||||
|
||||
def deserialize(self, f):
|
||||
self.nVersion = struct.unpack("<i", f.read(4))[0]
|
||||
@@ -589,7 +594,7 @@ class CUnsignedAlert(object):
|
||||
self.strReserved = deser_string(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += struct.pack("<q", self.nRelayUntil)
|
||||
r += struct.pack("<q", self.nExpiration)
|
||||
@@ -614,15 +619,15 @@ class CUnsignedAlert(object):
|
||||
|
||||
class CAlert(object):
|
||||
def __init__(self):
|
||||
self.vchMsg = ""
|
||||
self.vchSig = ""
|
||||
self.vchMsg = b""
|
||||
self.vchSig = b""
|
||||
|
||||
def deserialize(self, f):
|
||||
self.vchMsg = deser_string(f)
|
||||
self.vchSig = deser_string(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += ser_string(self.vchMsg)
|
||||
r += ser_string(self.vchSig)
|
||||
return r
|
||||
@@ -634,12 +639,12 @@ class CAlert(object):
|
||||
|
||||
# Objects that correspond to messages on the wire
|
||||
class msg_version(object):
|
||||
command = "version"
|
||||
command = b"version"
|
||||
|
||||
def __init__(self):
|
||||
self.nVersion = MY_VERSION
|
||||
self.nServices = 1
|
||||
self.nTime = time.time()
|
||||
self.nTime = int(time.time())
|
||||
self.addrTo = CAddress()
|
||||
self.addrFrom = CAddress()
|
||||
self.nNonce = random.getrandbits(64)
|
||||
@@ -670,7 +675,7 @@ class msg_version(object):
|
||||
self.nStartingHeight = None
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += struct.pack("<Q", self.nServices)
|
||||
r += struct.pack("<q", self.nTime)
|
||||
@@ -689,7 +694,7 @@ class msg_version(object):
|
||||
|
||||
|
||||
class msg_verack(object):
|
||||
command = "verack"
|
||||
command = b"verack"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -698,14 +703,14 @@ class msg_verack(object):
|
||||
pass
|
||||
|
||||
def serialize(self):
|
||||
return ""
|
||||
return b""
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_verack()"
|
||||
|
||||
|
||||
class msg_addr(object):
|
||||
command = "addr"
|
||||
command = b"addr"
|
||||
|
||||
def __init__(self):
|
||||
self.addrs = []
|
||||
@@ -721,7 +726,7 @@ class msg_addr(object):
|
||||
|
||||
|
||||
class msg_alert(object):
|
||||
command = "alert"
|
||||
command = b"alert"
|
||||
|
||||
def __init__(self):
|
||||
self.alert = CAlert()
|
||||
@@ -731,7 +736,7 @@ class msg_alert(object):
|
||||
self.alert.deserialize(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += self.alert.serialize()
|
||||
return r
|
||||
|
||||
@@ -740,7 +745,7 @@ class msg_alert(object):
|
||||
|
||||
|
||||
class msg_inv(object):
|
||||
command = "inv"
|
||||
command = b"inv"
|
||||
|
||||
def __init__(self, inv=None):
|
||||
if inv is None:
|
||||
@@ -759,7 +764,7 @@ class msg_inv(object):
|
||||
|
||||
|
||||
class msg_getdata(object):
|
||||
command = "getdata"
|
||||
command = b"getdata"
|
||||
|
||||
def __init__(self, inv=None):
|
||||
self.inv = inv if inv != None else []
|
||||
@@ -775,11 +780,11 @@ class msg_getdata(object):
|
||||
|
||||
|
||||
class msg_getblocks(object):
|
||||
command = "getblocks"
|
||||
command = b"getblocks"
|
||||
|
||||
def __init__(self):
|
||||
self.locator = CBlockLocator()
|
||||
self.hashstop = 0L
|
||||
self.hashstop = 0
|
||||
|
||||
def deserialize(self, f):
|
||||
self.locator = CBlockLocator()
|
||||
@@ -787,7 +792,7 @@ class msg_getblocks(object):
|
||||
self.hashstop = deser_uint256(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += self.locator.serialize()
|
||||
r += ser_uint256(self.hashstop)
|
||||
return r
|
||||
@@ -798,7 +803,7 @@ class msg_getblocks(object):
|
||||
|
||||
|
||||
class msg_tx(object):
|
||||
command = "tx"
|
||||
command = b"tx"
|
||||
|
||||
def __init__(self, tx=CTransaction()):
|
||||
self.tx = tx
|
||||
@@ -814,7 +819,7 @@ class msg_tx(object):
|
||||
|
||||
|
||||
class msg_block(object):
|
||||
command = "block"
|
||||
command = b"block"
|
||||
|
||||
def __init__(self, block=None):
|
||||
if block is None:
|
||||
@@ -833,7 +838,7 @@ class msg_block(object):
|
||||
|
||||
|
||||
class msg_getaddr(object):
|
||||
command = "getaddr"
|
||||
command = b"getaddr"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -842,14 +847,14 @@ class msg_getaddr(object):
|
||||
pass
|
||||
|
||||
def serialize(self):
|
||||
return ""
|
||||
return b""
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_getaddr()"
|
||||
|
||||
|
||||
class msg_ping_prebip31(object):
|
||||
command = "ping"
|
||||
command = b"ping"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -858,23 +863,23 @@ class msg_ping_prebip31(object):
|
||||
pass
|
||||
|
||||
def serialize(self):
|
||||
return ""
|
||||
return b""
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_ping() (pre-bip31)"
|
||||
|
||||
|
||||
class msg_ping(object):
|
||||
command = "ping"
|
||||
command = b"ping"
|
||||
|
||||
def __init__(self, nonce=0L):
|
||||
def __init__(self, nonce=0):
|
||||
self.nonce = nonce
|
||||
|
||||
def deserialize(self, f):
|
||||
self.nonce = struct.unpack("<Q", f.read(8))[0]
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<Q", self.nonce)
|
||||
return r
|
||||
|
||||
@@ -883,16 +888,16 @@ class msg_ping(object):
|
||||
|
||||
|
||||
class msg_pong(object):
|
||||
command = "pong"
|
||||
command = b"pong"
|
||||
|
||||
def __init__(self, nonce=0L):
|
||||
def __init__(self, nonce=0):
|
||||
self.nonce = nonce
|
||||
|
||||
def deserialize(self, f):
|
||||
self.nonce = struct.unpack("<Q", f.read(8))[0]
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += struct.pack("<Q", self.nonce)
|
||||
return r
|
||||
|
||||
@@ -901,7 +906,7 @@ class msg_pong(object):
|
||||
|
||||
|
||||
class msg_mempool(object):
|
||||
command = "mempool"
|
||||
command = b"mempool"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -910,13 +915,13 @@ class msg_mempool(object):
|
||||
pass
|
||||
|
||||
def serialize(self):
|
||||
return ""
|
||||
return b""
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_mempool()"
|
||||
|
||||
class msg_sendheaders(object):
|
||||
command = "sendheaders"
|
||||
command = b"sendheaders"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -925,21 +930,22 @@ class msg_sendheaders(object):
|
||||
pass
|
||||
|
||||
def serialize(self):
|
||||
return ""
|
||||
return b""
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_sendheaders()"
|
||||
|
||||
|
||||
# getheaders message has
|
||||
# number of entries
|
||||
# vector of hashes
|
||||
# hash_stop (hash of last desired block header, 0 to get as many as possible)
|
||||
class msg_getheaders(object):
|
||||
command = "getheaders"
|
||||
command = b"getheaders"
|
||||
|
||||
def __init__(self):
|
||||
self.locator = CBlockLocator()
|
||||
self.hashstop = 0L
|
||||
self.hashstop = 0
|
||||
|
||||
def deserialize(self, f):
|
||||
self.locator = CBlockLocator()
|
||||
@@ -947,7 +953,7 @@ class msg_getheaders(object):
|
||||
self.hashstop = deser_uint256(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ""
|
||||
r = b""
|
||||
r += self.locator.serialize()
|
||||
r += ser_uint256(self.hashstop)
|
||||
return r
|
||||
@@ -960,7 +966,7 @@ class msg_getheaders(object):
|
||||
# headers message has
|
||||
# <count> <vector of block headers>
|
||||
class msg_headers(object):
|
||||
command = "headers"
|
||||
command = b"headers"
|
||||
|
||||
def __init__(self):
|
||||
self.headers = []
|
||||
@@ -980,26 +986,29 @@ class msg_headers(object):
|
||||
|
||||
|
||||
class msg_reject(object):
|
||||
command = "reject"
|
||||
command = b"reject"
|
||||
REJECT_MALFORMED = 1
|
||||
|
||||
def __init__(self):
|
||||
self.message = ""
|
||||
self.code = ""
|
||||
self.reason = ""
|
||||
self.data = 0L
|
||||
self.message = b""
|
||||
self.code = 0
|
||||
self.reason = b""
|
||||
self.data = 0
|
||||
|
||||
def deserialize(self, f):
|
||||
self.message = deser_string(f)
|
||||
self.code = struct.unpack("<B", f.read(1))[0]
|
||||
self.reason = deser_string(f)
|
||||
if (self.message == "block" or self.message == "tx"):
|
||||
if (self.code != self.REJECT_MALFORMED and
|
||||
(self.message == b"block" or self.message == b"tx")):
|
||||
self.data = deser_uint256(f)
|
||||
|
||||
def serialize(self):
|
||||
r = ser_string(self.message)
|
||||
r += struct.pack("<B", self.code)
|
||||
r += ser_string(self.reason)
|
||||
if (self.message == "block" or self.message == "tx"):
|
||||
if (self.code != self.REJECT_MALFORMED and
|
||||
(self.message == b"block" or self.message == b"tx")):
|
||||
r += ser_uint256(self.data)
|
||||
return r
|
||||
|
||||
@@ -1074,10 +1083,10 @@ class NodeConnCB(object):
|
||||
time.sleep(deliver_sleep)
|
||||
with mininode_lock:
|
||||
try:
|
||||
getattr(self, 'on_' + message.command)(conn, message)
|
||||
getattr(self, 'on_' + message.command.decode('ascii'))(conn, message)
|
||||
except:
|
||||
print "ERROR delivering %s (%s)" % (repr(message),
|
||||
sys.exc_info()[0])
|
||||
print("ERROR delivering %s (%s)" % (repr(message),
|
||||
sys.exc_info()[0]))
|
||||
|
||||
def on_version(self, conn, message):
|
||||
if message.nVersion >= 209:
|
||||
@@ -1115,6 +1124,7 @@ class NodeConnCB(object):
|
||||
def on_mempool(self, conn): pass
|
||||
def on_pong(self, conn, message): pass
|
||||
def on_feefilter(self, conn, message): pass
|
||||
def on_sendheaders(self, conn, message): pass
|
||||
|
||||
# More useful callbacks and functions for NodeConnCB's which have a single NodeConn
|
||||
class SingleNodeConnCB(NodeConnCB):
|
||||
@@ -1147,28 +1157,29 @@ class SingleNodeConnCB(NodeConnCB):
|
||||
# This class provides an interface for a p2p connection to a specified node
|
||||
class NodeConn(asyncore.dispatcher):
|
||||
messagemap = {
|
||||
"version": msg_version,
|
||||
"verack": msg_verack,
|
||||
"addr": msg_addr,
|
||||
"alert": msg_alert,
|
||||
"inv": msg_inv,
|
||||
"getdata": msg_getdata,
|
||||
"getblocks": msg_getblocks,
|
||||
"tx": msg_tx,
|
||||
"block": msg_block,
|
||||
"getaddr": msg_getaddr,
|
||||
"ping": msg_ping,
|
||||
"pong": msg_pong,
|
||||
"headers": msg_headers,
|
||||
"getheaders": msg_getheaders,
|
||||
"reject": msg_reject,
|
||||
"mempool": msg_mempool,
|
||||
"feefilter": msg_feefilter
|
||||
b"version": msg_version,
|
||||
b"verack": msg_verack,
|
||||
b"addr": msg_addr,
|
||||
b"alert": msg_alert,
|
||||
b"inv": msg_inv,
|
||||
b"getdata": msg_getdata,
|
||||
b"getblocks": msg_getblocks,
|
||||
b"tx": msg_tx,
|
||||
b"block": msg_block,
|
||||
b"getaddr": msg_getaddr,
|
||||
b"ping": msg_ping,
|
||||
b"pong": msg_pong,
|
||||
b"headers": msg_headers,
|
||||
b"getheaders": msg_getheaders,
|
||||
b"reject": msg_reject,
|
||||
b"mempool": msg_mempool,
|
||||
b"feefilter": msg_feefilter,
|
||||
b"sendheaders": msg_sendheaders
|
||||
}
|
||||
MAGIC_BYTES = {
|
||||
"mainnet": "\xf9\xbe\xb4\xd9", # mainnet
|
||||
"testnet3": "\x0b\x11\x09\x07", # testnet3
|
||||
"regtest": "\xfa\xbf\xb5\xda" # regtest
|
||||
"mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
|
||||
"testnet3": b"\x0b\x11\x09\x07", # testnet3
|
||||
"regtest": b"\xfa\xbf\xb5\xda" # regtest
|
||||
}
|
||||
|
||||
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
|
||||
@@ -1177,8 +1188,8 @@ class NodeConn(asyncore.dispatcher):
|
||||
self.dstaddr = dstaddr
|
||||
self.dstport = dstport
|
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.sendbuf = ""
|
||||
self.recvbuf = ""
|
||||
self.sendbuf = b""
|
||||
self.recvbuf = b""
|
||||
self.ver_send = 209
|
||||
self.ver_recv = 209
|
||||
self.last_sent = 0
|
||||
@@ -1195,8 +1206,8 @@ class NodeConn(asyncore.dispatcher):
|
||||
vt.addrFrom.ip = "0.0.0.0"
|
||||
vt.addrFrom.port = 0
|
||||
self.send_message(vt, True)
|
||||
print 'MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \
|
||||
+ str(dstport)
|
||||
print('MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \
|
||||
+ str(dstport))
|
||||
|
||||
try:
|
||||
self.connect((dstaddr, dstport))
|
||||
@@ -1215,8 +1226,8 @@ class NodeConn(asyncore.dispatcher):
|
||||
self.show_debug_msg("MiniNode: Closing Connection to %s:%d... "
|
||||
% (self.dstaddr, self.dstport))
|
||||
self.state = "closed"
|
||||
self.recvbuf = ""
|
||||
self.sendbuf = ""
|
||||
self.recvbuf = b""
|
||||
self.sendbuf = b""
|
||||
try:
|
||||
self.close()
|
||||
except:
|
||||
@@ -1250,43 +1261,48 @@ class NodeConn(asyncore.dispatcher):
|
||||
self.sendbuf = self.sendbuf[sent:]
|
||||
|
||||
def got_data(self):
|
||||
while True:
|
||||
if len(self.recvbuf) < 4:
|
||||
return
|
||||
if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
|
||||
raise ValueError("got garbage %s" % repr(self.recvbuf))
|
||||
if self.ver_recv < 209:
|
||||
if len(self.recvbuf) < 4 + 12 + 4:
|
||||
try:
|
||||
while True:
|
||||
if len(self.recvbuf) < 4:
|
||||
return
|
||||
command = self.recvbuf[4:4+12].split("\x00", 1)[0]
|
||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
||||
checksum = None
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + msglen:
|
||||
return
|
||||
msg = self.recvbuf[4+12+4:4+12+4+msglen]
|
||||
self.recvbuf = self.recvbuf[4+12+4+msglen:]
|
||||
else:
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + 4:
|
||||
return
|
||||
command = self.recvbuf[4:4+12].split("\x00", 1)[0]
|
||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
||||
checksum = self.recvbuf[4+12+4:4+12+4+4]
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
|
||||
return
|
||||
msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
|
||||
th = sha256(msg)
|
||||
h = sha256(th)
|
||||
if checksum != h[:4]:
|
||||
raise ValueError("got bad checksum " + repr(self.recvbuf))
|
||||
self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
|
||||
if command in self.messagemap:
|
||||
f = BytesIO(msg)
|
||||
t = self.messagemap[command]()
|
||||
t.deserialize(f)
|
||||
self.got_message(t)
|
||||
else:
|
||||
self.show_debug_msg("Unknown command: '" + command + "' " +
|
||||
repr(msg))
|
||||
if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
|
||||
raise ValueError("got garbage %s" % repr(self.recvbuf))
|
||||
if self.ver_recv < 209:
|
||||
if len(self.recvbuf) < 4 + 12 + 4:
|
||||
return
|
||||
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
|
||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
||||
checksum = None
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + msglen:
|
||||
return
|
||||
msg = self.recvbuf[4+12+4:4+12+4+msglen]
|
||||
self.recvbuf = self.recvbuf[4+12+4+msglen:]
|
||||
else:
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + 4:
|
||||
return
|
||||
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
|
||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
||||
checksum = self.recvbuf[4+12+4:4+12+4+4]
|
||||
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
|
||||
return
|
||||
msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
|
||||
th = sha256(msg)
|
||||
h = sha256(th)
|
||||
if checksum != h[:4]:
|
||||
raise ValueError("got bad checksum " + repr(self.recvbuf))
|
||||
self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
|
||||
if command in self.messagemap:
|
||||
f = BytesIO(msg)
|
||||
t = self.messagemap[command]()
|
||||
t.deserialize(f)
|
||||
self.got_message(t)
|
||||
else:
|
||||
self.show_debug_msg("Unknown command: '" + command + "' " +
|
||||
repr(msg))
|
||||
except Exception as e:
|
||||
print('got_data:', repr(e))
|
||||
# import traceback
|
||||
# traceback.print_tb(sys.exc_info()[2])
|
||||
|
||||
def send_message(self, message, pushbuf=False):
|
||||
if self.state != "connected" and not pushbuf:
|
||||
@@ -1296,7 +1312,7 @@ class NodeConn(asyncore.dispatcher):
|
||||
data = message.serialize()
|
||||
tmsg = self.MAGIC_BYTES[self.network]
|
||||
tmsg += command
|
||||
tmsg += "\x00" * (12 - len(command))
|
||||
tmsg += b"\x00" * (12 - len(command))
|
||||
tmsg += struct.pack("<I", len(data))
|
||||
if self.ver_send >= 209:
|
||||
th = sha256(data)
|
||||
@@ -1308,11 +1324,11 @@ class NodeConn(asyncore.dispatcher):
|
||||
self.last_sent = time.time()
|
||||
|
||||
def got_message(self, message):
|
||||
if message.command == "version":
|
||||
if message.command == b"version":
|
||||
if message.nVersion <= BIP0031_VERSION:
|
||||
self.messagemap['ping'] = msg_ping_prebip31
|
||||
self.messagemap[b'ping'] = msg_ping_prebip31
|
||||
if self.last_sent + 30 * 60 < time.time():
|
||||
self.send_message(self.messagemap['ping']())
|
||||
self.send_message(self.messagemap[b'ping']())
|
||||
self.show_debug_msg("Recv %s" % repr(message))
|
||||
self.cb.deliver(self, message)
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
# Linux network utilities
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import fcntl
|
||||
import struct
|
||||
import array
|
||||
import os
|
||||
import binascii
|
||||
from binascii import unhexlify, hexlify
|
||||
|
||||
# Roughly based on http://voorloopnul.com/blog/a-python-netstat-in-less-than-100-lines-of-code/ by Ricardo Pascal
|
||||
STATE_ESTABLISHED = '01'
|
||||
@@ -43,9 +44,9 @@ def _remove_empty(array):
|
||||
def _convert_ip_port(array):
|
||||
host,port = array.split(':')
|
||||
# convert host from mangled-per-four-bytes form as used by kernel
|
||||
host = binascii.unhexlify(host)
|
||||
host = unhexlify(host)
|
||||
host_out = ''
|
||||
for x in range(0, len(host)/4):
|
||||
for x in range(0, len(host) // 4):
|
||||
(val,) = struct.unpack('=I', host[x*4:(x+1)*4])
|
||||
host_out += '%08x' % val
|
||||
|
||||
@@ -94,7 +95,7 @@ def all_interfaces():
|
||||
max_possible = 8 # initial value
|
||||
while True:
|
||||
bytes = max_possible * struct_size
|
||||
names = array.array('B', '\0' * bytes)
|
||||
names = array.array('B', b'\0' * bytes)
|
||||
outbytes = struct.unpack('iL', fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8912, # SIOCGIFCONF
|
||||
@@ -105,7 +106,7 @@ def all_interfaces():
|
||||
else:
|
||||
break
|
||||
namestr = names.tostring()
|
||||
return [(namestr[i:i+16].split('\0', 1)[0],
|
||||
return [(namestr[i:i+16].split(b'\0', 1)[0],
|
||||
socket.inet_ntoa(namestr[i+20:i+24]))
|
||||
for i in range(0, outbytes, struct_size)]
|
||||
|
||||
@@ -134,9 +135,10 @@ def addr_to_hex(addr):
|
||||
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
||||
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
|
||||
addr = sub[0] + ([0] * nullbytes) + sub[1]
|
||||
else:
|
||||
else:
|
||||
raise ValueError('Could not parse address %s' % addr)
|
||||
return binascii.hexlify(bytearray(addr))
|
||||
return hexlify(bytearray(addr)).decode('ascii')
|
||||
|
||||
def test_ipv6_local():
|
||||
'''
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#!/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.
|
||||
|
||||
#
|
||||
# script.py
|
||||
#
|
||||
# This file is modified from python-bitcoinlib.
|
||||
#
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
"""Scripts
|
||||
|
||||
Functionality to build scripts, as well as SignatureHash().
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from .mininode import CTransaction, CTxOut, hash256
|
||||
from binascii import hexlify
|
||||
@@ -227,7 +228,7 @@ OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf)
|
||||
# expansion
|
||||
OP_NOP1 = CScriptOp(0xb0)
|
||||
OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1)
|
||||
OP_NOP3 = CScriptOp(0xb2)
|
||||
OP_CHECKSEQUENCEVERIFY = CScriptOp(0xb2)
|
||||
OP_NOP4 = CScriptOp(0xb3)
|
||||
OP_NOP5 = CScriptOp(0xb4)
|
||||
OP_NOP6 = CScriptOp(0xb5)
|
||||
@@ -354,7 +355,7 @@ VALID_OPCODES = {
|
||||
|
||||
OP_NOP1,
|
||||
OP_CHECKLOCKTIMEVERIFY,
|
||||
OP_NOP3,
|
||||
OP_CHECKSEQUENCEVERIFY,
|
||||
OP_NOP4,
|
||||
OP_NOP5,
|
||||
OP_NOP6,
|
||||
@@ -473,7 +474,7 @@ OPCODE_NAMES.update({
|
||||
OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY',
|
||||
OP_NOP1 : 'OP_NOP1',
|
||||
OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY',
|
||||
OP_NOP3 : 'OP_NOP3',
|
||||
OP_CHECKSEQUENCEVERIFY : 'OP_CHECKSEQUENCEVERIFY',
|
||||
OP_NOP4 : 'OP_NOP4',
|
||||
OP_NOP5 : 'OP_NOP5',
|
||||
OP_NOP6 : 'OP_NOP6',
|
||||
@@ -592,7 +593,7 @@ OPCODES_BY_NAME = {
|
||||
'OP_CHECKMULTISIGVERIFY' : OP_CHECKMULTISIGVERIFY,
|
||||
'OP_NOP1' : OP_NOP1,
|
||||
'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY,
|
||||
'OP_NOP3' : OP_NOP3,
|
||||
'OP_CHECKSEQUENCEVERIFY' : OP_CHECKSEQUENCEVERIFY,
|
||||
'OP_NOP4' : OP_NOP4,
|
||||
'OP_NOP5' : OP_NOP5,
|
||||
'OP_NOP6' : OP_NOP6,
|
||||
@@ -629,7 +630,7 @@ class CScriptNum(object):
|
||||
neg = obj.value < 0
|
||||
absvalue = -obj.value if neg else obj.value
|
||||
while (absvalue):
|
||||
r.append(chr(absvalue & 0xff))
|
||||
r.append(absvalue & 0xff)
|
||||
absvalue >>= 8
|
||||
if r[-1] & 0x80:
|
||||
r.append(0x80 if neg else 0)
|
||||
@@ -658,7 +659,7 @@ class CScript(bytes):
|
||||
other = bchr(CScriptOp(OP_0))
|
||||
else:
|
||||
other = CScriptNum.encode(other)
|
||||
elif isinstance(other, (int, long)):
|
||||
elif isinstance(other, int):
|
||||
if 0 <= other <= 16:
|
||||
other = bytes(bchr(CScriptOp.encode_op_n(other)))
|
||||
elif other == -1:
|
||||
@@ -777,7 +778,7 @@ class CScript(bytes):
|
||||
# need to change
|
||||
def _repr(o):
|
||||
if isinstance(o, bytes):
|
||||
return "x('%s')" % hexlify(o).decode('utf8')
|
||||
return b"x('%s')" % hexlify(o).decode('ascii')
|
||||
else:
|
||||
return repr(o)
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
#!/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.
|
||||
'''
|
||||
Dummy Socks5 server for testing.
|
||||
'''
|
||||
from __future__ import print_function, division, unicode_literals
|
||||
import socket, threading, Queue
|
||||
|
||||
import socket, threading, queue
|
||||
import traceback, sys
|
||||
|
||||
### Protocol constants
|
||||
@@ -102,7 +103,7 @@ class Socks5Connection(object):
|
||||
addr = recvall(self.conn, 4)
|
||||
elif atyp == AddressType.DOMAINNAME:
|
||||
n = recvall(self.conn, 1)[0]
|
||||
addr = str(recvall(self.conn, n))
|
||||
addr = recvall(self.conn, n)
|
||||
elif atyp == AddressType.IPV6:
|
||||
addr = recvall(self.conn, 16)
|
||||
else:
|
||||
@@ -132,7 +133,7 @@ class Socks5Server(object):
|
||||
self.s.listen(5)
|
||||
self.running = False
|
||||
self.thread = None
|
||||
self.queue = Queue.Queue() # report connections and exceptions to client
|
||||
self.queue = queue.Queue() # report connections and exceptions to client
|
||||
|
||||
def run(self):
|
||||
while self.running:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -144,10 +144,10 @@ class BitcoinTestFramework(object):
|
||||
print("JSONRPC error: "+e.error['message'])
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
except AssertionError as e:
|
||||
print("Assertion failed: "+ str(e))
|
||||
print("Assertion failed: " + str(e))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
except Exception as e:
|
||||
print("Unexpected exception caught during testing: "+str(e))
|
||||
print("Unexpected exception caught during testing: " + repr(e))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
|
||||
if not self.options.noshutdown:
|
||||
@@ -190,7 +190,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
|
||||
help="bitcoind binary to use for reference nodes (if any)")
|
||||
|
||||
def setup_chain(self):
|
||||
print "Initializing test directory "+self.options.tmpdir
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
||||
|
||||
def setup_network(self):
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
#
|
||||
# Helpful routines for regression testing
|
||||
#
|
||||
@@ -9,6 +12,8 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from binascii import hexlify, unhexlify
|
||||
from base64 import b64encode
|
||||
from decimal import Decimal, ROUND_DOWN
|
||||
import json
|
||||
import random
|
||||
@@ -16,6 +21,7 @@ import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import re
|
||||
import errno
|
||||
|
||||
from . import coverage
|
||||
from .authproxy import AuthServiceProxy, JSONRPCException
|
||||
@@ -90,6 +96,15 @@ def check_json_precision():
|
||||
def count_bytes(hex_string):
|
||||
return len(bytearray.fromhex(hex_string))
|
||||
|
||||
def bytes_to_hex_str(byte_str):
|
||||
return hexlify(byte_str).decode('ascii')
|
||||
|
||||
def hex_str_to_bytes(hex_str):
|
||||
return unhexlify(hex_str.encode('ascii'))
|
||||
|
||||
def str_to_b64str(string):
|
||||
return b64encode(string.encode('utf-8')).decode('ascii')
|
||||
|
||||
def sync_blocks(rpc_connections, wait=1):
|
||||
"""
|
||||
Wait until everybody has the same block count
|
||||
@@ -130,11 +145,33 @@ def initialize_datadir(dirname, n):
|
||||
f.write("listenonion=0\n")
|
||||
return datadir
|
||||
|
||||
def rpc_url(i, rpchost=None):
|
||||
return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
|
||||
|
||||
def wait_for_bitcoind_start(process, url, i):
|
||||
'''
|
||||
Wait for bitcoind to start. This means that RPC is accessible and fully initialized.
|
||||
Raise an exception if bitcoind exits during initialization.
|
||||
'''
|
||||
while True:
|
||||
if process.poll() is not None:
|
||||
raise Exception('bitcoind exited with status %i during initialization' % process.returncode)
|
||||
try:
|
||||
rpc = get_rpc_proxy(url, i)
|
||||
blocks = rpc.getblockcount()
|
||||
break # break out of loop on success
|
||||
except IOError as e:
|
||||
if e.errno != errno.ECONNREFUSED: # Port not yet open?
|
||||
raise # unknown IO error
|
||||
except JSONRPCException as e: # Initialization phase
|
||||
if e.error['code'] != -28: # RPC in warmup?
|
||||
raise # unkown JSON RPC exception
|
||||
time.sleep(0.25)
|
||||
|
||||
def initialize_chain(test_dir):
|
||||
"""
|
||||
Create (or copy from cache) a 200-block-long chain and
|
||||
4 wallets.
|
||||
bitcoind and bitcoin-cli must be in search path.
|
||||
"""
|
||||
|
||||
if (not os.path.isdir(os.path.join("cache","node0"))
|
||||
@@ -147,7 +184,6 @@ def initialize_chain(test_dir):
|
||||
if os.path.isdir(os.path.join("cache","node"+str(i))):
|
||||
shutil.rmtree(os.path.join("cache","node"+str(i)))
|
||||
|
||||
devnull = open(os.devnull, "w")
|
||||
# Create cache directories, run bitcoinds:
|
||||
for i in range(4):
|
||||
datadir=initialize_datadir("cache", i)
|
||||
@@ -156,19 +192,15 @@ def initialize_chain(test_dir):
|
||||
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
|
||||
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir,
|
||||
"-rpcwait", "getblockcount"], stdout=devnull)
|
||||
print("initialize_chain: bitcoind started, waiting for RPC to come up")
|
||||
wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed"
|
||||
devnull.close()
|
||||
print("initialize_chain: RPC succesfully started")
|
||||
|
||||
rpcs = []
|
||||
|
||||
for i in range(4):
|
||||
try:
|
||||
url = "http://rt:rt@127.0.0.1:%d" % (rpc_port(i),)
|
||||
rpcs.append(get_rpc_proxy(url, i))
|
||||
rpcs.append(get_rpc_proxy(rpc_url(i), i))
|
||||
except:
|
||||
sys.stderr.write("Error connecting to "+url+"\n")
|
||||
sys.exit(1)
|
||||
@@ -240,20 +272,16 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
datadir = os.path.join(dirname, "node"+str(i))
|
||||
if binary is None:
|
||||
binary = os.getenv("BITCOIND", "bitcoind")
|
||||
args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ]
|
||||
# RPC tests still depend on free transactions
|
||||
args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000", "-mocktime="+str(get_mocktime()) ]
|
||||
if extra_args is not None: args.extend(extra_args)
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
devnull = open(os.devnull, "w")
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
|
||||
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] +
|
||||
_rpchost_to_args(rpchost) +
|
||||
["-rpcwait", "getblockcount"], stdout=devnull)
|
||||
print("start_node: bitcoind started, waiting for RPC to come up")
|
||||
url = rpc_url(i, rpchost)
|
||||
wait_for_bitcoind_start(bitcoind_processes[i], url, i)
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print "start_node: calling bitcoin-cli -rpcwait getblockcount returned"
|
||||
devnull.close()
|
||||
url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
|
||||
|
||||
print("start_node: RPC succesfully started")
|
||||
proxy = get_rpc_proxy(url, i, timeout=timewait)
|
||||
|
||||
if COVERAGE_DIR:
|
||||
@@ -267,7 +295,14 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
|
||||
"""
|
||||
if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
|
||||
if binary is None: binary = [ None for i in range(num_nodes) ]
|
||||
return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ]
|
||||
rpcs = []
|
||||
try:
|
||||
for i in range(num_nodes):
|
||||
rpcs.append(start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]))
|
||||
except: # If one node failed to start, stop the others
|
||||
stop_nodes(rpcs)
|
||||
raise
|
||||
return rpcs
|
||||
|
||||
def log_filename(dirname, n_node, logname):
|
||||
return os.path.join(dirname, "node"+str(n_node), "regtest", logname)
|
||||
@@ -445,7 +480,7 @@ def assert_is_hex_string(string):
|
||||
"Couldn't interpret %r as hexadecimal; raised: %s" % (string, e))
|
||||
|
||||
def assert_is_hash_string(string, length=64):
|
||||
if not isinstance(string, basestring):
|
||||
if not isinstance(string, str):
|
||||
raise AssertionError("Expected a string, got type %r" % type(string))
|
||||
elif length and len(string) != length:
|
||||
raise AssertionError(
|
||||
@@ -454,9 +489,40 @@ def assert_is_hash_string(string, length=64):
|
||||
raise AssertionError(
|
||||
"String %r contains invalid characters for a hash." % string)
|
||||
|
||||
def satoshi_round(amount):
|
||||
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
||||
def assert_array_result(object_array, to_match, expected, should_not_find = False):
|
||||
"""
|
||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
||||
to match against, and another dictionary with expected key/value
|
||||
pairs.
|
||||
If the should_not_find flag is true, to_match should not be found
|
||||
in object_array
|
||||
"""
|
||||
if should_not_find == True:
|
||||
assert_equal(expected, { })
|
||||
num_matched = 0
|
||||
for item in object_array:
|
||||
all_match = True
|
||||
for key,value in to_match.items():
|
||||
if item[key] != value:
|
||||
all_match = False
|
||||
if not all_match:
|
||||
continue
|
||||
elif should_not_find == True:
|
||||
num_matched = num_matched+1
|
||||
for key,value in expected.items():
|
||||
if item[key] != value:
|
||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
||||
num_matched = num_matched+1
|
||||
if num_matched == 0 and should_not_find != True:
|
||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
||||
if num_matched > 0 and should_not_find == True:
|
||||
raise AssertionError("Objects were found %s"%(str(to_match)))
|
||||
|
||||
def satoshi_round(amount):
|
||||
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
||||
|
||||
# Helper to create at least "count" utxos
|
||||
# Pass in a fee that is sufficient for relay and mining new transactions.
|
||||
def create_confirmed_utxos(fee, node, count):
|
||||
node.generate(int(0.5*count)+101)
|
||||
utxos = node.listunspent()
|
||||
@@ -465,7 +531,7 @@ def create_confirmed_utxos(fee, node, count):
|
||||
addr2 = node.getnewaddress()
|
||||
if iterations <= 0:
|
||||
return utxos
|
||||
for i in xrange(iterations):
|
||||
for i in range(iterations):
|
||||
t = utxos.pop()
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
@@ -484,16 +550,18 @@ def create_confirmed_utxos(fee, node, count):
|
||||
assert(len(utxos) >= count)
|
||||
return utxos
|
||||
|
||||
# Create large OP_RETURN txouts that can be appended to a transaction
|
||||
# to make it large (helper for constructing large transactions).
|
||||
def gen_return_txouts():
|
||||
# Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
|
||||
# So we have big transactions (and therefore can't fit very many into each block)
|
||||
# create one script_pubkey
|
||||
script_pubkey = "6a4d0200" #OP_RETURN OP_PUSH2 512 bytes
|
||||
for i in xrange (512):
|
||||
for i in range (512):
|
||||
script_pubkey = script_pubkey + "01"
|
||||
# concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
|
||||
txouts = "81"
|
||||
for k in xrange(128):
|
||||
for k in range(128):
|
||||
# add txout value
|
||||
txouts = txouts + "0000000000000000"
|
||||
# add length of script_pubkey
|
||||
@@ -502,10 +570,20 @@ def gen_return_txouts():
|
||||
txouts = txouts + script_pubkey
|
||||
return txouts
|
||||
|
||||
def create_tx(node, coinbase, to_address, amount):
|
||||
inputs = [{ "txid" : coinbase, "vout" : 0}]
|
||||
outputs = { to_address : amount }
|
||||
rawtx = node.createrawtransaction(inputs, outputs)
|
||||
signresult = node.signrawtransaction(rawtx)
|
||||
assert_equal(signresult["complete"], True)
|
||||
return signresult["hex"]
|
||||
|
||||
# Create a spend of each passed-in utxo, splicing in "txouts" to each raw
|
||||
# transaction to make it large. See gen_return_txouts() above.
|
||||
def create_lots_of_big_transactions(node, txouts, utxos, fee):
|
||||
addr = node.getnewaddress()
|
||||
txids = []
|
||||
for i in xrange(len(utxos)):
|
||||
for i in range(len(utxos)):
|
||||
t = utxos.pop()
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
|
||||
Reference in New Issue
Block a user