def parse(cls, s, version_msg=False): # Documentation says that the `time` field ins't present in version messages ... if version_msg: time = None else: time = little_endian_to_int(s.read(4)) services = little_endian_to_int(s.read(8)) ip = little_endian_to_int(s.read(16)) port = little_endian_to_int(s.read(2)) return cls(services, ip, port, time)
def parse(cls, s): version = little_endian_to_int(s.read(4)) #prev_block = s.read(32)[::-1] # little endian prev_block = little_endian_to_int(s.read(32)) #merkle_root = s.read(32)[::-1] # little endian merkle_root = little_endian_to_int(s.read(32)) timestamp = little_endian_to_int(s.read(4)) bits = s.read(4) nonce = s.read(4) txn_count = read_varint(s) # apparently this is always 0? return cls(version, prev_block, merkle_root, timestamp, bits, nonce, txn_count)
def parse(cls, s): '''Takes a byte stream and parses the tx_input at the start return a TxIn object ''' # s.read(n) will return n bytes # prev_tx is 32 bytes, little endian prev_tx = s.read(32)[::-1] # prev_index is 4 bytes, little endian, interpret as int prev_index = little_endian_to_int(s.read(4)) # script_sig is a variable field (length followed by the data) # get the length by using read_varint(s) script_sig_length = read_varint(s) script_sig = s.read(script_sig_length) # sequence is 4 bytes, little-endian, interpret as int sequence = little_endian_to_int(s.read(4)) # return an instance of the class (cls(...)) return cls(prev_tx, prev_index, script_sig, sequence)
def target(self): '''Returns the proof-of-work target based on the bits''' # last byte is exponent exponent = self.bits[-1] # the first three bytes are the coefficient in little endian coefficient = little_endian_to_int(self.bits[:-1]) # the formula is: # coefficient * 2**(8*(exponent-3)) return coefficient * 2**(8 * (exponent - 3))
async def read_message(reader): magic = await reader.read(4) if magic != NETWORK_MAGIC: raise RuntimeError("Network Magic not at beginning of stream") command = await reader.read(12) payload_length = little_endian_to_int(await reader.read(4)) checksum = await reader.read(4) payload = await reader.read(payload_length) if double_sha256(payload)[:4] != checksum: raise RuntimeError("Payload and Checksum do not match") return Message(command, payload)
def parse(cls, s): '''Takes a byte stream and parses the tx_output at the start return a TxOut object ''' # s.read(n) will return n bytes # amount is 8 bytes, little endian, interpret as int amount = little_endian_to_int(s.read(8)) # script_pubkey is a variable field (length followed by the data) # get the length by using read_varint(s) script_pubkey_length = read_varint(s) script_pubkey = s.read(script_pubkey_length) # return an instance of the class (cls(...)) return cls(amount, script_pubkey)
def parse(cls, s): '''Takes a byte stream and parses the transaction at the start return a Tx object ''' # s.read(n) will return n bytes # version has 4 bytes, little-endian, interpret as int version = little_endian_to_int(s.read(4)) # num_inputs is a varint, use read_varint(s) num_inputs = read_varint(s) # each input needs parsing 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) # each output needs parsing outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parse(s)) # locktime is 4 bytes, little-endian locktime = little_endian_to_int(s.read(4)) # return an instance of the class (cls(...)) return cls(version, inputs, outputs, locktime)
def parse(cls, s): version = little_endian_to_int(s.read(4)) services = little_endian_to_int(s.read(8)) timestamp = little_endian_to_int(s.read(8)) addr_recv = Address.parse(io.BytesIO(s.read(26)), version_msg=True) addr_from = Address.parse(io.BytesIO(s.read(26)), version_msg=True) nonce = little_endian_to_int(s.read(8)) user_agent = read_varstr( s) # Should we convert stuff like to to strings? start_height = little_endian_to_int(s.read(4)) relay = little_endian_to_int(s.read(1)) return cls(version, services, timestamp, addr_recv, addr_from, nonce, user_agent, start_height, relay)
def parse(cls, s): magic = consume_stream(s, 4) if magic != NETWORK_MAGIC: raise ValueError('magic is not right') command = parse_command(consume_stream(s, 12)) payload_length = little_endian_to_int(consume_stream(s, 4)) checksum = consume_stream(s, 4) payload = consume_stream(s, payload_length) calculated_checksum = double_sha256(payload)[:4] if calculated_checksum != checksum: raise RuntimeError('checksum does not match') if payload_length != len(payload): raise RuntimeError( "Tried to read {payload_length} bytes, only received {len(payload)} bytes" ) return cls(command, payload)
def pow(self): s = self.serialize() sha = double_sha256(s) return little_endian_to_int(sha)
def parse(cls, s): type_ = little_endian_to_int(s.read(4)) hash_ = s.read(32) return cls(type_, hash_)