def revert(self, state_container, multi_sig_spend, addresses_state: dict, paginated_tx_hash: PaginatedData, current_block_number: int, threshold: int) -> bool: if not self.executed: return True if self.total_weight < threshold: return False if current_block_number > self.expiry_block_number: return False addresses_state[self.multi_sig_address].update_balance( state_container, multi_sig_spend.total_amount) addr_from_pk = bytes(xrdHelper.getAddress(multi_sig_spend.PK)) for index in range(0, len(multi_sig_spend.addrs_to)): addr_to = multi_sig_spend.addrs_to[index] address_state = addresses_state[addr_to] if addr_to not in (multi_sig_spend.addr_from, addr_from_pk): paginated_tx_hash.remove(address_state, multi_sig_spend.txhash) address_state.update_balance(state_container, multi_sig_spend.amounts[index], subtract=True) self._data.executed = False return True
def _revert_state_changes_for_PK(self, state_container: StateContainer) -> bool: addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) address_state = state_container.addresses_state[addr_from_pk] if self.addr_from != addr_from_pk: state_container.paginated_tx_hash.remove(address_state, self.txhash) address_state.decrease_nonce() state_container.paginated_bitfield.unset_ots_key( state_container.addresses_state, addr_from_pk, self.ots_key) return True
def get_slaves_by_address(self, address: bytes, item_per_page: int, page_number: int): if item_per_page > config.dev.data_per_page or item_per_page == 0: return None slave_hashes = self._load_slave_transaction_hashes(address, item_per_page, page_number) response = xrd_pb2.GetSlavesByAddressResp() for tx_hash in slave_hashes: tx, _ = self._chain_manager.get_tx_metadata(tx_hash) for index in range(0, len(tx.slave_pks)): transaction_detail = xrd_pb2.SlaveDetail(slave_address=bytes(xrdHelper.getAddress(tx.slave_pks[index])), access_type=tx.access_types[index]) response.slaves_detail.extend([transaction_detail]) return response
def revert(self, state: State, state_container: StateContainer) -> bool: address_state = state_container.addresses_state[self.addr_from] address_state.update_balance(state_container, self.fee) state_container.paginated_tx_hash.remove(address_state, self.txhash) if self.addr_to: addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) address_state = state_container.addresses_state[self.addr_to] if self.addr_to not in (self.addr_from, addr_from_pk): state_container.paginated_tx_hash.remove( address_state, self.txhash) state_container.paginated_inbox_message.remove( address_state, self.txhash) return self._revert_state_changes_for_PK(state_container)
def apply(self, state: State, state_container: StateContainer) -> bool: address_state = state_container.addresses_state[self.addr_from] address_state.update_balance(state_container, self.total_amount + self.fee, subtract=True) state_container.paginated_tx_hash.insert(address_state, self.txhash) addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) for index in range(0, len(self.addrs_to)): addr_to = self.addrs_to[index] amount = self.amounts[index] address_state = state_container.addresses_state[addr_to] address_state.update_balance(state_container, amount) if addr_to in (self.addr_from, addr_from_pk): continue state_container.paginated_tx_hash.insert(address_state, self.txhash) return self._apply_state_changes_for_PK(state_container)
def apply(self, state_container, multi_sig_spend, addresses_state: dict, paginated_tx_hash: PaginatedData, current_block_number: int, threshold: int) -> bool: # TODO: return False if executed if self.executed: return True if self.total_weight < threshold: return False if current_block_number > self.expiry_block_number: return False if multi_sig_spend.total_amount > addresses_state[ self.multi_sig_address].balance: logger.info( "[VoteStats] Insufficient funds to execute Multi Sig Spend") logger.info("Multi Sig Spend Amount: %s, Funds Available: %s", multi_sig_spend.total_amount, addresses_state[self.multi_sig_address].balance) logger.info("Multi Sig Spend txn hash: %s", bin2hstr(multi_sig_spend.txhash)) logger.info("Multi Sig Address: %s", bin2hstr(multi_sig_spend.multi_sig_address)) return False addresses_state[self.multi_sig_address].update_balance( state_container, multi_sig_spend.total_amount, subtract=True) addr_from_pk = bytes(xrdHelper.getAddress(multi_sig_spend.PK)) for index in range(0, len(multi_sig_spend.addrs_to)): addr_to = multi_sig_spend.addrs_to[index] address_state = addresses_state[addr_to] if addr_to not in (multi_sig_spend.addr_from, addr_from_pk): paginated_tx_hash.insert(address_state, multi_sig_spend.txhash) address_state.update_balance(state_container, multi_sig_spend.amounts[index]) self._data.executed = True return True
def revert(self, state: State, state_container: StateContainer) -> bool: address_state = state_container.addresses_state[self.addr_from] address_state.update_balance(state_container, self.fee) state_container.paginated_tx_hash.remove(address_state, self.txhash) multi_sig_address = MultiSigAddressState.generate_multi_sig_address(self.txhash) MultiSigAddressState.remove_multi_sig_address_state(state, multi_sig_address, state_container.batch) addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) for index in range(0, len(self.signatories)): signatory = self.signatories[index] address_state = state_container.addresses_state[signatory] if signatory not in (self.addr_from, addr_from_pk): state_container.paginated_tx_hash.remove(address_state, self.txhash) state_container.paginated_multisig_address.remove(address_state, multi_sig_address) if multi_sig_address in state_container.addresses_state: del state_container.addresses_state[multi_sig_address] return self._revert_state_changes_for_PK(state_container)
def apply(self, state: State, state_container: StateContainer) -> bool: address_state = state_container.addresses_state[self.addr_from] address_state.update_balance(state_container, self.fee, subtract=True) state_container.paginated_tx_hash.insert(address_state, self.txhash) multi_sig_address_state = MultiSigAddressState.get_default(self.txhash, self.signatories, self.weights, self.threshold) state_container.addresses_state[multi_sig_address_state.address] = multi_sig_address_state state_container.paginated_tx_hash.insert(multi_sig_address_state, self.txhash) addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) for index in range(0, len(self.signatories)): signatory = self.signatories[index] address_state = state_container.addresses_state[signatory] if signatory not in (self.addr_from, addr_from_pk): state_container.paginated_tx_hash.insert(address_state, self.txhash) state_container.paginated_multisig_address.insert(address_state, multi_sig_address_state.address) return self._apply_state_changes_for_PK(state_container)
def validate_slave(self, state_container: StateContainer) -> bool: addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) master_address = self._get_master_address() allowed_access_types = self._get_allowed_access_types() if self.master_addr == addr_from_pk: logger.warning('Matching master_addr field and address from PK') return False if addr_from_pk != master_address: if (self.addr_from, self.PK) not in state_container.slaves.data: logger.warning("Public key and address doesn't match") return False slave_access_type = state_container.slaves.data[( self.addr_from, self.PK)].access_type if slave_access_type not in allowed_access_types: logger.warning('Access Type %s', slave_access_type) logger.warning( 'Slave Address doesnt have sufficient permission') return False return True
def validate_all(self, state_container: StateContainer, check_nonce=True) -> bool: if self.pbdata.WhichOneof('transactionType') == 'coinbase': if not self._validate_extended(state_container): return False return True if not self.validate(True): # It also calls _validate_custom return False if not self.validate_slave(state_container): return False if not self._validate_extended(state_container): return False addr_from_pk = bytes(xrdHelper.getAddress(self.PK)) addr_from_pk_state = state_container.addresses_state[addr_from_pk] expected_nonce = addr_from_pk_state.nonce + 1 if check_nonce and self.nonce != expected_nonce: logger.warning('nonce incorrect, invalid tx') logger.warning('subtype: %s', self.type) logger.warning('%s actual: %s expected: %s', OptimizedAddressState.bin_to_qaddress(addr_from_pk), self.nonce, expected_nonce) return False if state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( addr_from_pk_state.address, self.ots_key): logger.warning('pubkey reuse detected: invalid tx %s', bin2hstr(self.txhash)) logger.warning('subtype: %s', self.type) return False return True
def GetAddressFromPK(self, request: xrd_pb2.GetAddressFromPKReq, context) -> xrd_pb2.GetAddressFromPKResp: return xrd_pb2.GetAddressFromPKResp( address=bytes(xrdHelper.getAddress(request.pk)))
def addr_from(self): if self.master_addr: return self.master_addr return bytes(xrdHelper.getAddress(self.PK))
def _coinbase_filter(self): if config.dev.coinbase_address in [ bytes(xrdHelper.getAddress(self.PK)), self.master_addr ]: raise ValueError( 'Coinbase Address only allowed to do Coinbase Transaction')
def get_slave(tx): addr_from_pk = bytes(xrdHelper.getAddress(tx.PK)) if addr_from_pk != tx.addr_from: return addr_from_pk return None
def get_addr_from(xmss_pk, master_addr): if master_addr: return master_addr return bytes(xrdHelper.getAddress(xmss_pk))
def test_transferCoins_sign(self): with set_xrd_dir('wallet_ver1'): with State() as db_state: p2p_factory = Mock(spec=P2PFactory) p2p_factory.pow = Mock(spec=POW) chain_manager = ChainManager(db_state) xrdnode = xrdNode(mining_address=b'') xrdnode.set_chain_manager(chain_manager) xrdnode._p2pfactory = p2p_factory xrdnode._pow = p2p_factory.pow xrdnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] service = PublicAPIService(xrdnode) context = Mock(spec=ServicerContext) alice = get_alice_xmss() bob = get_bob_xmss() request = xrd_pb2.TransferCoinsReq( addresses_to=[bob.address], amounts=[101], fee=12, xmss_pk=alice.pk ) response = service.TransferCoins(request=request, context=context) context.set_code.assert_not_called() context.set_details.assert_not_called() self.assertIsNotNone(response) self.assertIsNotNone(response.extended_transaction_unsigned.tx) self.assertEqual('transfer', response.extended_transaction_unsigned.tx.WhichOneof('transactionType')) self.assertEqual(12, response.extended_transaction_unsigned.tx.fee) self.assertEqual(alice.pk, response.extended_transaction_unsigned.tx.public_key) self.assertEqual(0, response.extended_transaction_unsigned.tx.nonce) self.assertEqual(b'', response.extended_transaction_unsigned.tx.signature) self.assertEqual(b'', response.extended_transaction_unsigned.tx.transaction_hash) self.assertEqual(bob.address, response.extended_transaction_unsigned.tx.transfer.addrs_to[0]) self.assertEqual(101, response.extended_transaction_unsigned.tx.transfer.amounts[0]) tmp_hash_pre = bytes(xrdHelper.getAddress(response.extended_transaction_unsigned.tx.public_key)) tmp_hash_pre += str(response.extended_transaction_unsigned.tx.fee).encode() tmp_hash_pre += response.extended_transaction_unsigned.tx.transfer.addrs_to[0] tmp_hash_pre += str(response.extended_transaction_unsigned.tx.transfer.amounts[0]).encode() self.assertEqual('010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c939078' '2a9c61ac02f31320103001d65d7e59aed5efbeae64246e0f3184d7c42411421eb38' '5ba30f2c1c005a85ebc4419cfd313031', bin2hstr(tmp_hash_pre)) tmp_hash = sha256(tmp_hash_pre) self.assertEqual('3645f2819aba65479f9a7fad3f5d7a41a9357410a595fa02fb947bfe3ed96e0f', bin2hstr(tmp_hash)) signed_transaction = response.extended_transaction_unsigned.tx signed_transaction.signature = alice.sign(tmp_hash) req_push = xrd_pb2.PushTransactionReq(transaction_signed=signed_transaction) resp_push = service.PushTransaction(req_push, context=context) context.set_code.assert_not_called() context.set_details.assert_not_called() self.assertIsNotNone(resp_push) self.assertEqual(xrd_pb2.PushTransactionResp.SUBMITTED, resp_push.error_code) self.assertEqual('30955fdc5e2d9dbe5fb9bf812f2e1b6c4b409a8a7c7a75f1c3e9ba1ffdd8e60e', bin2hstr(resp_push.tx_hash))
def set_affected_address(self, addresses_set: set): addresses_set.add(self.addr_from) addresses_set.add(bytes(xrdHelper.getAddress(self.PK)))
def get_address_from_pk(self, pk: str) -> str: return self.address_to_qaddress( xrdHelper.getAddress(bytes(hstr2bin(pk))))