def test_contract_with_4bit_shard_mask(self): EXPECTED_PAYLOAD = "a12180532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d464c0c8c103e8c2000f42401c0b666f6f2e6261722e62617a066c61756e6368000418c2a33af8bd2cba7fa714a840a308a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75a0251c" mask = BitVector(4) mask.set(3, 1) mask.set(2, 1) # build the payload bytes for the transaction payload = Transaction() payload.from_address = IDENTITIES[0] payload.add_signer(IDENTITIES[0]) payload.charge_rate = 1000 payload.charge_limit = 1000000 payload.valid_from = 100 payload.valid_until = 200 payload.target_chain_code('foo.bar.baz', mask) payload.action = 'launch' # sign the final transaction transaction_bytes = encode_transaction(payload, [ENTITIES[0]]) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx)
def de_stake(self, entity: Entity, amount: int, fee: int): """ Destakes a specific amount of tokens from a staking miner. This will put the tokens in a cool down period :param entity: The entity object that desires to destake :param amount: The amount of tokens to destake :return: The digest of the submitted transaction :raises: ApiError on any failures """ ENDPOINT = 'deStake' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(entity) tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = 'deStake' tx.add_signer(entity) # format the transaction payload tx.data = self._encode_json({ 'address': entity.public_key, 'amount': amount }) # encode and sign the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def collect_stake(self, entity: Entity, fee: int): """ Collect all stakes that have reached the end of the cooldown period :param entity: The entity object that desires to collect :return: The digest of the submitted transaction :raises: ApiError on any failures """ ENDPOINT = 'collectStake' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(entity) tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = 'collectStake' tx.add_signer(entity) # encode and sign the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def transfer(self, entity: Entity, to: AddressLike, amount: int, fee: int): """ Transfers wealth from one account to another account :param private_key_bin: The bytes of the private key of the source address :param to_address: The bytes of the targeted address to send funds to :param amount: The amount of funds being transfered :param fee: The fee associated with the transfer :return: The digest of the submitted transaction :raises: ApiError on any failures """ ENDPOINT = 'transfer' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = Transaction() tx.from_address = Address(entity) tx.valid_until = 10000 tx.charge_rate = 1 tx.charge_limit = fee tx.add_transfer(to, amount) tx.add_signer(entity) # encode and sign the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def wealth(self, entity: Entity, amount: int): """ Creates wealth for specified account :param entity: The entity object to create wealth for :param amount: The amount of wealth to be generated :return: The digest of the submitted transaction :raises: ApiError on any failures """ ENDPOINT = 'wealth' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(1) tx.from_address = Address(entity) tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = 'wealth' tx.add_signer(entity) # format the transaction payload tx.data = self._encode_json({ 'address': entity.public_key, 'amount': amount }) # encode and sign the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def create(self, owner: Entity, contract: 'Contract', fee: int): ENDPOINT = 'create' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(owner) tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = ENDPOINT tx.data = self._encode_json({ 'text': contract.encoded_source, 'digest': contract.digest.to_hex() }) tx.add_signer(owner) # encode and sign the transaction encoded_tx = encode_transaction(tx, [owner]) # update the contracts owner contract.owner = owner # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def create(self, api: ContractsApiLike, owner: Entity, fee: int): # Set contract owner (required for resource prefix) self.owner = owner if self._init is None: raise RuntimeError("Contract has no initialisation function") # Generate resource addresses used by persistent globals try: resource_addresses = [ 'fetch.contract.state.{}'.format(self.digest.to_hex()) ] resource_addresses.extend( ShardMask.state_to_address(address, self) for address in self._parser.used_globals_to_addresses( self._init, [self._owner])) except (UnparsableAddress, UseWildcardShardMask): logging.warning( "Couldn't auto-detect used shards, using wildcard shard mask") shard_mask = BitVector() else: # Generate shard mask from resource addresses shard_mask = ShardMask.resources_to_shard_mask( resource_addresses, api.server.num_lanes()) return self._api(api).create(owner, self, fee, shard_mask=shard_mask)
def test_synergetic_data_submission(self): EXPECTED_PAYLOAD = "a120c0532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d4c1271001c3000000e8d4a5100080da2e9c3191e3768d1c59ea43f6318367ed9b21e6974f46a60d0dd8976740af6de6672a9d98da667e5dc25b2bca8acf9644a7ac0797f01cb5968abf39de011df204646174610f7b2276616c7565223a20313233347d0418c2a33af8bd2cba7fa714a840a308a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75a0251c" # build the payload bytes for the transaction payload = Transaction() payload.from_address = IDENTITIES[0] payload.valid_until = 10000 payload.target_contract(IDENTITIES[3], IDENTITIES[4], BitVector()) payload.charge_rate = 1 payload.charge_limit = 1000000000000 payload.action = 'data' payload.synergetic_data_submission = True payload.data = json.dumps({'value': 1234}).encode('ascii') payload.add_signer(IDENTITIES[0]) # sign the final transaction transaction_bytes = encode_transaction(payload, [ENTITIES[0]]) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx)
def _build_shard_mask(self, num_lanes: int, name: Optional[str], arguments: List[Any]) -> BitVector: try: resource_addresses = [ 'fetch.contract.state.{}'.format(str(self.address)), ] # only process the init functions resources if this function is actually present if name is not None: variables = self._parser.used_globals_to_addresses( name, arguments) for variable in variables: resource_addresses.append( ShardMask.state_to_address(str(self.address), variable)) shard_mask = ShardMask.resources_to_shard_mask( resource_addresses, num_lanes) except (UnparsableAddress, UseWildcardShardMask, EtchParserError, AssertionError) as ex: logging.debug('Parser Error: {}'.format(ex)) logging.warning( "Couldn't auto-detect used shards, using wildcard shard mask") shard_mask = BitVector() return shard_mask
def action(self, contract_digest: Address, contract_address: Address, action: str, fee: int, from_address: Address, signers: EntityList, *args, shard_mask: BitVector = None): # Default to wildcard shard mask if none supplied if not shard_mask: logging.warning( "Defaulting to wildcard shard mask as none supplied") shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(from_address) tx.target_contract(contract_digest, contract_address, shard_mask) tx.action = str(action) tx.data = self._encode_msgpack_payload(*args) for signer in signers: tx.add_signer(signer) encoded_tx = encode_transaction(tx, signers) return self._post_tx_json(encoded_tx, None)
def create(self, owner: Entity, contract: 'Contract', fee: int, shard_mask: BitVector = None): ENDPOINT = 'create' logging.debug('Deploying contract', contract.address) # Default to wildcard shard mask if none supplied if not shard_mask: logging.warning( "Defaulting to wildcard shard mask as none supplied") shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(owner) tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = ENDPOINT tx.data = self._encode_json({ 'nonce': contract.nonce, 'text': contract.encoded_source, 'digest': contract.digest.to_hex() }) tx.add_signer(owner) # encode and sign the transaction encoded_tx = encode_transaction(tx, [owner]) # update the contracts owner contract.owner = owner # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def test_smart_contract(self): EXPECTED_DIGEST = "9ea094e71cbe846192429db3d7e8b02b649730c8b525c3268eb9ff5633c27130" EXPECTED_PAYLOAD = \ "a1604000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d400c103e8c2000f424080" \ "e6672a9d98da667e5dc25b2bca8acf9644a7ac0797f01cb5968abf39de011df2066c61756e636802676f00000000" \ "000000000418c2a33af8bd2cba7fa714a840a308a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c25" \ "8cfd7025a2b9a942770e5b17758bcc4961bbdc75a0251c" # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.add_signer(IDENTITIES[0]) payload.charge_rate = 1000 payload.charge_limit = 1000000 payload.target_contract(Address(IDENTITIES[4]), BitVector()) payload.action = 'launch' payload.data = 'go'.encode('ascii') # sign the final transaction payload.sign(ENTITIES[0]) transaction_bytes = transaction.encode_transaction(payload) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = transaction.decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest self.assertEqual(sha256_hex(payload.encode_payload()), EXPECTED_DIGEST)
def deed(cls, from_address: AddressLike, deed: Optional[Deed], fee: int, signatories: Iterable[Identity]) -> 'Transaction': # TODO: This is known shard_mask = BitVector() tx = cls._create_chain_code_action_tx(fee, from_address, 'deed', signatories, shard_mask) tx.data = cls._encode_json({} if deed is None else deed.to_json()) return tx
def test_sets(self): bits = BitVector(8) bits.set(3, 1) bits.set(6, 1) bits.set(7, 1) self.assertEqual(len(bits), 8) self.assertEqual(bits.byte_length, 1) self.assertEqual(bits.as_hex(), 'c8')
def test_gets(self): bits = BitVector.from_hex_string('c8') self.assertEqual(bits.get(0), 0) self.assertEqual(bits.get(1), 0) self.assertEqual(bits.get(2), 0) self.assertEqual(bits.get(3), 1) self.assertEqual(bits.get(4), 0) self.assertEqual(bits.get(5), 0) self.assertEqual(bits.get(6), 1) self.assertEqual(bits.get(7), 1)
def _construct_gov_tx(cls, tx_endpoint: str, from_address: Address, fee: int, signatories: Iterable[Identity], proposal: GovernanceProposal) -> 'Transaction': shard_mask = BitVector() tx = cls._create_chain_code_action_tx(fee, from_address, tx_endpoint, signatories, shard_mask) tx.data = base64.b64encode(cls._encode_json(proposal.to_dict())) return tx
def test_contract_with_4bit_shard_mask(self): EXPECTED_DIGEST = "7915d6393fb07dbb4ff6896ef0f57025e5153b744d3a652b0f4815f129a9033c" EXPECTED_PAYLOAD = \ "a1418000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d464c0c8c103e8c2000f42" \ "401c0b666f6f2e6261722e62617a066c61756e63680000000000000000000418c2a33af8bd2cba7fa714a840a308" \ "a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75" \ "a0251c" mask = BitVector(4) mask.set(3, 1) mask.set(2, 1) # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.add_signer(IDENTITIES[0]) payload.charge_rate = 1000 payload.charge_limit = 1000000 payload.valid_from = 100 payload.valid_until = 200 payload.target_chain_code('foo.bar.baz', mask) payload.action = 'launch' # sign the final transaction transaction_bytes = encode_transaction(payload, [ENTITIES[0]]) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest buffer = io.BytesIO() encode_payload(buffer, payload) self.assertEqual(sha256_hash(buffer.getvalue()), EXPECTED_DIGEST)
def test_contract_with_4bit_shard_mask(self): EXPECTED_DIGEST = "e1ac018356792e492aaac92bf6928af1e47ed987761b81cafb51f1106f403eee" EXPECTED_PAYLOAD = \ "a1618000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d464c0c8c103e8c2000f42" \ "401c0b666f6f2e6261722e62617a066c61756e63680000000000000000000418c2a33af8bd2cba7fa714a840a308" \ "a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75" \ "a0251c" mask = BitVector(4) mask.set(3, 1) mask.set(2, 1) # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.add_signer(IDENTITIES[0]) payload.charge_rate = 1000 payload.charge_limit = 1000000 payload.valid_from = 100 payload.valid_until = 200 payload.target_chain_code('foo.bar.baz', mask) payload.action = 'launch' # sign the final transaction payload.sign(ENTITIES[0]) transaction_bytes = transaction.encode_transaction(payload) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = transaction.decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest self.assertEqual(sha256_hex(payload.encode_payload()), EXPECTED_DIGEST)
def de_stake(cls, identity: Identity, amount: int, fee: int, signatories: Iterable[Identity]) -> 'Transaction': # build up the basic transaction information tx = cls._create_chain_code_action_tx(fee, identity, 'deStake', signatories, BitVector()) # format the transaction payload tx.data = cls._encode_json({ 'address': identity.public_key, 'amount': amount }) return tx
def resources_to_shard_mask(cls, resource_addresses: Iterable[str], num_lanes: int) -> BitVector: """ Converts a set resources addresses into a compatible shard mask :param resource_addresses: The iterable set of fully qualified resource addresses :param num_lanes: The number of lanes that are being targeted :return: The shard mask bit vector for shard allocation """ shards = [ cls.resource_to_shard(ra, num_lanes) for ra in resource_addresses ] return BitVector.from_indices(shards, num_lanes)
def submit_data(self, entity: Entity, contract_address: Address, fee: int, **kwargs): # build up the basic transaction information tx = self._create_skeleton_tx(fee) self._set_validity_period(tx) tx.from_address = Address(entity) tx.target_synergetic_data(contract_address, BitVector()) tx.action = 'data' tx.data = self._encode_json(dict(**kwargs)) tx.add_signer(entity) tx.sign(entity) # encode the transaction encoded_tx = transaction.encode_transaction(tx) # submit the transaction to the catch-all endpoint return self._post_tx_json(encoded_tx, None)
def action(self, contract_digest: Address, contract_owner: Address, action: str, fee: int, signers: EntityList, *args): shard_mask = BitVector() # build up the basic transaction information tx = self._create_skeleton_tx(fee) tx.from_address = Address(contract_owner) tx.target_contract(contract_digest, contract_owner, shard_mask) tx.action = str(action) tx.data = self._encode_msgpack_payload(*args) for signer in signers: tx.add_signer(signer) encoded_tx = encode_transaction(tx, signers) return self._post_tx_json(encoded_tx, None)
def create(cls, from_address: AddressLike, contract: 'Contract', fee: int, signatories: Iterable[Identity], shard_mask: Optional[BitVector] = None) -> Transaction: # Default to wildcard shard mask if none supplied if not shard_mask: logging.warning("Defaulting to wildcard shard mask as none supplied") shard_mask = BitVector() # build up the basic transaction information tx = cls._create_chain_code_action_tx(fee, from_address, 'create', signatories, shard_mask) tx.data = cls._encode_json({ 'nonce': contract.nonce, 'text': contract.encoded_source, 'digest': contract.digest, }) return tx
def submit_data(self, entity: Entity, digest: Address, **kwargs): # build up the basic transaction information tx = Transaction() tx.from_address = Address(entity) tx.valid_until = 10000 tx.target_contract(digest, Address(entity), BitVector()) tx.charge_rate = 1 tx.charge_limit = 1000000000000 tx.action = 'data' tx.synergetic_data_submission = True tx.data = self._encode_json(dict(**kwargs)) tx.add_signer(entity) # encode the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction to the catch-all endpoint return self._post_tx_json(encoded_tx, None)
def action(cls, from_address: Address, contract_address: Address, action: str, fee: int, signers: List[Identity], *args, shard_mask: Optional[BitVector] = None) -> Transaction: # Default to wildcard shard mask if none supplied if not shard_mask: logging.warning("Defaulting to wildcard shard mask as none supplied") shard_mask = BitVector() # select the from address if from_address is None: if len(signers) == 1: from_address = Address(signers[0]) else: raise RuntimeError('Unable to determine from field for transaction, more than 1 signer provided') # build up the basic transaction information tx = cls._create_smart_contract_action_tx(fee, from_address, contract_address, action, signers, shard_mask) tx.data = cls._encode_msgpack_payload(*args) return tx
def test_synergetic_data_submission(self): EXPECTED_DIGEST = "9397fd490b60a394ea0af5526435608a1e853e2cb6b09bc7cafec8f6a0aa2cf6" EXPECTED_PAYLOAD = \ "a140c000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d4c1271001c3000000e8d4" \ "a5100080da2e9c3191e3768d1c59ea43f6318367ed9b21e6974f46a60d0dd8976740af6de6672a9d98da667e5dc2" \ "5b2bca8acf9644a7ac0797f01cb5968abf39de011df204646174610f7b2276616c7565223a20313233347d000000" \ "00000000000418c2a33af8bd2cba7fa714a840a308a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c" \ "258cfd7025a2b9a942770e5b17758bcc4961bbdc75a0251c" # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.valid_until = 10000 payload.target_contract(IDENTITIES[3], IDENTITIES[4], BitVector()) payload.charge_rate = 1 payload.charge_limit = 1000000000000 payload.action = 'data' payload.synergetic_data_submission = True payload.data = json.dumps({'value': 1234}).encode('ascii') payload.add_signer(IDENTITIES[0]) # sign the final transaction transaction_bytes = encode_transaction(payload, [ENTITIES[0]]) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest buffer = io.BytesIO() encode_payload(buffer, payload) self.assertEqual(sha256_hash(buffer.getvalue()), EXPECTED_DIGEST)
def test_action(self, mock_shard_mask): # create contract owner = Entity() contract = Contract(CONTRACT_TEXT, owner) # Mock api for providing number of lanes and receiving create call api = mock.Mock(spec=LedgerApi) api.server = mock.Mock() lane_number = 2 api.server.num_lanes.side_effect = [lane_number] api.contracts = mock.Mock(spec=ContractsApi) # Mock shard mask static method dummy_shard_mask = mock.Mock() mock_shard_mask.side_effect = [dummy_shard_mask] contract.action(api, 'action1', 1000, owner, 'arg1', 'arg2') # Check shard mask gen called with contract digest address base_contract_address = 'fetch.contract.state.{}'.format( str(contract.address)) expected_resources = [ base_contract_address, '{}.value_.arg1'.format(base_contract_address), '{}.value_.arg2'.format(base_contract_address), ] # TODO: Due to parser errors the contract can not correctly distinguish the bit vectors. This means a wild card # bit vector is used. #mock_shard_mask.assert_called_once_with(expected_resources, lane_number) # Check api create method called api.contracts.action.assert_called_once_with(contract.address, 'action1', 1000, owner, 'arg1', 'arg2', shard_mask=BitVector())
def wealth(self, entity: Entity, amount: int): """ Creates wealth for specified account :param private_key_bin: The bytes of the private key of the targeted address :param amount: The amount of wealth to be generated :param fee: The fee value to be used for the transaction :return: The digest of the submitted transaction :raises: ApiError on any failures """ ENDPOINT = 'wealth' # format the data to be closed by the transaction # wildcard for the moment shard_mask = BitVector() # build up the basic transaction information tx = Transaction() tx.from_address = Address(entity) tx.valid_until = 10000 tx.charge_rate = 1 tx.charge_limit = 10 tx.target_chain_code(self.API_PREFIX, shard_mask) tx.action = 'wealth' tx.add_signer(entity) # format the transaction payload tx.data = self._encode_json({ 'address': entity.public_key, 'amount': amount }) # encode and sign the transaction encoded_tx = encode_transaction(tx, [entity]) # submit the transaction return self._post_tx_json(encoded_tx, ENDPOINT)
def test_synergetic_data_submission(self): EXPECTED_DIGEST = "261ba516c9b7b4d3ecb39f349dbb0a35db0d9fc362f2b9cc81c7d844be4d0081" EXPECTED_PAYLOAD = \ "a160c000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d4c1271001c3000000e8d4" \ "a5100080e6672a9d98da667e5dc25b2bca8acf9644a7ac0797f01cb5968abf39de011df204646174610f7b227661" \ "6c7565223a20313233347d00000000000000000418c2a33af8bd2cba7fa714a840a308a217aa4483880b1ef14b4f" \ "dffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75a0251c" # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.valid_until = 10000 payload.target_synergetic_data(Address(IDENTITIES[4]), BitVector()) payload.charge_rate = 1 payload.charge_limit = 1000000000000 payload.action = 'data' payload.data = json.dumps({'value': 1234}).encode('ascii') payload.add_signer(IDENTITIES[0]) # sign the final transaction payload.sign(ENTITIES[0]) transaction_bytes = transaction.encode_transaction(payload) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = transaction.decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest self.assertEqual(sha256_hex(payload.encode_payload()), EXPECTED_DIGEST)
def test_chain_code(self): EXPECTED_DIGEST = "25cc72ca7d4871aaaabd027af129ecd4327adde5ec0c9977bfe11018d4bab64a" EXPECTED_PAYLOAD = \ "a1608000532398dd883d1990f7dad3fde6a53a53347afc2680a04748f7f15ad03cadc4d400c103e8c2000f424080" \ "0b666f6f2e6261722e62617a066c61756e636802676f00000000000000000418c2a33af8bd2cba7fa714a840a308" \ "a217aa4483880b1ef14b4fdffe08ab956e3f4b921cec33be7c258cfd7025a2b9a942770e5b17758bcc4961bbdc75" \ "a0251c" # build the payload bytes for the transaction with mock.patch('random.getrandbits') as mock_counter: mock_counter.side_effect = [0] payload = Transaction() payload.from_address = IDENTITIES[0] payload.add_signer(IDENTITIES[0]) payload.charge_rate = 1000 payload.charge_limit = 1000000 payload.target_chain_code('foo.bar.baz', BitVector()) payload.action = 'launch' payload.data = 'go'.encode('ascii') # sign the final transaction payload.sign(ENTITIES[0]) transaction_bytes = transaction.encode_transaction(payload) self.assertIsExpectedTx(payload, transaction_bytes, EXPECTED_PAYLOAD) # attempt to decode a transaction from the generated bytes buffer = io.BytesIO(transaction_bytes) success, tx = transaction.decode_transaction(buffer) self.assertTrue(success) self.assertTxAreEqual(payload, tx) # Check payload digest self.assertEqual(sha256_hex(payload.encode_payload()), EXPECTED_DIGEST)