async def sendRawTransaction(self, tx_data): evm_tx = rlp.decode(tx_data, EvmTransaction) tx = Transaction(code=Code.create_evm_code(evm_tx)) success = await self.master.add_transaction(tx) if not success: return "0x" + bytes(32 + 4).hex() return id_encoder(tx.get_hash(), evm_tx.from_full_shard_id)
async def sendTransaction(self, **data): def get_data_default(key, decoder, default=None): if key in data: return decoder(data[key]) return default to = get_data_default("to", recipient_decoder, b"") startgas = get_data_default("gas", quantity_decoder, DEFAULT_STARTGAS) gasprice = get_data_default("gasPrice", quantity_decoder, DEFAULT_GASPRICE) gas_token_id = get_data_default("gasTokenId", quantity_decoder, 0) value = get_data_default("value", quantity_decoder, 0) transfer_token_id = get_data_default("transfer_token_id", quantity_decoder, 0) data_ = get_data_default("data", data_decoder, b"") v = get_data_default("v", quantity_decoder, 0) r = get_data_default("r", quantity_decoder, 0) s = get_data_default("s", quantity_decoder, 0) nonce = get_data_default("nonce", quantity_decoder, None) to_full_shard_id = get_data_default("toFullShardId", full_shard_id_decoder, None) from_full_shard_id = get_data_default("fromFullShardId", full_shard_id_decoder, None) network_id = get_data_default( "networkId", quantity_decoder, self.master.env.quark_chain_config.NETWORK_ID) if nonce is None: raise InvalidParams("Missing nonce") if not (v and r and s): raise InvalidParams("Missing v, r, s") if from_full_shard_id is None: raise InvalidParams("Missing fromFullShardId") if to_full_shard_id is None: to_full_shard_id = from_full_shard_id evm_tx = EvmTransaction( nonce, gasprice, startgas, gas_token_id, to, value, transfer_token_id, data_, v, r, s, from_full_shard_id=from_full_shard_id, to_full_shard_id=to_full_shard_id, network_id=network_id, ) tx = Transaction(code=Code.create_evm_code(evm_tx)) success = await self.master.add_transaction(tx) if not success: return None return id_encoder(tx.get_hash(), from_full_shard_id)
def test_sendTransaction(self): id1 = Identity.create_random_identity() acc1 = Address.create_from_identity(id1, full_shard_key=0) acc2 = Address.create_random_account(full_shard_key=1) with ClusterContext( 1, acc1, small_coinbase=True ) as clusters, jrpc_server_context(clusters[0].master): slaves = clusters[0].slave_list master = clusters[0].master is_root, block = call_async(master.get_next_block_to_mine(address=acc2)) self.assertTrue(is_root) call_async(master.add_root_block(block)) evm_tx = EvmTransaction( nonce=0, gasprice=6, startgas=30000, to=acc2.recipient, value=15, data=b"", from_full_shard_key=acc1.full_shard_key, to_full_shard_key=acc2.full_shard_key, network_id=slaves[0].env.quark_chain_config.NETWORK_ID, gas_token_id=master.env.quark_chain_config.genesis_token, transfer_token_id=master.env.quark_chain_config.genesis_token, ) evm_tx.sign(id1.get_key()) request = dict( to="0x" + acc2.recipient.hex(), gasPrice="0x6", gas=hex(30000), value="0xf", # 15 v=quantity_encoder(evm_tx.v), r=quantity_encoder(evm_tx.r), s=quantity_encoder(evm_tx.s), nonce="0x0", fromFullShardId="0x00000000", toFullShardId="0x00000001", network_id=hex(slaves[0].env.quark_chain_config.NETWORK_ID), ) tx = Transaction(code=Code.create_evm_code(evm_tx)) response = send_request("sendTransaction", [request]) self.assertEqual(response, "0x" + tx.get_hash().hex() + "00000000") self.assertEqual(len(clusters[0].get_shard_state(2 | 0).tx_queue), 1) self.assertEqual( clusters[0].get_shard_state(2 | 0).tx_queue.pop_transaction(), evm_tx )
async def donate(self, from_address, to_address, value=hex(10 ** 18)): """Faucet function to send value (default 1 token) from from_address to to_address. from_address must be one of the addresses in genesis_data/alloc.json. Only allow one pending tx at a time. Return tx id if success else None """ if value > 100 * (10 ** 18): return None key = self.master.env.quark_chain_config.alloc_accounts.get( from_address.hex(), None ) if not key: return None from_address = Address.deserialize(from_address) to_address = Address.deserialize(to_address) # Do nothing if there is already a pending tx result = await self.master.get_transactions_by_address( from_address, bytes(1), 1 ) if result: tx_list, next_token = result if tx_list: return None account_branch_data = await self.master.get_primary_account_data(from_address) nonce = account_branch_data.transaction_count network_id = self.master.env.quark_chain_config.NETWORK_ID evm_tx = EvmTransaction( nonce, 10 ** 9, 30000, to_address.recipient, value, b"", from_full_shard_id=from_address.full_shard_id, to_full_shard_id=to_address.full_shard_id, network_id=network_id, ) evm_tx.sign(key) tx = Transaction(code=Code.create_evm_code(evm_tx)) success = await self.master.add_transaction(tx) if not success: return None return id_encoder(tx.get_hash(), from_address.full_shard_id)
def test_sendTransaction(self): id1 = Identity.create_random_identity() acc1 = Address.create_from_identity(id1, full_shard_id=0) acc2 = Address.create_random_account(full_shard_id=1) with ClusterContext( 1, acc1, small_coinbase=True) as clusters, jrpc_server_context( clusters[0].master): slaves = clusters[0].slave_list branch = Branch.create(2, 0) evm_tx = EvmTransaction( nonce=0, gasprice=6, startgas=30000, to=acc2.recipient, value=15, data=b"", from_full_shard_id=acc1.full_shard_id, to_full_shard_id=acc2.full_shard_id, network_id=slaves[0].env.quark_chain_config.NETWORK_ID, ) evm_tx.sign(id1.get_key()) request = dict( to="0x" + acc2.recipient.hex(), gasPrice="0x6", gas=hex(30000), value="0xf", # 15 v=quantity_encoder(evm_tx.v), r=quantity_encoder(evm_tx.r), s=quantity_encoder(evm_tx.s), nonce="0x0", fromFullShardId="0x00000000", toFullShardId="0x00000001", network_id=hex(slaves[0].env.quark_chain_config.NETWORK_ID), ) tx = Transaction(code=Code.create_evm_code(evm_tx)) response = send_request("sendTransaction", [request]) self.assertEqual(response, "0x" + tx.get_hash().hex() + "00000000") self.assertEqual(len(slaves[0].shards[branch].state.tx_queue), 1) self.assertEqual( slaves[0].shards[branch].state.tx_queue.pop_transaction(), evm_tx)