def parse(cls, s): '''Takes a byte stream and parses the tx_input at the start return a TxIn object ''' # prev_tx is 32 bytes, little endian prev_tx = s.read(32)[::-1] # prev_index is an integer in 4 bytes, little endian prev_index = little_endian_to_int(s.read(4)) # use Script.parse to get the ScriptSig script_sig = Script.parse(s) # sequence is an integer in 4 bytes, little-endian sequence = little_endian_to_int(s.read(4)) # return an instance of the class (see __init__ for args) return cls(prev_tx, prev_index, script_sig, sequence)
def parse(cls, s): '''Takes a stream and creates a NetworkEnvelope''' # check the network magic magic = s.read(4) if magic == b'': raise RuntimeError('Connection reset!') if magic != NETWORK_MAGIC: raise RuntimeError('magic is not right {} vs {}'.format( magic.hex(), NETWORK_MAGIC.hex())) # command 12 bytes command = s.read(12) # strip the trailing 0's command = command.strip(b'\x00') # payload length 4 bytes, little endian payload_length = little_endian_to_int(s.read(4)) # checksum 4 bytes, first four of hash256 of payload checksum = s.read(4) # payload is of length payload_length payload = s.read(payload_length) # verify checksum calculated_checksum = double_sha256(payload)[:4] if calculated_checksum != checksum: raise RuntimeError('checksum does not match') # return an instance of the class return cls(command, payload)
def parse(cls, s): '''Takes a byte stream and parses a block. Returns a Block object''' # s.read(n) will read n bytes from the stream # version - 4 bytes, little endian, interpret as int version = little_endian_to_int(s.read(4)) # prev_block - 32 bytes, little endian (use [::-1] to reverse) prev_block = s.read(32)[::-1] # merkle_root - 32 bytes, little endian (use [::-1] to reverse) merkle_root = s.read(32)[::-1] # timestamp - 4 bytes, little endian, interpret as int timestamp = little_endian_to_int(s.read(4)) # bits - 4 bytes bits = s.read(4) # nonce - 4 bytes nonce = s.read(4) # initialize class return cls(version, prev_block, merkle_root, timestamp, bits, nonce)
def check_pow(self): '''Returns whether this block satisfies proof of work''' # get the double_sha256 of the serialization of this block h256 = double_sha256(self.serialize()) # interpret this hash as a little-endian number proof = little_endian_to_int(h256) # return whether this integer is less than the target return proof < self.target()
def parse(cls, s): '''Takes a byte stream and parses the tx_output at the start return a TxOut object ''' # amount is an integer in 8 bytes, little endian amount = little_endian_to_int(s.read(8)) # use Script.parse to get the ScriptPubKey script_pubkey = Script.parse(s) # return an instance of the class (see __init__ for args) return cls(amount, script_pubkey)
def mine(block): target = bits_to_target(block.bits) nonce = 0 serialized_block = block.serialize() nonce_index = 76 while True: ser = serialized_block[:76] + int_to_little_endian( nonce, 4) + serialized_block[80:] proof = little_endian_to_int(double_sha256(ser)) if proof < target: block.nonce = int_to_little_endian(nonce, 4) return block else: nonce += 1
def parse(cls, s, testnet=False): '''Takes a byte stream and parses the transaction at the start return a Tx object ''' # s.read(n) will return n bytes # version is an integer in 4 bytes, little-endian version = little_endian_to_int(s.read(4)) # num_inputs is a varint, use read_varint(s) num_inputs = read_varint(s) # parse num_inputs number of TxIns inputs = [] for _ in range(num_inputs): inputs.append(TxIn.parse(s)) # num_outputs is a varint, use read_varint(s) num_outputs = read_varint(s) # parse num_outputs number of TxOuts outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parse(s)) # locktime is an integer in 4 bytes, little-endian locktime = little_endian_to_int(s.read(4)) # return an instance of the class (see __init__ for args) return cls(version, inputs, outputs, locktime, testnet=testnet)
def mine(block): while not block.check_pow(): block.nonce = int_to_little_endian( little_endian_to_int(block.nonce) + 1, 4) return block