Esempio n. 1
0
 def filterload(self, flag=1):
     payload = encode_varint(self.size)
     payload += self.filter_bytes()
     payload += int_to_little_endian(self.function_count, 4)
     payload += int_to_little_endian(self.tweak, 4)
     payload += int_to_little_endian(flag, 1)
     return GenericMessage(b'filterload', payload)
 def serialize(self):
     # get the raw serialization (no prepended length)
     result = self.raw_serialize()
     # get the length of the whole thing
     total = len(result)
     # encode_varint the total length of the result and prepend
     return encode_varint(total) + result
 def serialize(self):
     '''Serialize this message to send over the network'''
     # version is 4 bytes little endian
     result = int_to_little_endian(self.version, 4)
     # services is 8 bytes little endian
     result += int_to_little_endian(self.services, 8)
     # timestamp is 8 bytes little endian
     result += int_to_little_endian(self.timestamp, 8)
     # receiver services is 8 bytes little endian
     result += int_to_little_endian(self.receiver_services, 8)
     # IPV4 is 10 00 bytes and 2 ff bytes then receiver ip
     result += b'\x00' * 10 + b'\xff\xff' + self.receiver_ip
     # receiver port is 2 bytes, big endian
     result += self.receiver_port.to_bytes(2, 'big')
     # sender services is 8 bytes little endian
     result += int_to_little_endian(self.sender_services, 8)
     # IPV4 is 10 00 bytes and 2 ff bytes then sender ip
     result += b'\x00' * 10 + b'\xff\xff' + self.sender_ip
     # sender port is 2 bytes, big endian
     result += self.sender_port.to_bytes(2, 'big')
     # nonce should be 8 bytes
     result += self.nonce
     # useragent is a variable string, so varint first
     result += encode_varint(len(self.user_agent))
     result += self.user_agent
     # latest block is 4 bytes little endian
     result += int_to_little_endian(self.latest_block, 4)
     # relay is 00 if false, 01 if true
     if self.relay:
         result += b'\x01'
     else:
         result += b'\x00'
     return result
 def evaluate(self, z, witness):
     # create a copy as we may need to add to this list if we have a
     # RedeemScript
     cmds = self.cmds[:]
     stack = []
     altstack = []
     while len(cmds) > 0:
         cmd = cmds.pop(0)
         if type(cmd) == int:
             # do what the opcode says
             operation = OP_CODE_FUNCTIONS[cmd]
             if cmd in (99, 100):
                 # op_if/op_notif require the cmds array
                 if not operation(stack, cmds):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (107, 108):
                 # op_toaltstack/op_fromaltstack require the altstack
                 if not operation(stack, altstack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (172, 173, 174, 175):
                 # these are signing operations, they need a sig_hash
                 # to check against
                 if not operation(stack, z):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             else:
                 if not operation(stack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
         else:
             # add the cmd to the stack
             stack.append(cmd)
             # p2sh rule. if the next three cmds are:
             # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript
             # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87
             if len(cmds) == 3 and cmds[0] == 0xa9 \
                 and type(cmds[1]) == bytes and len(cmds[1]) == 20 \
                 and cmds[2] == 0x87:
                 redeem_script = encode_varint(len(cmd)) + cmd
                 # we execute the next three opcodes
                 cmds.pop()
                 h160 = cmds.pop()
                 cmds.pop()
                 if not op_hash160(stack):
                     return False
                 stack.append(h160)
                 if not op_equal(stack):
                     return False
                 # final result should be a 1
                 if not op_verify(stack):
                     LOGGER.info('bad p2sh h160')
                     return False
                 # hashes match! now add the RedeemScript
                 redeem_script = encode_varint(len(cmd)) + cmd
                 stream = BytesIO(redeem_script)
                 cmds.extend(Script.parse(stream).cmds)
             # witness program version 0 rule. if stack cmds are:
             # 0 <20 byte hash> this is p2wpkh
             # tag::source3[]
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20:  # <1>
                 h160 = stack.pop()
                 stack.pop()
                 cmds.extend(witness)
                 cmds.extend(p2pkh_script(h160).cmds)
             # end::source3[]
             # witness program version 0 rule. if stack cmds are:
             # 0 <32 byte hash> this is p2wsh
             # tag::source6[]
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32:
                 s256 = stack.pop()  # <1>
                 stack.pop()  # <2>
                 cmds.extend(witness[:-1])  # <3>
                 witness_script = witness[-1]  # <4>
                 if s256 != sha256(witness_script):  # <5>
                     print('bad sha256 {} vs {}'.format
                         (s256.hex(), sha256(witness_script).hex()))
                     return False
                 stream = BytesIO(encode_varint(len(witness_script))
                     + witness_script)
                 witness_script_cmds = Script.parse(stream).cmds  # <6>
                 cmds.extend(witness_script_cmds)
             # end::source6[]
     if len(stack) == 0:
         return False
     if stack.pop() == b'':
         return False
     return True
 def serialize(self):
     result = encode_varint(len(self.data))
     for data_type, identifier in self.data:
         result += int_to_little_endian(data_type, 4)
         result += identifier[::-1]
     return result
 def serialize(self):
     result = int_to_little_endian(self.version, 4)
     result += encode_varint(self.num_hashes)
     result += self.start_block[::-1]
     result += self.end_block[::-1]
     return result