@ -28,7 +28,7 @@ import asyncore
@@ -28,7 +28,7 @@ import asyncore
import time
import sys
import random
from binascii import hexlify , unhexlify
from . util import hex_str_to_bytes , bytes_to_hex_str
from io import BytesIO
from codecs import encode
import hashlib
@ -46,6 +46,11 @@ MAX_BLOCK_SIZE = 1000000
@@ -46,6 +46,11 @@ MAX_BLOCK_SIZE = 1000000
COIN = 100000000 # 1 btc in satoshis
NODE_NETWORK = ( 1 << 0 )
NODE_GETUTXO = ( 1 << 1 )
NODE_BLOOM = ( 1 << 2 )
NODE_WITNESS = ( 1 << 3 )
# 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)
@ -63,6 +68,8 @@ mininode_lock = RLock()
@@ -63,6 +68,8 @@ mininode_lock = RLock()
def sha256 ( s ) :
return hashlib . new ( ' sha256 ' , s ) . digest ( )
def ripemd160 ( s ) :
return hashlib . new ( ' ripemd160 ' , s ) . digest ( )
def hash256 ( s ) :
return sha256 ( sha256 ( s ) )
@ -133,7 +140,10 @@ def deser_vector(f, c):
@@ -133,7 +140,10 @@ def deser_vector(f, c):
return r
def ser_vector ( l ) :
# ser_function_name: Allow for an alternate serialization function on the
# entries in the vector (we use this for serializing the vector of transactions
# for a witness block).
def ser_vector ( l , ser_function_name = None ) :
r = b " "
if len ( l ) < 253 :
r = struct . pack ( " B " , len ( l ) )
@ -144,6 +154,9 @@ def ser_vector(l):
@@ -144,6 +154,9 @@ def ser_vector(l):
else :
r = struct . pack ( " <BQ " , 255 , len ( l ) )
for i in l :
if ser_function_name :
r + = getattr ( i , ser_function_name ) ( )
else :
r + = i . serialize ( )
return r
@ -239,12 +252,12 @@ def ser_int_vector(l):
@@ -239,12 +252,12 @@ def ser_int_vector(l):
# Deserialize from a hex string representation (eg from RPC)
def FromHex ( obj , hex_string ) :
obj . deserialize ( BytesIO ( unhexlify ( hex_string . encode ( ' ascii ' ) ) ) )
obj . deserialize ( BytesIO ( hex_str_to_bytes ( hex_string ) ) )
return obj
# Convert a binary-serializable object to hex (eg for submission via RPC)
def ToHex ( obj ) :
return hexlify ( obj . serialize ( ) ) . decode ( ' ascii ' )
return bytes_to_hex_str ( obj . serialize ( ) )
# Objects that map to bitcoind objects, which can be serialized/deserialized
@ -273,12 +286,16 @@ class CAddress(object):
@@ -273,12 +286,16 @@ class CAddress(object):
return " CAddress(nServices= %i ip= %s port= %i ) " % ( self . nServices ,
self . ip , self . port )
MSG_WITNESS_FLAG = 1 << 30
class CInv ( object ) :
typemap = {
0 : " Error " ,
1 : " TX " ,
2 : " Block " }
2 : " Block " ,
1 | MSG_WITNESS_FLAG : " WitnessTx " ,
2 | MSG_WITNESS_FLAG : " WitnessBlock "
}
def __init__ ( self , t = 0 , h = 0 ) :
self . type = t
@ -362,7 +379,7 @@ class CTxIn(object):
@@ -362,7 +379,7 @@ class CTxIn(object):
def __repr__ ( self ) :
return " CTxIn(prevout= %s scriptSig= %s nSequence= %i ) " \
% ( repr ( self . prevout ) , hexlify ( self . scriptSig ) ,
% ( repr ( self . prevout ) , bytes_to_hex_str ( self . scriptSig ) ,
self . nSequence )
@ -384,7 +401,67 @@ class CTxOut(object):
@@ -384,7 +401,67 @@ class CTxOut(object):
def __repr__ ( self ) :
return " CTxOut(nValue= %i . %08i scriptPubKey= %s ) " \
% ( self . nValue / / COIN , self . nValue % COIN ,
hexlify ( self . scriptPubKey ) )
bytes_to_hex_str ( self . scriptPubKey ) )
class CScriptWitness ( object ) :
def __init__ ( self ) :
# stack is a vector of strings
self . stack = [ ]
def __repr__ ( self ) :
return " CScriptWitness( %s ) " % \
( " , " . join ( [ bytes_to_hex_str ( x ) for x in self . stack ] ) )
def is_null ( self ) :
if self . stack :
return False
return True
class CTxinWitness ( object ) :
def __init__ ( self ) :
self . scriptWitness = CScriptWitness ( )
def deserialize ( self , f ) :
self . scriptWitness . stack = deser_string_vector ( f )
def serialize ( self ) :
return ser_string_vector ( self . scriptWitness . stack )
def __repr__ ( self ) :
return repr ( self . scriptWitness )
def is_null ( self ) :
return self . scriptWitness . is_null ( )
class CTxWitness ( object ) :
def __init__ ( self ) :
self . vtxinwit = [ ]
def deserialize ( self , f ) :
for i in range ( len ( self . vtxinwit ) ) :
self . vtxinwit [ i ] . deserialize ( f )
def serialize ( self ) :
r = b " "
# This is different than the usual vector serialization --
# we omit the length of the vector, which is required to be
# the same length as the transaction's vin vector.
for x in self . vtxinwit :
r + = x . serialize ( )
return r
def __repr__ ( self ) :
return " CTxWitness( %s ) " % \
( ' ; ' . join ( [ repr ( x ) for x in self . vtxinwit ] ) )
def is_null ( self ) :
for x in self . vtxinwit :
if not x . is_null ( ) :
return False
return True
class CTransaction ( object ) :
@ -393,6 +470,7 @@ class CTransaction(object):
@@ -393,6 +470,7 @@ class CTransaction(object):
self . nVersion = 1
self . vin = [ ]
self . vout = [ ]
self . wit = CTxWitness ( )
self . nLockTime = 0
self . sha256 = None
self . hash = None
@ -401,32 +479,80 @@ class CTransaction(object):
@@ -401,32 +479,80 @@ class CTransaction(object):
self . vin = copy . deepcopy ( tx . vin )
self . vout = copy . deepcopy ( tx . vout )
self . nLockTime = tx . nLockTime
self . sha256 = None
self . hash = None
self . sha256 = tx . sha256
self . hash = tx . hash
self . wit = copy . deepcopy ( tx . wit )
def deserialize ( self , f ) :
self . nVersion = struct . unpack ( " <i " , f . read ( 4 ) ) [ 0 ]
self . vin = deser_vector ( f , CTxIn )
flags = 0
if len ( self . vin ) == 0 :
flags = struct . unpack ( " <B " , f . read ( 1 ) ) [ 0 ]
# Not sure why flags can't be zero, but this
# matches the implementation in bitcoind
if ( flags != 0 ) :
self . vin = deser_vector ( f , CTxIn )
self . vout = deser_vector ( f , CTxOut )
else :
self . vout = deser_vector ( f , CTxOut )
if flags != 0 :
self . wit . vtxinwit = [ CTxinWitness ( ) ] * len ( self . vin )
self . wit . deserialize ( f )
self . nLockTime = struct . unpack ( " <I " , f . read ( 4 ) ) [ 0 ]
self . sha256 = None
self . hash = None
def serialize ( self ) :
def serialize_without_witness ( self ) :
r = b " "
r + = struct . pack ( " <i " , self . nVersion )
r + = ser_vector ( self . vin )
r + = ser_vector ( self . vout )
r + = struct . pack ( " <I " , self . nLockTime )
return r
# Only serialize with witness when explicitly called for
def serialize_with_witness ( self ) :
flags = 0
if not self . wit . is_null ( ) :
flags | = 1
r = b " "
r + = struct . pack ( " <i " , self . nVersion )
if flags :
dummy = [ ]
r + = ser_vector ( dummy )
r + = struct . pack ( " <B " , flags )
r + = ser_vector ( self . vin )
r + = ser_vector ( self . vout )
if flags & 1 :
if ( len ( self . wit . vtxinwit ) != len ( self . vin ) ) :
# vtxinwit must have the same length as vin
self . wit . vtxinwit = self . wit . vtxinwit [ : len ( self . vin ) ]
for i in range ( len ( self . wit . vtxinwit ) , len ( self . vin ) ) :
self . wit . vtxinwit . append ( CTxinWitness ( ) )
r + = self . wit . serialize ( )
r + = struct . pack ( " <I " , self . nLockTime )
return r
# Regular serialization is without witness -- must explicitly
# call serialize_with_witness to include witness data.
def serialize ( self ) :
return self . serialize_without_witness ( )
# Recalculate the txid (transaction hash without witness)
def rehash ( self ) :
self . sha256 = None
self . calc_sha256 ( )
def calc_sha256 ( self ) :
# We will only cache the serialization without witness in
# self.sha256 and self.hash -- those are expected to be the txid.
def calc_sha256 ( self , with_witness = False ) :
if with_witness :
# Don't cache the result, just return it
return uint256_from_str ( hash256 ( self . serialize_with_witness ( ) ) )
if self . sha256 is None :
self . sha256 = uint256_from_str ( hash256 ( self . serialize ( ) ) )
self . sha256 = uint256_from_str ( hash256 ( self . serialize_without_witness ( ) ) )
self . hash = encode ( hash256 ( self . serialize ( ) ) [ : : - 1 ] , ' hex_codec ' ) . decode ( ' ascii ' )
def is_valid ( self ) :
@ -518,17 +644,17 @@ class CBlock(CBlockHeader):
@@ -518,17 +644,17 @@ class CBlock(CBlockHeader):
super ( CBlock , self ) . deserialize ( f )
self . vtx = deser_vector ( f , CTransaction )
def serialize ( self ) :
def serialize ( self , with_witness = False ) :
r = b " "
r + = super ( CBlock , self ) . serialize ( )
if with_witness :
r + = ser_vector ( self . vtx , " serialize_with_witness " )
else :
r + = ser_vector ( self . vtx )
return r
def calc_merkle_root ( self ) :
hashes = [ ]
for tx in self . vtx :
tx . calc_sha256 ( )
hashes . append ( ser_uint256 ( tx . sha256 ) )
# Calculate the merkle root given a vector of transaction hashes
def get_merkle_root ( self , hashes ) :
while len ( hashes ) > 1 :
newhashes = [ ]
for i in range ( 0 , len ( hashes ) , 2 ) :
@ -537,6 +663,24 @@ class CBlock(CBlockHeader):
@@ -537,6 +663,24 @@ class CBlock(CBlockHeader):
hashes = newhashes
return uint256_from_str ( hashes [ 0 ] )
def calc_merkle_root ( self ) :
hashes = [ ]
for tx in self . vtx :
tx . calc_sha256 ( )
hashes . append ( ser_uint256 ( tx . sha256 ) )
return self . get_merkle_root ( hashes )
def calc_witness_merkle_root ( self ) :
# For witness root purposes, the hash of the
# coinbase, with witness, is defined to be 0...0
hashes = [ ser_uint256 ( 0 ) ]
for tx in self . vtx [ 1 : ] :
# Calculate the hashes with witness data
hashes . append ( ser_uint256 ( tx . calc_sha256 ( True ) ) )
return self . get_merkle_root ( hashes )
def is_valid ( self ) :
self . calc_sha256 ( )
target = uint256_from_compact ( self . nBits )
@ -812,11 +956,16 @@ class msg_tx(object):
@@ -812,11 +956,16 @@ class msg_tx(object):
self . tx . deserialize ( f )
def serialize ( self ) :
return self . tx . serialize ( )
return self . tx . serialize_without_witness ( )
def __repr__ ( self ) :
return " msg_tx(tx= %s ) " % ( repr ( self . tx ) )
class msg_witness_tx ( msg_tx ) :
def serialize ( self ) :
return self . tx . serialize_with_witness ( )
class msg_block ( object ) :
command = b " block "
@ -849,6 +998,12 @@ class msg_generic(object):
@@ -849,6 +998,12 @@ class msg_generic(object):
def __repr__ ( self ) :
return " msg_generic() "
class msg_witness_block ( msg_block ) :
def serialize ( self ) :
r = self . block . serialize ( with_witness = True )
return r
class msg_getaddr ( object ) :
command = b " getaddr "
@ -947,6 +1102,7 @@ class msg_sendheaders(object):
@@ -947,6 +1102,7 @@ class msg_sendheaders(object):
def __repr__ ( self ) :
return " msg_sendheaders() "
# getheaders message has
# number of entries
# vector of hashes
@ -1068,6 +1224,8 @@ class NodeConnCB(object):
@@ -1068,6 +1224,8 @@ class NodeConnCB(object):
# tests; it causes message delivery to sleep for the specified time
# before acquiring the global lock and delivering the next message.
self . deliver_sleep_time = None
# Remember the services our peer has advertised
self . peer_services = None
def set_deliver_sleep_time ( self , value ) :
with mininode_lock :
@ -1105,6 +1263,7 @@ class NodeConnCB(object):
@@ -1105,6 +1263,7 @@ class NodeConnCB(object):
conn . ver_send = min ( MY_VERSION , message . nVersion )
if message . nVersion < 209 :
conn . ver_recv = conn . ver_send
conn . nServices = message . nServices
def on_verack ( self , conn , message ) :
conn . ver_recv = conn . ver_send
@ -1135,6 +1294,7 @@ class NodeConnCB(object):
@@ -1135,6 +1294,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 ) :
@ -1183,15 +1343,16 @@ class NodeConn(asyncore.dispatcher):
@@ -1183,15 +1343,16 @@ class NodeConn(asyncore.dispatcher):
b " getheaders " : msg_getheaders ,
b " reject " : msg_reject ,
b " mempool " : msg_mempool ,
b " feefilter " : msg_feefilter
b " feefilter " : msg_feefilter ,
b " sendheaders " : msg_sendheaders
}
MAGIC_BYTES = {
" mainnet " : b " \xf9 \xbe \xb4 \xd9 " , # mainnet
" testnet3 " : b " \x0b \x11 \x09 \x07 " , # testnet3
" regtest " : b " \xfa \xbf \xb5 \xda " # regtest
" regtest " : b " \xfa \xbf \xb5 \xda " , # regtest
}
def __init__ ( self , dstaddr , dstport , rpc , callback , net = " regtest " , services = 1 ) :
def __init__ ( self , dstaddr , dstport , rpc , callback , net = " regtest " , services = NODE_NETWORK ) :
asyncore . dispatcher . __init__ ( self , map = mininode_socket_map )
self . log = logging . getLogger ( " NodeConn( %s : %d ) " % ( dstaddr , dstport ) )
self . dstaddr = dstaddr
@ -1206,6 +1367,7 @@ class NodeConn(asyncore.dispatcher):
@@ -1206,6 +1367,7 @@ class NodeConn(asyncore.dispatcher):
self . network = net
self . cb = callback
self . disconnect = False
self . nServices = 0
# stuff version msg into sendbuf
vt = msg_version ( )