コード例 #1
0
ファイル: test_transaction.py プロジェクト: WorldBosss1/fhi-
    def setUp(self) -> None:
        self.source_identity = Entity()
        self.multi_sig_identity = Entity()
        self.multi_sig_board = [Entity() for _ in range(4)]
        self.target_identity = Entity()

        self.tx = TokenTxFactory.transfer(self.source_identity, Identity(self.target_identity),
                                          500, 500, [self.source_identity])
        self.mstx = TokenTxFactory.transfer(self.multi_sig_identity, Identity(self.target_identity),
                                            500, 500, self.multi_sig_board)
コード例 #2
0
    def get_transfer_transaction(  # pylint: disable=arguments-differ
        self,
        sender_address: Address,
        destination_address: Address,
        amount: int,
        tx_fee: int,
        tx_nonce: str,
        **kwargs,
    ) -> Optional[Any]:
        """
        Submit a transfer transaction to the ledger.

        :param sender_address: the sender address of the payer.
        :param destination_address: the destination address of the payee.
        :param amount: the amount of wealth to be transferred.
        :param tx_fee: the transaction fee.
        :param tx_nonce: verifies the authenticity of the tx
        :return: the transfer transaction
        """
        tx = TokenTxFactory.transfer(
            FetchaiAddress(sender_address),
            FetchaiAddress(destination_address),
            amount,
            tx_fee,
            [],  # we don't add signer here as we would need the public key for this
        )
        self._api.set_validity_period(tx)
        return tx
コード例 #3
0
 def test_handle_tx_signing_fetchai(self):
     """Test tx signing for fetchai."""
     tx = TokenTxFactory.transfer(
         FetchaiAddress("v3sZs7gKKz9xmoTo9yzRkfHkjYuX42MzXaq4eVjGHxrX9qu3U"),
         FetchaiAddress("2bzQNV4TTjMAiKZe85EyLUttoFpHHuksRzUUBYB1brt98pMXKK"),
         1,
         1,
         [],
     )
     signing_dialogues = SigningDialogues("agent1")
     signing_msg = SigningMessage(
         performative=SigningMessage.Performative.SIGN_TRANSACTION,
         dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(),
         skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),),
         skill_callback_info={},
         terms=Terms(
             ledger_id=FETCHAI,
             sender_address="pk1",
             counterparty_address="pk2",
             amount_by_currency_id={"FET": -1},
             is_sender_payable_tx_fee=True,
             quantities_by_good_id={"good_id": 10},
             nonce="transaction nonce",
         ),
         raw_transaction=RawTransaction(FETCHAI, tx),
     )
     signing_msg.counterparty = "decision_maker"
     self.decision_maker.message_in_queue.put_nowait(signing_msg)
     signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2)
     assert (
         signing_msg_response.performative
         == SigningMessage.Performative.SIGNED_TRANSACTION
     )
     assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids
     assert type(signing_msg_response.signed_transaction.body) == FetchaiTransaction
コード例 #4
0
def run_transfer(args):
    from getpass import getpass

    from fetchai.ledger.crypto import Address
    from fetchai.ledger.api.token import TokenTxFactory

    from pocketbook.address_book import AddressBook
    from pocketbook.key_store import KeyStore
    from pocketbook.utils import create_api, from_canonical, token_amount

    address_book = AddressBook()
    key_store = KeyStore()

    # choose the destination
    destination_name = '{}:'.format(args.destination)
    if args.destination in address_book.keys():
        destination = address_book.lookup_address(args.destination)
    else:
        destination = key_store.lookup_address(args.destination)
        if destination is None:
            destination = Address(args.destination)
            destination_name = ''

    # convert the amount
    amount = args.amount
    charge_rate = args.charge_rate
    computed_amount = from_canonical(amount)

    # check all the signers make sense
    for signer in args.signers:
        if signer not in key_store.list_keys():
            raise RuntimeError('Unknown key: {}'.format(signer))

    # determine the from account
    from_address_name = None
    if len(args.signers) == 1 and args.from_address is None:
        from_address_name = args.signers[0]
    elif len(args.signers) >= 1 and args.from_address is not None:
        present = args.from_address in key_store.list_keys() or args.from_address in address_book.keys()
        from_address_name = args.from_address
        if not present:
            raise RuntimeError('Unknown from address: {}'.format(args.from_address))
    else:
        raise RuntimeError('Unable to determine from account')

    required_ops = len(args.signers)
    fee = required_ops * charge_rate
    computed_fee = from_canonical(fee)
    computed_total = computed_amount + computed_fee
    computed_charge_rate = from_canonical(charge_rate)

    print('Network....:', args.network)
    print('From.......:', str(from_address_name))
    print('Signer(s)..:', ','.join(args.signers))
    print('Destination:', destination_name, str(destination))
    print('Amount.....:', token_amount(computed_amount))
    print('Fee........:', token_amount(computed_fee))

    # only display extended fee information if something other than the default it selected
    if charge_rate != 1:
        print('           : {} ops @ {}'.format(required_ops, token_amount(computed_charge_rate)))

    print('Total......:', token_amount(computed_total), '(Amount + Fee)')
    print()
    input('Press enter to continue')

    api = create_api(args.network)

    # start unsealing the private keys
    entities = {}
    for signer in args.signers:
        entity = key_store.load_key(signer, getpass('Enter password for key {}: '.format(signer)))
        entities[signer] = entity

    from_address = None
    if from_address_name in entities:
        from_address = Address(entities[from_address_name])
    elif from_address_name in address_book.keys():
        from_address = Address(address_book.lookup_address(from_address_name))

    # cache the signers
    signers = list(entities.values())

    # build up the basic transaction information
    tx = TokenTxFactory.transfer(Address(from_address), destination, amount, 0, signers)
    tx.charge_rate = charge_rate
    tx.charge_limit = required_ops
    api.set_validity_period(tx)
    for entity in signers:
        tx.sign(entity)

    tx_digest = api.submit_signed_tx(tx)
    print('TX: 0x{} submitted'.format(tx_digest))

    # submit the transaction
    print('Waiting for transaction to be confirmed...')
    api.sync(tx_digest)
    print('Waiting for transaction to be confirmed...complete')

    # determine if there is a block explorer link to be printed
    explorer_link = None
    if args.network == 'mainnet':
        explorer_link = 'https://explore.fetch.ai/transactions/0x{}'.format(tx_digest)
    elif args.network == 'testnet':
        explorer_link = 'https://explore-testnet.fetch.ai/transactions/0x{}'.format(tx_digest)

    if explorer_link is not None:
        print()
        print('See {} for more details'.format(explorer_link))
コード例 #5
0
def main():
    # create the APIs
    api = LedgerApi(HOST, PORT)

    # we generate an identity from a known key, which contains funds.
    multi_sig_identity = Entity.from_hex(
        "6e8339a0c6d51fc58b4365bf2ce18ff2698d2b8c40bb13fcef7e1ba05df18e4b")

    # generate a board to control multi-sig account, with variable voting weights
    board = [
        Entity.from_hex(
            "e833c747ee0aeae29e6823e7c825d3001638bc30ffe50363f8adf2693c3286f8"
        ),
        Entity.from_hex(
            "4083a476c4872f25cb40839ac8d994924bcef12d83e2ba4bd3ed6c9705959860"
        ),
        Entity.from_hex(
            "20293422c4b5faefba3422ed436427f2d37f310673681e98ac8637b04e756de3"
        ),
        Entity.from_hex(
            "d5f10ad865fff147ae7fcfdc98b755452a27a345975c8b9b3433ff16f23495fb"
        ),
    ]

    voting_weights = {
        board[0]: 1,
        board[1]: 1,
        board[2]: 1,
        board[3]: 2,
    }

    # generate another entity as a target for transfers
    other_identity = Entity.from_hex(
        "7da0e3fa62a916238decd4f54d43301c809595d66dd469f82f29e076752b155c")

    # submit deed
    print("\nCreating deed...")
    deed = Deed()
    for sig, weight in voting_weights.items():
        deed.set_signee(sig, weight)
    deed.set_operation(Operation.amend, 4)
    deed.set_operation(Operation.transfer, 3)

    api.sync(api.tokens.deed(multi_sig_identity, deed, 500))

    # display balance before
    print("\nBefore remote-multisig transfer")
    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))
    print()

    # scatter/gather example
    print("Generating transaction and distributing to signers...")

    # add intended signers to transaction
    ref_tx = TokenTxFactory.transfer(multi_sig_identity,
                                     other_identity,
                                     250,
                                     20,
                                     signatories=board)
    api.set_validity_period(ref_tx)

    # make a reference payload that can be used in this script for validation
    reference_payload = ref_tx.encode_payload()

    # have signers individually sign transaction
    signed_txs = []
    for signer in board:
        # signer builds their own transaction to compare to note that each of the signers will need to agree on all
        # parts of the message including the validity period and the counter
        signer_tx = TokenTxFactory.transfer(multi_sig_identity,
                                            other_identity,
                                            250,
                                            20,
                                            signatories=board)
        signer_tx.counter = ref_tx.counter
        signer_tx.valid_until = ref_tx.valid_until
        signer_tx.valid_from = ref_tx.valid_from

        # sanity check each of the signers payload should match the reference payload
        assert signer_tx.encode_payload() == reference_payload

        # signers locally sign there version of the transaction
        signer_tx.sign(signer)

        # simulate distribution of signed partial transactions
        signed_txs.append(signer_tx.encode_partial())

    # gather and encode final transaction - this step in theory can be done by all the signers provided they are
    # received all the signature shares
    print("Gathering and combining signed transactions...")
    partial_txs = [Transaction.decode_partial(s)[1] for s in signed_txs]

    # merge them together into one fully signed transaction
    success, tx = Transaction.merge(partial_txs)
    assert success  # this indicates that all the signatures have been merged and that the transaction now validates

    # submit the transaction
    api.sync(api.submit_signed_tx(tx))

    print("\nAfter remote multisig-transfer")
    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))

    # round-robin example
    print("\nGenerating transaction and sending down the line of signers...")

    # create the basis for the transaction
    tx = TokenTxFactory.transfer(multi_sig_identity,
                                 other_identity,
                                 250,
                                 20,
                                 signatories=board)
    api.set_validity_period(tx)

    # serialize and send to be signed
    tx_payload = tx.encode_payload()

    # have signers individually sign transaction and pass on to next signer
    for signer in board:
        # build the target transaction
        signer_tx = Transaction.decode_payload(tx_payload)

        # Signer decodes payload to inspect transaction
        signer_tx.sign(signer)

        # ensure that when we merge the signers signature into the payload that it is correct
        assert tx.merge_signatures(signer_tx)

    # once all the partial signatures have been merged then it makes sense
    print("Collecting final signed transaction...")
    assert tx.is_valid()
    api.sync(api.submit_signed_tx(tx))

    print("\nAfter remote multisig-transfer")
    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))
コード例 #6
0
ファイル: test_transaction.py プロジェクト: WorldBosss1/fhi-
    def test_compare(self):
        tx = TokenTxFactory.transfer(self.source_identity, Identity(self.target_identity),
                                     500, 500, [self.source_identity])

        # encode the transaction so that copies can be made afterwards
        encoded_tx = tx.encode_partial()

        # Test comparison fails if any data changed
        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.from_address = Entity()
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.add_transfer(Entity(), 500)
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.valid_from = 999
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.valid_until = 999
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.charge_rate = 999
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.charge_limit = 999
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._contract_address = Address(Entity())
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._chain_code = 'changed'
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._action = 'changed'
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._shard_mask = BitVector(size=16)
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.data = b'changed'
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2.add_signer(Entity())
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._counter = 999
        self.assertNotEqual(tx, tx2)

        _, tx2 = Transaction.decode_partial(encoded_tx)
        tx2._is_synergetic = True
        self.assertNotEqual(tx, tx2)
コード例 #7
0
ファイル: multisig.py プロジェクト: WorldBosss1/fhi-
def main():
    # create the APIs
    api = LedgerApi(HOST, PORT)

    # generate an identity from a known key, which contains funds.
    multi_sig_identity = Entity.from_hex(
        "6e8339a0c6d51fc58b4365bf2ce18ff2698d2b8c40bb13fcef7e1ba05df18e4b")
    # generate a board to control multi-sig account, with variable voting weights.
    # we use keys for accounts which already have funds.
    board = []
    board.append(
        Entity.from_hex(
            "e833c747ee0aeae29e6823e7c825d3001638bc30ffe50363f8adf2693c3286f8")
    )
    board.append(
        Entity.from_hex(
            "4083a476c4872f25cb40839ac8d994924bcef12d83e2ba4bd3ed6c9705959860")
    )
    board.append(
        Entity.from_hex(
            "20293422c4b5faefba3422ed436427f2d37f310673681e98ac8637b04e756de3")
    )
    board.append(
        Entity.from_hex(
            "d5f10ad865fff147ae7fcfdc98b755452a27a345975c8b9b3433ff16f23495fb")
    )
    voting_weights = {
        board[0]: 1,
        board[1]: 1,
        board[2]: 1,
        board[3]: 2,
    }
    # generate another entity as a target for transfers
    other_identity = Entity.from_hex(
        "e833c747ee0aeae29e6823e7c825d3001638bc30ffe50363f8adf2693c3286f8")

    print('Original balance of multi_sig_identity:',
          api.tokens.balance(multi_sig_identity))

    # transfers can happen normally without a deed
    print('\nSubmitting pre-deed transfer with original signature...')
    api.sync(api.tokens.transfer(multi_sig_identity, other_identity, 250, 20))

    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))

    # submit the original deed
    print("\nCreating deed...")
    deed = Deed()
    for sig, weight in voting_weights.items():
        deed.set_signee(sig, weight)
    # set our initial voting thresholds
    deed.set_operation(Operation.transfer, 2)
    deed.set_operation(Operation.amend, 4)

    api.sync(api.tokens.deed(multi_sig_identity, deed, 6000))

    # original address can no longer validate transfers
    print("\nTransfer with original signature should fail...")
    try:
        api.sync(
            api.tokens.transfer(multi_sig_identity, other_identity, 250, 20))
    except RuntimeError as e:
        print("Transaction failed as expected")
    else:
        print("Transaction succeeded, it shouldn't have")

    # sufficient voting power required to sign transfers
    print("\nSubmitting transfer with two signatures with total 2 votes...")
    print_signing_votes(voting_weights, board[:2])

    # since we now want to create a transaction which has only been signed by a subset of the board, we must use
    # the factory interface in order to build out the transaction we are after
    tx = TokenTxFactory.transfer(multi_sig_identity, other_identity, 250, 20,
                                 board[:2])
    tx.valid_until = api.tokens.current_block_number() + 100
    # the signatories to sign the transaction
    for signatory in board[:2]:
        tx.sign(signatory)

    api.sync(api.submit_signed_tx(tx))

    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))

    # some entities may have more voting power
    print("\nSubmitting transfer with single signature with 2 votes...")
    print_signing_votes(voting_weights, board[3])

    tx = TokenTxFactory.transfer(multi_sig_identity, other_identity, 250, 20,
                                 [board[3]])
    tx.valid_until = api.tokens.current_block_number() + 100
    tx.sign(board[3])
    api.sync(api.submit_signed_tx(tx))

    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))

    # amend the deed
    print("\nAmending deed to increase transfer threshold to 3 votes...")
    deed.set_operation(Operation.transfer, 3)
    tx = TokenTxFactory.deed(multi_sig_identity, deed, 400, board)
    tx.valid_until = api.tokens.current_block_number() + 100
    for member in board:
        tx.sign(member)
    api.sync(api.submit_signed_tx(tx))

    # single member no longer has enough voting power
    print("\nSingle member transfer with 2 votes should no longer succeed...")
    try:
        print_signing_votes(voting_weights, board[3])

        tx = TokenTxFactory.transfer(multi_sig_identity, other_identity, 250,
                                     20, [board[3]])
        tx.valid_until = api.tokens.current_block_number() + 100
        tx.sign(board[3])
        api.sync(api.submit_signed_tx(tx))

    except RuntimeError as e:
        print("Transaction failed as expected")
    else:
        print("Transaction succeeded, it shouldn't have")

    # correct number of signatory votes
    print("\nSuccesful transaction with sufficient voting weight...")
    print_signing_votes(voting_weights, board[1:])

    tx = TokenTxFactory.transfer(multi_sig_identity, other_identity, 250, 20,
                                 board[1:])
    tx.valid_until = api.tokens.current_block_number() + 100
    for member in board[1:]:
        tx.sign(member)
    api.sync(api.submit_signed_tx(tx))

    print('Balance 1:', api.tokens.balance(multi_sig_identity))
    print('Balance 2:', api.tokens.balance(other_identity))

    # warning: if no amend threshold is set, future amendments are impossible
    print("\nAmending deed to remove threshold...")
    deed.remove_operation(Operation.amend)
    deed.require_amend = False

    tx = TokenTxFactory.deed(multi_sig_identity, deed, 400, board)
    tx.valid_until = api.tokens.current_block_number() + 100
    for member in board:
        tx.sign(member)
    api.sync(api.submit_signed_tx(tx))

    deed.set_operation(Operation.amend, 1)
    print("\nExpecting further amendment to fail...")
    try:
        tx = TokenTxFactory.deed(multi_sig_identity, deed, 400, board)
        tx.valid_until = api.tokens.current_block_number() + 100
        for member in board:
            tx.sign(member)
        api.sync(api.submit_signed_tx(tx))
    except RuntimeError as e:
        print("Transaction failed as expected")
    else:
        print("Transaction succeeded, it shouldn't have")