Beispiel #1
0
    def spend_utxo(self, utxo_id, new_owner, amount, signer):
        """Creates a spending transaction and inserts it into the chain.

        Args:
            utxo_id (int): Identifier of the UTXO to spend.
            new_owner (EthereumAccount): Account to own the output of this spend.
            amount (int): Amount to spend.
            signer (EthereumAccount): Account to sign this transaction.

        Returns:
            int: Unique identifier of the spend.
        """

        spend_tx = Transaction(*decode_utxo_id(utxo_id),
                               0, 0, 0,
                               NULL_ADDRESS,
                               new_owner.address, amount,
                               NULL_ADDRESS, 0)
        spend_tx.sign1(signer.key)

        blknum = self.root_chain.currentChildBlock()
        block = Block(transaction_set=[spend_tx], number=blknum)
        block.sign(self.operator.key)
        self.root_chain.submitBlock(block.root)
        self.child_chain.add_block(block)
        return encode_utxo_id(blknum, 0, 0)
Beispiel #2
0
 def set_dict(self, **num):
     print("set test")
     print("Data type of argument:", type(num))
     for key, value in num.items():
         print("{} is {}".format(key, value))
     #self.root_chain.deposit(transact={'from': owner, 'value': amount})
     mapping = {}
     mapping.update(num)
     for key, value in mapping.items():
         print("{} is {}".format(key, value))
     #convert dict to binary string
     bin_mapping = pickle.dumps(mapping)
     blknum = self.chain.next_deposit_block
     new_block = Block(None, blknum, NULL_SIGNATURE)
     new_block.add_mapping(mapping)
     self.chain.add_block(new_block)
     print("Number {} {}".format(new_block.number,
                                 self.chain.next_deposit_block))
     tx = Transaction(
         blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0),
         utils.normalize_address(
             '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1,
         utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE,
         NULL_SIGNATURE, 0, bin_mapping)
     key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304'
     print("Data type of key1:", type(key1))
     tx.sign1(utils.normalize_key(key1))
     self.current_block.add_transaction(tx)
     print("Added {}".format(self.current_block.transaction_set[0]))
     print("Added {}".format(self.current_block.transaction_set[0].mapping))
     self.chain.set_dict(**num)
 def __init__(self, operator, root_chain):
     self.operator = operator
     self.root_chain = root_chain
     self.chain = {}
     self.tree = MerkleTree(2)
     self.roots = {}
     self.nullifiers = {}
     self.height = 0
     self.current_block = Block()
Beispiel #4
0
    def submit_block(self, block):
        if isinstance(block, str):
            block = rlp.decode(utils.decode_hex(block), Block)

        self.chain.add_block(block)
        self.root_chain.transact({
            'from':
            utils.checksum_encode(address_to_hex(self.operator))
        }).submitBlock(block.merkle.root)
        self.current_block = Block(number=self.chain.next_child_block)
Beispiel #5
0
    def __init__(self, operator, root_chain):
        self.operator = operator
        self.root_chain = root_chain
        self.chain = Chain(self.operator)
        self.current_block = Block(number=self.chain.next_child_block)

        # Listen for events
        self.event_listener = RootEventListener(root_chain, confirmations=0)
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)
Beispiel #6
0
class ChildChain(object):
    def __init__(self, operator, root_chain):
        self.operator = operator
        self.root_chain = root_chain
        self.chain = Chain(self.operator)
        self.current_block = Block(number=self.chain.next_child_block)

        # Listen for events
        self.event_listener = RootEventListener(root_chain, confirmations=0)
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)

    def apply_exit(self, event):
        event_args = event['args']
        utxo_id = event_args['utxoPos']
        self.chain.mark_utxo_spent(utxo_id)

    def apply_deposit(self, event):
        event_args = event['args']
        owner = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = get_deposit_tx(owner, amount)
        deposit_block = Block([deposit_tx], number=blknum)
        self.chain.add_block(deposit_block)

    def apply_transaction(self, tx):
        self.chain.validate_transaction(tx, self.current_block.spent_utxos)
        self.current_block.add_transaction(tx)
        return encode_utxo_id(self.current_block.number,
                              len(self.current_block.transaction_set) - 1, 0)

    def submit_block(self, block):
        self.chain.add_block(block)
        self.root_chain.transact({
            'from': self.operator
        }).submitBlock(block.merkle.root)
        self.current_block = Block(number=self.chain.next_child_block)

    def get_transaction(self, tx_id):
        return self.chain.get_transaction(tx_id)

    def get_block(self, blknum):
        return self.chain.get_block(blknum)

    def get_current_block(self):
        return self.current_block

    def get_all_blocks(self):
        for b in list(self.chain.blocks.values()):
            b.print_debug()
        return ""
Beispiel #7
0
class ChildChain(object):
    def __init__(self, operator, root_chain):
        self.operator = operator
        self.root_chain = root_chain
        self.chain = Chain(self.operator)
        self.current_block = Block(number=self.chain.next_child_block)

        # Listen for events
        self.event_listener = RootEventListener(root_chain, confirmations=0)
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)

    def apply_exit(self, event):
        event_args = event['args']
        utxo_id = event_args['utxoPos']
        self.chain.mark_utxo_spent(utxo_id)

    def apply_deposit(self, event):
        event_args = event['args']
        owner = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = get_deposit_tx(owner, amount)
        deposit_block = Block([deposit_tx], number=blknum)
        self.chain.add_block(deposit_block)

    def apply_transaction(self, tx):
        self.chain.validate_transaction(tx, self.current_block.spent_utxos)
        self.current_block.add_transaction(tx)
        return encode_utxo_id(self.current_block.number,
                              len(self.current_block.transaction_set) - 1, 0)

    def submit_block(self, block):
        if isinstance(block, str):
            block = rlp.decode(utils.decode_hex(block), Block)

        self.chain.add_block(block)
        self.root_chain.transact({
            'from':
            utils.checksum_encode(address_to_hex(self.operator))
        }).submitBlock(block.merkle.root)
        self.current_block = Block(number=self.chain.next_child_block)

    def get_transaction(self, tx_id):
        return self.chain.get_transaction(tx_id)

    def get_block(self, blknum):
        return rlp.encode(self.chain.get_block(blknum), Block).hex()

    def get_current_block(self):
        return rlp.encode(self.current_block, Block).hex()
Beispiel #8
0
 def __init__(self, operator, root_chain):
     self.operator = operator
     self.root_chain = root_chain
     self.chain = Chain(self.operator)
     self.current_block = Block(number=self.chain.next_child_block)
     print("self.current_block {0}".format(self.current_block.number))
     # Listen for events
     self.event_listener = RootEventListener(root_chain, confirmations=0)
     self.event_listener.on('Deposit', self.apply_deposit)
     self.event_listener.on('ExitStarted', self.apply_exit)
     self.event_listener.on('MsgSender', self.msgsender)
     self.event_listener.on('FinalState', self.finalstate)
     self.event_listener.on('forDebug01', self.debug01)
Beispiel #9
0
 def submit_block(self, transactions, signer=None, force_invalid=False):
     signer = signer or self.operator
     blknum = self.root_chain.nextChildBlock()
     block = Block(transactions, number=blknum)
     block.sign(signer.key)
     self.root_chain.submitBlock(block.root, sender=signer.key)
     if force_invalid:
         self.child_chain.blocks[self.child_chain.next_child_block] = block
         self.child_chain.next_deposit_block = self.child_chain.next_child_block + 1
         self.child_chain.next_child_block += self.child_chain.child_block_interval
     else:
         assert self.child_chain.add_block(block)
     return blknum
Beispiel #10
0
    def __init__(self, authority, root_chain):
        self.root_chain = root_chain
        self.authority = authority
        self.blocks = {}
        self.child_block_interval = 1000
        self.current_block_number = self.child_block_interval
        self.current_block = Block()
        self.pending_transactions = []

        self.event_listener = RootEventListener(root_chain, confirmations=0)

        # Register event listeners
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)
Beispiel #11
0
    def submit_block(self, block):
        block = rlp.decode(utils.decode_hex(block), Block)
        if block.merklize_transaction_set() != self.current_block.merklize_transaction_set():
            raise InvalidBlockMerkleException('input block merkle mismatch with the current block')

        valid_signature = block.sig != NULL_SIGNATURE and block.sender == bytes.fromhex(self.authority[2:])
        if not valid_signature:
            raise InvalidBlockSignatureException('failed to submit block')

        self.root_chain.transact({'from': self.authority}).submitBlock(block.merkle.root)
        # TODO: iterate through block and validate transactions
        self.blocks[self.current_block_number] = self.current_block
        self.current_block_number += self.child_block_interval
        self.current_block = Block()
Beispiel #12
0
    def deposit_token(self, owner, token, amount):
        """Mints, approves and deposits token for given owner and amount

        Args:
            owner (EthereumAccount): Account to own the deposit.
            token (Contract: ERC20, MintableToken): Token to be deposited.
            amount (int): Deposit amount.

        Returns:
            int: Unique identifier of the deposit.
        """

        deposit_tx = Transaction(outputs=[(owner.address, token.address,
                                           amount)])
        token.mint(owner.address, amount)
        token.approve(self.root_chain.erc20_vault.address, amount,
                      **{'from': owner.address})
        blknum = self.root_chain.getDepositBlockNumber()
        pre_balance = self.get_balance(self.root_chain.erc20_vault, token)
        self.root_chain.depositFrom(deposit_tx.encoded,
                                    **{'from': owner.address})
        balance = self.get_balance(self.root_chain.erc20_vault, token)
        assert balance == pre_balance + amount
        block = Block(transactions=[deposit_tx], number=blknum)
        self.child_chain.add_block(block)
        return encode_utxo_id(blknum, 0, 0)
Beispiel #13
0
    def deposit_token(self, owner, token, amount):
        """Mints, approves and deposits token for given owner and amount

        Args:
            owner (EthereumAccount): Account to own the deposit.
            token (Contract: ERC20, MintableToken): Token to be deposited.
            amount (int): Deposit amount.

        Returns:
            int: Unique identifier of the deposit.
        """

        deposit_tx = Transaction(0, 0, 0,
                                 0, 0, 0,
                                 token.address,
                                 owner.address, amount,
                                 NULL_ADDRESS, 0)

        token.mint(owner.address, amount)
        self.ethtester.chain.mine()
        token.approve(self.root_chain.address, amount, sender=owner.key)
        self.ethtester.chain.mine()
        blknum = self.root_chain.getDepositBlock()
        self.root_chain.depositFrom(owner.address, token.address, amount, sender=owner.key)

        block = Block(transaction_set=[deposit_tx], number=blknum)
        self.child_chain.add_block(block)
        return blknum
def _deposit(testlang, owner, amount, blknum):
    deposit_tx = Transaction(outputs=[(owner.address, NULL_ADDRESS, amount)])
    testlang.root_chain.eth_vault.functions.deposit(deposit_tx.encoded).transact({'from': owner.address, 'value': amount})
    deposit_id = encode_utxo_id(blknum, 0, 0)
    block = Block([deposit_tx], number=blknum)
    testlang.child_chain.add_block(block)
    return deposit_id
Beispiel #15
0
 def deposit(self, owner, amount):
     deposit_tx = Transaction(outputs=[(owner.address, NULL_ADDRESS,
                                        amount)])
     blknum = self.root_chain.getDepositBlockNumber()
     self.root_chain.deposit(deposit_tx.encoded, value=amount)
     deposit_id = encode_utxo_id(blknum, 0, 0)
     block = Block([deposit_tx], number=blknum)
     self.child_chain.add_block(block)
     return deposit_id
Beispiel #16
0
    def apply_deposit(self, event):
        event_args = event['args']
        owner = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = get_deposit_tx(owner, amount)
        deposit_block = Block([deposit_tx], number=blknum)
        self.chain.add_block(deposit_block)
Beispiel #17
0
def test_commit_plasma_block_root_should_succeed(testlang):
    # Operator should be able to submit
    operator = testlang.accounts[0]
    block = Block()
    testlang.commit_plasma_block_root(block, signer=operator)

    # Check that the block was created correctly
    plasma_block_root = testlang.get_plasma_block(1)
    assert plasma_block_root.root == block.root
    assert plasma_block_root.timestamp == testlang.ethtester.chain.head_state.timestamp
    assert testlang.current_plasma_block_number == 2
Beispiel #18
0
def test_commit_plasma_block_root_not_operator_should_fail(testlang):
    # Operator should be able to submit
    non_operator = testlang.accounts[1]
    block = Block()
    with pytest.raises(TransactionFailed):
        testlang.commit_plasma_block_root(block, signer=non_operator)

    # Check nothing was submitted
    plasma_block = testlang.get_plasma_block(1)
    assert plasma_block.root == NULL_HASH
    assert plasma_block.timestamp == 0
    assert testlang.current_plasma_block_number == 1
Beispiel #19
0
    def apply_deposit(self, event):
        event_args = event['args']

        depositor = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = Transaction(0, 0, 0,
                                 0, 0, 0,
                                 NULL_ADDRESS,
                                 depositor, amount,
                                 NULL_ADDRESS, 0)
        deposit_block = Block([deposit_tx])

        self.blocks[blknum] = deposit_block
    def deposit(self, owner, amount):
        """Creates a deposit transaction for a given owner and amount.

        Args:
            owner (EthereumAccount): Account to own the deposit.
            amount (int): Deposit amount.

        Returns:
            int: Unique identifier of the deposit.
        """

        deposit_tx = Transaction(inputs=[], outputs=[(owner.address, amount)])
        blknum = self.root_chain.currentPlasmaBlockNumber()
        self.root_chain.deposit(value=amount, sender=owner.key)

        block = Block(transactions=[deposit_tx], number=blknum)
        self.child_chain.add_block(block)
        return blknum
Beispiel #21
0
    def deposit(self, owner, amount):
        """Creates a deposit transaction for a given owner and amount.

        Args:
            owner (EthereumAccount): Account to own the deposit.
            amount (int): Deposit amount.

        Returns:
            int: Unique identifier of the deposit.
        """

        deposit_tx = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, owner.address,
                                 amount, NULL_ADDRESS, 0)

        blknum = self.root_chain.getDepositBlock()
        self.root_chain.deposit(value=amount, sender=owner.key)

        block = Block(transaction_set=[deposit_tx], number=blknum)
        self.child_chain.add_block(block)
        return blknum
Beispiel #22
0
    def spend_utxo(self, utxo_position, new_owner, amount, signer):
        """Creates a spending transaction and inserts it into the chain.

        Args:
            utxo_position (int): Identifier of the UTXO to spend.
            new_owner (EthereumAccount): Account to own the output of this spend.
            amount (int): Amount to spend.
            signer (EthereumAccount): Account to sign this transaction.

        Returns:
            int: Unique identifier of the spend.
        """

        spend_tx = Transaction(inputs=[decode_utxo_position(utxo_position)],
                               outputs=[(new_owner.address, amount)])
        spend_tx.sign(0, signer.key)

        blknum = self.root_chain.currentPlasmaBlockNumber()
        block = Block(transactions=[spend_tx], number=blknum)
        self.commit_plasma_block_root(block)
        return encode_utxo_position(blknum, 0, 0)
Beispiel #23
0
 def set_test(self, num):
     print("set test")
     print("Data type of argument:", type(num))
     blknum = self.chain.next_deposit_block
     file_block = Block(None, blknum, NULL_SIGNATURE)
     self.chain.add_block(file_block)
     print("Number {} {} {}".format(num, file_block.number,
                                    self.chain.next_deposit_block))
     tx = Transaction(
         blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0),
         utils.normalize_address(
             '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1,
         utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE,
         NULL_SIGNATURE, num)
     key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304'
     print("Data type of key1:", type(key1))
     tx.sign1(utils.normalize_key(key1))
     self.current_block.add_transaction(tx)
     print("Added {}".format(self.current_block.transaction_set[0]))
     print("Added {}".format(self.current_block.transaction_set[0].files))
     self.chain.set_test(num)
Beispiel #24
0
 def submit_block(self, block):
     self.chain.add_block(block)
     self.root_chain.transact({
         'from': self.operator
     }).submitBlock(block.merkle.root)
     self.current_block = Block(number=self.chain.next_child_block)
Beispiel #25
0
class ChildChain(object):
    def __init__(self, operator, root_chain):
        self.operator = operator
        self.root_chain = root_chain
        self.chain = Chain(self.operator)
        self.current_block = Block(number=self.chain.next_child_block)
        print("self.current_block {0}".format(self.current_block.number))
        # Listen for events
        self.event_listener = RootEventListener(root_chain, confirmations=0)
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)
        self.event_listener.on('MsgSender', self.msgsender)
        self.event_listener.on('FinalState', self.finalstate)
        self.event_listener.on('forDebug01', self.debug01)

    def debug01(self, event):
        print("debug01 {0}".format(event['args']))

    def finalstate(self, event):
        print("finalstate {0}".format(event['args']))
        event_args = event['args']
        dmapping = event_args['dmapping']
        print("pickle {}".format(pickle.loads(dmapping)))

    def msgsender(self, event):
        print("msgsender {0}".format(event['args']))

    def apply_exit(self, event):
        print("exit started {0}".format(event['args']))
        event_args = event['args']
        utxo_id = event_args['utxoPos']
        blknum = utxo_id / 1000000000
        print("blknum {0}".format(blknum))
        block = self.chain.get_block(blknum)
        print("Files {}".format(block.transaction_set[0].files))
        self.chain.mark_utxo_spent(utxo_id)

    def apply_deposit(self, event):
        print("apply deposit {0}".format(event['args']))
        event_args = event['args']
        owner = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = get_deposit_tx(owner, amount)
        deposit_block = Block([deposit_tx], number=blknum)
        self.chain.add_block(deposit_block)

    def apply_transaction(self, tx):
        print("spent_utxos {0} {1}".format(self.current_block.spent_utxos,
                                           self.current_block.number))
        self.chain.validate_transaction(tx, self.current_block.spent_utxos)
        self.current_block.add_transaction(tx)
        return encode_utxo_id(self.current_block.number,
                              len(self.current_block.transaction_set) - 1, 0)

    def submit_block(self, block):
        self.chain.add_block(block)
        self.root_chain.transact({
            'from': self.operator
        }).submitBlock(block.merkle.root)
        self.current_block = Block(number=self.chain.next_child_block)

    def get_transaction(self, tx_id):
        return self.chain.get_transaction(tx_id)

    def get_block(self, blknum):
        return self.chain.get_block(blknum)

    def get_current_block(self):
        print("current block")
        return self.current_block

    def get_current_block_num(self):
        print("current block num")
        return self.current_block.number

    def get_test(self):
        print("get test")
        return self.chain.get_test()

    def set_test(self, num):
        print("set test")
        print("Data type of argument:", type(num))
        blknum = self.chain.next_deposit_block
        file_block = Block(None, blknum, NULL_SIGNATURE)
        self.chain.add_block(file_block)
        print("Number {} {} {}".format(num, file_block.number,
                                       self.chain.next_deposit_block))
        tx = Transaction(
            blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0),
            utils.normalize_address(
                '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1,
            utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE,
            NULL_SIGNATURE, num)
        key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304'
        print("Data type of key1:", type(key1))
        tx.sign1(utils.normalize_key(key1))
        self.current_block.add_transaction(tx)
        print("Added {}".format(self.current_block.transaction_set[0]))
        print("Added {}".format(self.current_block.transaction_set[0].files))
        self.chain.set_test(num)

    def set_dict(self, **num):
        print("set test")
        print("Data type of argument:", type(num))
        for key, value in num.items():
            print("{} is {}".format(key, value))
        #self.root_chain.deposit(transact={'from': owner, 'value': amount})
        mapping = {}
        mapping.update(num)
        for key, value in mapping.items():
            print("{} is {}".format(key, value))
        #convert dict to binary string
        bin_mapping = pickle.dumps(mapping)
        blknum = self.chain.next_deposit_block
        new_block = Block(None, blknum, NULL_SIGNATURE)
        new_block.add_mapping(mapping)
        self.chain.add_block(new_block)
        print("Number {} {}".format(new_block.number,
                                    self.chain.next_deposit_block))
        tx = Transaction(
            blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0),
            utils.normalize_address(
                '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1,
            utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE,
            NULL_SIGNATURE, 0, bin_mapping)
        key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304'
        print("Data type of key1:", type(key1))
        tx.sign1(utils.normalize_key(key1))
        self.current_block.add_transaction(tx)
        print("Added {}".format(self.current_block.transaction_set[0]))
        print("Added {}".format(self.current_block.transaction_set[0].mapping))
        self.chain.set_dict(**num)

    def hello(self):
        print("hello")
Beispiel #26
0
def block():
    return Block()
Beispiel #27
0
    def submit_block(self, block):
        self.chain[self.height] = block
        self.root_chain.submitBlock(self.operator, block.root)

        self.height += 1
        self.current_block = Block(number=self.height)
Beispiel #28
0
class ChildChain(object):

    def __init__(self, authority, root_chain):
        self.root_chain = root_chain
        self.authority = authority
        self.blocks = {}
        self.child_block_interval = 1000
        self.current_block_number = self.child_block_interval
        self.current_block = Block()
        self.pending_transactions = []

        self.event_listener = RootEventListener(root_chain, confirmations=0)

        # Register event listeners
        self.event_listener.on('Deposit', self.apply_deposit)
        self.event_listener.on('ExitStarted', self.apply_exit)

    def apply_exit(self, event):
        event_args = event['args']
        utxo_pos = event_args['utxoPos']
        self.mark_utxo_spent(*decode_utxo_id(utxo_pos))

    def apply_deposit(self, event):
        event_args = event['args']

        depositor = event_args['depositor']
        amount = event_args['amount']
        blknum = event_args['depositBlock']

        deposit_tx = Transaction(0, 0, 0,
                                 0, 0, 0,
                                 NULL_ADDRESS,
                                 depositor, amount,
                                 NULL_ADDRESS, 0)
        deposit_block = Block([deposit_tx])

        self.blocks[blknum] = deposit_block

    def apply_transaction(self, transaction):
        tx = rlp.decode(utils.decode_hex(transaction), Transaction)

        # Validate the transaction
        self.validate_tx(tx)

        # Mark the inputs as spent
        self.mark_utxo_spent(tx.blknum1, tx.txindex1, tx.oindex1)
        self.mark_utxo_spent(tx.blknum2, tx.txindex2, tx.oindex2)

        self.current_block.transaction_set.append(tx)

    def validate_tx(self, tx):
        inputs = [(tx.blknum1, tx.txindex1, tx.oindex1), (tx.blknum2, tx.txindex2, tx.oindex2)]

        output_amount = tx.amount1 + tx.amount2
        input_amount = 0

        for (blknum, txindex, oindex) in inputs:
            # Assume empty inputs and are valid
            if blknum == 0:
                continue

            transaction = self.blocks[blknum].transaction_set[txindex]

            if oindex == 0:
                valid_signature = tx.sig1 != NULL_SIGNATURE and transaction.newowner1 == tx.sender1
                spent = transaction.spent1
                input_amount += transaction.amount1
            else:
                valid_signature = tx.sig2 != NULL_SIGNATURE and transaction.newowner2 == tx.sender2
                spent = transaction.spent2
                input_amount += transaction.amount2
            if spent:
                raise TxAlreadySpentException('failed to validate tx')
            if not valid_signature:
                raise InvalidTxSignatureException('failed to validate tx')

        if input_amount < output_amount:
            raise TxAmountMismatchException('failed to validate tx')

    def mark_utxo_spent(self, blknum, txindex, oindex):
        if blknum == 0:
            return

        if oindex == 0:
            self.blocks[blknum].transaction_set[txindex].spent1 = True
        else:
            self.blocks[blknum].transaction_set[txindex].spent2 = True

    def submit_block(self, block):
        block = rlp.decode(utils.decode_hex(block), Block)
        if block.merklize_transaction_set() != self.current_block.merklize_transaction_set():
            raise InvalidBlockMerkleException('input block merkle mismatch with the current block')

        valid_signature = block.sig != NULL_SIGNATURE and block.sender == bytes.fromhex(self.authority[2:])
        if not valid_signature:
            raise InvalidBlockSignatureException('failed to submit block')

        self.root_chain.transact({'from': self.authority}).submitBlock(block.merkle.root)
        # TODO: iterate through block and validate transactions
        self.blocks[self.current_block_number] = self.current_block
        self.current_block_number += self.child_block_interval
        self.current_block = Block()

    def get_transaction(self, blknum, txindex):
        return rlp.encode(self.blocks[blknum].transaction_set[txindex]).hex()

    def get_tx_pos(self, transaction):
        decoded_tx = rlp.decode(utils.decode_hex(transaction), Transaction)

        for blknum in self.blocks:
            block = self.blocks[blknum]
            for txindex in range(0, len(block.transaction_set)):
                tx = block.transaction_set[txindex]
                if (decoded_tx.hash == tx.hash):
                    return blknum, txindex

        return None, None

    def get_block(self, blknum):
        return rlp.encode(self.blocks[blknum]).hex()

    def get_current_block(self):
        return rlp.encode(self.current_block).hex()

    def get_current_block_num(self):
        return self.current_block_number
Beispiel #29
0
class ChildChain(object):
    def __init__(self, operator, root_chain):
        self.operator = operator
        self.root_chain = root_chain
        self.chain = {}
        self.tree = MerkleTree(2)
        self.roots = {}
        self.nullifiers = {}
        self.height = 0
        self.current_block = Block()

    def apply_exit(self):
        # TODO
        return

    def apply_deposit(self):
        # TODO
        return

    def apply_transaction(self, transaction):
        tx = Transaction(transaction["serialNumbers"],
                         transaction["newRecords"], transaction["memo"],
                         transaction["in_root"], transaction["in_proof"])

        assert (self.approve_transaction(tx.serialNumbers, tx.newRecords,
                                         tx.memo, tx.in_root, tx.in_root))

        # insert into tree
        for i in range(len(tx.newRecords)):
            self.insert(tx.newRecords[i])
            print("Added new commitment: ", tx.newRecords[i])
            print("Added new memo: ", tx.memo[i])

        self.current_block.add(tx, self.get_root())

        # For now, 1 tx = 1 block!
        self.submit_block(self.current_block)

    def submit_block(self, block):
        self.chain[self.height] = block
        self.root_chain.submitBlock(self.operator, block.root)

        self.height += 1
        self.current_block = Block(number=self.height)

    def get_root(self):
        return self.tree.root

    def insert(self, leaf):
        # insert leaf to merkle tree
        self.tree.append(leaf)
        self.roots[self.get_root()] = True

    def is_spent(self, nullifier):
        # check if utxo is spent
        return self.nullifiers[nullifier]

    def approve_transaction(self, serialNumbers, newRecords, memo, in_root,
                            in_proof):
        # verify transaction
        assert (len(newRecords) > 0)
        assert (len(newRecords) == len(memo))
        assert (len(serialNumbers) > 0)
        # assert(self.roots[in_root])

        is_valid = self.verify_proof(serialNumbers, newRecords, memo, in_root,
                                     in_proof)

        assert (is_valid)

        # check if record is dummy
        for sn in serialNumbers:
            # assert(self.nullifiers[sn])
            self.nullifiers[sn] = True

        return True

    def verify_proof(self, serialNumbers, newRecords, memo, in_root, in_proof):
        # construct SNARK input
        snark_input = self.hash_public_inputs(serialNumbers, newRecords, memo,
                                              in_root)

        # return verifier.verify(self.vk, self.vk_gammaABC, in_proof, snark_input)
        return True

    def hash_public_inputs(self, serialNumbers, newRecords, memo, in_root):
        inputs_to_hash = []

        for sn in serialNumbers:
            inputs_to_hash.append(int(sn))

        for commit in newRecords:
            inputs_to_hash.append(int(commit))

        for m in memo:
            inputs_to_hash.append(int(m))

        inputs_to_hash.append(int(in_root))

        return mimc_hash(inputs_to_hash)