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 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 hash(self): '''Returns the double_sha256 interpreted little endian of the block''' # serialize s = self.serialize() # double_sha256 h256 = double_sha256(s) # reverse return h256[::-1]
def serialize(self): '''Returns the byte serialization of the entire network message''' # add the network magic result = self.magic # command 12 bytes # fill with 0's result += self.command + b'\x00' * (12 - len(self.command)) # payload length 4 bytes, little endian result += int_to_little_endian(len(self.payload), 4) # checksum 4 bytes, first four of hash256 of payload result += double_sha256(self.payload)[:4] # payload result += self.payload return result
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 sig_hash(self, input_index, script_pubkey, redeem_script=None): # FIXME: DELETE '''Returns the byte serialization of the transaction''' '''Returns the integer representation of the hash that needs to get signed for index input_index''' # start the serialization with version # use int_to_little_endian in 4 bytes s = int_to_little_endian(self.version, 4) # add how many inputs there are using serialize_varint s += serialize_varint(len(self.tx_ins)) # loop through each input using enumerate, so we have the input index for i, tx_in in enumerate(self.tx_ins): # if the input index is the one we're signing if i == input_index: # if the RedeemScript was passed in, that's the ScriptSig # otherwise the previous tx's ScriptPubkey is the ScriptSig # script_sig = tx_in.script_pubkey(self.testnet) script_sig = script_pubkey # Otherwise, the ScriptSig is empty else: script_sig = None # add the serialization of the input with the ScriptSig we want s += TxIn( prev_tx=tx_in.prev_tx, prev_index=tx_in.prev_index, script_sig=script_sig, sequence=tx_in.sequence, ).serialize() # add how many outputs there are using serialize_varint s += serialize_varint(len(self.tx_outs)) # add the serialization of each output for tx_out in self.tx_outs: s += tx_out.serialize() # add the locktime using int_to_little_endian in 4 bytes s += int_to_little_endian(self.locktime, 4) # add SIGHASH_ALL using int_to_little_endian in 4 bytes s += int_to_little_endian(SIGHASH_ALL, 4) # double_sha256 the serialization h256 = double_sha256(s) # convert the result to an integer using int.from_bytes(x, 'big') return int.from_bytes(h256, 'big')
def hash(self): '''Binary hash of the legacy serialization''' return double_sha256(self.serialize())[::-1]
def op_hash256(stack): if len(stack) < 1: return False element = stack.pop() stack.append(double_sha256(element)) return True