Пример #1
0
 def spend_input(state,
                 utxo_cache: UTXOCache,
                 address,
                 seq_no,
                 is_committed=False,
                 remove_spent=True):
     state_key = TokenStaticHelper.create_state_key(address, seq_no)
     if remove_spent:
         state.remove(state_key)
     else:
         state.set(state_key, b'')
     utxo_cache.spend_output(Output(address, seq_no, None),
                             is_committed=is_committed)
Пример #2
0
 def update_state(self, txn, prev_result, request, is_committed=False):
     try:
         payload = get_payload_data(txn)
         seq_no = get_seq_no(txn)
         for output in payload[OUTPUTS]:
             TokenStaticHelper.add_new_output(
                 self.state,
                 self.database_manager.get_store(UTXO_CACHE_LABEL),
                 Output(output["address"], seq_no, output["amount"]),
                 is_committed=is_committed)
     except UTXOError as ex:
         error = 'Exception {} while updating state'.format(ex)
         raise OperationError(error)
Пример #3
0
def test_token_req_handler_commit_success(helpers, addresses, token_handler_b,
                                          txnPoolNodeSet):
    [address1, address2] = addresses
    inputs = [{"address": address1, "seqNo": 1}]
    outputs = [{
        "address": address1,
        "amount": 30
    }, {
        "address": address2,
        "amount": 30
    }]
    request = helpers.request.transfer(inputs, outputs)

    # apply transaction
    state_root = txnPoolNodeSet[1].master_replica.stateRootHash(
        TOKEN_LEDGER_ID)
    txn_root = txnPoolNodeSet[1].master_replica.txnRootHash(TOKEN_LEDGER_ID)
    token_handler_b.apply(request, CONS_TIME)
    new_state_root = txnPoolNodeSet[1].master_replica.stateRootHash(
        TOKEN_LEDGER_ID)
    new_txn_root = txnPoolNodeSet[1].master_replica.txnRootHash(
        TOKEN_LEDGER_ID)
    # add batch
    token_handler_b.onBatchCreated(base58.b58decode(new_state_root.encode()))
    # commit batch
    assert token_handler_b.utxo_cache.get_unspent_outputs(
        address1, True) == [Output(address1, 1, 40)]
    assert token_handler_b.utxo_cache.get_unspent_outputs(
        address2, True) == [Output(address2, 1, 60)]
    commit_ret_val = token_handler_b.commit(1, new_state_root, new_txn_root,
                                            None)
    assert token_handler_b.utxo_cache.get_unspent_outputs(
        address1, True) == [Output(address1, 2, 30)]
    assert token_handler_b.utxo_cache.get_unspent_outputs(
        address2, True) == [Output(address2, 1, 60),
                            Output(address2, 2, 30)]
    assert new_state_root != state_root
    assert new_txn_root != txn_root
def test_token_req_handler_sum_inputs_success(helpers, token_handler_a):
    address = helpers.wallet.create_address()

    # Verify no outputs
    pre_add_outputs = token_handler_a.utxo_cache.get_unspent_outputs(address)
    assert pre_add_outputs == []

    # add and verify new unspent output added
    token_handler_a.utxo_cache.add_output(Output(address, 5, 150))
    post_add_outputs = token_handler_a.utxo_cache.get_unspent_outputs(address)
    assert post_add_outputs == [Output(address, 5, 150)]

    # add second unspent output and verify
    token_handler_a.utxo_cache.add_output(Output(address, 6, 100))
    post_second_add_outputs = token_handler_a.utxo_cache.get_unspent_outputs(address)
    assert post_second_add_outputs == [Output(address, 5, 150), Output(address, 6, 100)]

    # Verify sum_inputs is working properly
    inputs = [{"address": address, "seqNo": 5}, {"address": address, "seqNo": 6}]
    outputs = []
    request = helpers.request.transfer(inputs, outputs)
    sum_inputs = token_handler_a._sum_inputs(request)
    assert sum_inputs == 250
Пример #5
0
def test_token_req_handler_get_query_response_success(helpers, addresses,
                                                      token_handler_a):
    address1 = addresses[0]
    request = helpers.request.get_utxo(address1)
    results = token_handler_a.get_query_response(request)

    state_proof = results.pop(STATE_PROOF)
    assert state_proof
    assert results == {
        ADDRESS: address1,
        TXN_TYPE: GET_UTXO,
        OUTPUTS: [Output(address=address1, seq_no=1, value=40)],
        IDENTIFIER: VALID_IDENTIFIER,
        TXN_PAYLOAD_METADATA_REQ_ID: request.reqId
    }
Пример #6
0
 def update_token_state(self, txn, request, is_committed=False):
     for utxo in txn[TXN_PAYLOAD][TXN_PAYLOAD_DATA][INPUTS]:
         TokenStaticHelper.spend_input(state=self.token_state,
                                       utxo_cache=self.utxo_cache,
                                       address=utxo[ADDRESS],
                                       seq_no=utxo[SEQNO],
                                       is_committed=is_committed)
     seq_no = get_seq_no(txn)
     for output in txn[TXN_PAYLOAD][TXN_PAYLOAD_DATA][OUTPUTS]:
         TokenStaticHelper.add_new_output(state=self.token_state,
                                          utxo_cache=self.utxo_cache,
                                          output=Output(
                                              output[ADDRESS], seq_no,
                                              output[AMOUNT]),
                                          is_committed=is_committed)
Пример #7
0
    def as_output_list(self) -> List[Output]:
        if len(self.data) % 2 != 0:
            raise UTXOError('Length of seqNo-amount pairs must be even: items={}'.format(len(self.data)))

        rtn = []
        for i in range(0, len(self.data), 2):
            try:
                seq_no = int(self.data[i])
                amount = int(self.data[i + 1])
            except ValueError:
                raise UTXOError("Invalid data -- not integers -- seq_no:{} amount:{}".format(self.data[i],
                                                                                             self.data[i + 1]))
            rtn.append(Output(self.address, seq_no, amount))


        return rtn
Пример #8
0
def test_token_req_handler_onBatchCreated_success(addresses, token_handler_a,
                                                  txnPoolNodeSet):
    address = addresses[0]
    output = Output(address, 10, 100)
    # add output to UTXO Cache
    token_handler_a.utxo_cache.add_output(output)
    state_root = txnPoolNodeSet[1].master_replica.stateRootHash(
        TOKEN_LEDGER_ID)
    # run onBatchCreated
    token_handler_a.onBatchCreated(state_root, CONS_TIME)
    # Verify onBatchCreated worked properly
    key = token_handler_a.utxo_cache._create_key(output)
    assert token_handler_a.utxo_cache.un_committed[0][0] == state_root
    assert key in token_handler_a.utxo_cache.un_committed[0][1]
    assert '{}:{}'.format(str(output.seqNo), str(
        output.amount)) in token_handler_a.utxo_cache.un_committed[0][1][key]
Пример #9
0
def test_token_req_handler_get_result_success(helpers, addresses,
                                              get_utxo_handler):
    address1 = addresses[0]
    request = helpers.request.get_utxo(address1)
    results = get_utxo_handler.get_result(request)

    state_proof = results.pop(STATE_PROOF)
    address1 = libsovtoken_address_to_address(address1)
    assert state_proof
    assert results == {
        ADDRESS: address1,
        TXN_TYPE: GET_UTXO,
        OUTPUTS: [Output(address=address1, seq_no=1, value=40)],
        IDENTIFIER:
        base58.b58encode(base58.b58decode_check(address1)).decode(),
        TXN_PAYLOAD_METADATA_REQ_ID: request.reqId
    }
Пример #10
0
def test_token_req_handler_get_query_response_success(
    helpers,
    addresses,
    token_handler_a
):
    address1 = addresses[0]
    request = helpers.request.get_utxo(address1)
    results = token_handler_a.get_query_response(request)

    state_proof = results.pop(STATE_PROOF)
    address1 = address1.replace("pay:sov:", "")
    assert state_proof
    assert results == {
        ADDRESS: address1,
        TXN_TYPE: GET_UTXO,
        OUTPUTS: [Output(address=address1, seq_no=1, value=40)],
        IDENTIFIER: base58.b58encode(base58.b58decode_check(address1)).decode(),
        TXN_PAYLOAD_METADATA_REQ_ID: request.reqId
    }
Пример #11
0
 def update_state(self, txn, prev_result, request, is_committed=False):
     try:
         payload = get_payload_data(txn)
         for inp in payload[INPUTS]:
             TokenStaticHelper.spend_input(self.state,
                                           self.utxo_cache,
                                           inp["address"],
                                           inp["seqNo"],
                                           is_committed=is_committed)
         for output in payload[OUTPUTS]:
             seq_no = get_seq_no(txn)
             TokenStaticHelper.add_new_output(self.state,
                                              self.utxo_cache,
                                              Output(
                                                  output["address"], seq_no,
                                                  output["amount"]),
                                              is_committed=is_committed)
     except UTXOError as ex:
         error = 'Exception {} while updating state'.format(ex)
         raise OperationError(error)
Пример #12
0
def test_token_req_handler_updateState_XFER_PUBLIC_success(
        helpers, addresses, token_handler_a):
    [address1, address2] = addresses
    seq_no = 1

    inputs = [{"address": address1, "seqNo": seq_no}]
    outputs = [{"address": address2, "amount": 40}]
    request = helpers.request.transfer(inputs, outputs)
    txn = reqToTxn(request)
    append_txn_metadata(txn, seq_no=seq_no)

    token_handler_a.validate(request)
    token_handler_a.updateState([txn])

    state_key = TokenReqHandler.create_state_key(address1, seq_no)
    key = token_handler_a.utxo_cache._create_key(Output(address1, seq_no, 60))
    assert token_handler_a.utxo_cache._store._has_key(key)
    try:
        token_handler_a.state.get(state_key, False)
    except Exception:
        pytest.fail("This state key isn't in the state")
Пример #13
0
    def get_all_utxo(self, request: Request):
        address = request.operation[ADDRESS]
        encoded_root_hash = state_roots_serializer.serialize(
            bytes(self.state.committedHeadHash))
        proof, rv = self.state.generate_state_proof_for_keys_with_prefix(
            address, serialize=True, get_value=True)
        multi_sig = self.bls_store.get(encoded_root_hash)
        if multi_sig:
            encoded_proof = proof_nodes_serializer.serialize(proof)
            proof = {
                MULTI_SIGNATURE: multi_sig.as_dict(),
                ROOT_HASH: encoded_root_hash,
                PROOF_NODES: encoded_proof
            }
        else:
            proof = {}

        # The outputs need to be returned in sorted order since each node's reply should be same.
        # Since no of outputs can be large, a concious choice to not use `operator.attrgetter` on an
        # already constructed list was made
        outputs = SortedItems()
        for k, v in rv.items():
            addr, seq_no = self.parse_state_key(k.decode())
            amount = rlp_decode(v)[0]
            if not amount:
                continue
            outputs.add(Output(addr, int(seq_no), int(amount)))

        result = {
            f.IDENTIFIER.nm: request.identifier,
            f.REQ_ID.nm: request.reqId,
            OUTPUTS: outputs.sorted_list
        }
        if proof:
            result[STATE_PROOF] = proof

        result.update(request.operation)
        return result
Пример #14
0
def test_token_req_handler_update_state_XFER_PUBLIC_success(
        helpers, addresses, xfer_handler_a):
    [address1, address2] = addresses
    seq_no = 1

    inputs = [{"source": utxo_from_addr_and_seq_no(address1, seq_no)}]
    outputs = [{"address": address2, "amount": 40}]
    request = helpers.request.transfer(inputs, outputs)
    txn = reqToTxn(request)
    append_txn_metadata(txn, seq_no=seq_no)

    xfer_handler_a.dynamic_validation(request)
    xfer_handler_a.update_state(txn, None, request)

    state_key = TokenStaticHelper.create_state_key(
        libsovtoken_address_to_address(address1), seq_no)
    utxo_cache = xfer_handler_a.database_manager.get_store(UTXO_CACHE_LABEL)
    key = utxo_cache._create_key(
        Output(libsovtoken_address_to_address(address1), seq_no, 60))
    assert utxo_cache._store._has_key(key)
    try:
        xfer_handler_a.state.get(state_key, False)
    except Exception:
        pytest.fail("This state key isn't in the state")
Пример #15
0
 def spend_input(state, utxo_cache, address, seq_no, is_committed=False):
     state_key = TokenReqHandler.create_state_key(address, seq_no)
     state.set(state_key, b'')
     utxo_cache.spend_output(Output(address, seq_no, None),
                             is_committed=is_committed)
Пример #16
0
def gen_outputs(num):
    return [
        Output(randomString(32), random.randint(1000, 10000),
               random.randint(100, 500)) for i in range(num)
    ]
Пример #17
0
def test_create_key(utxo_cache):
    output = Output(VALID_ADDR_1, 10, 10)
    key = utxo_cache._create_key(output)
    assert key == '6baBEYA94sAphWBA5efEsaA6X2wCdyaH7PXuBtv2H5S1'
Пример #18
0
def test_spend_output_fail_output_not_in_cache(utxo_cache):
    output = Output(VALID_ADDR_1, 10, 10)
    with pytest.raises(UTXOError):
        utxo_cache.spend_output(output)
Пример #19
0
def test_token_req_handler_add_new_output_success(helpers, token_handler_a):
    address = helpers.wallet.create_address()
    token_handler_a._add_new_output(Output(address, 8, 350))
    unspent_outputs = token_handler_a.utxo_cache.get_unspent_outputs(address)
    assert unspent_outputs == [Output(address, 8, 350)]
Пример #20
0
def test_token_req_handler_onBatchRejected_success(addresses, token_handler_a):
    address1 = addresses[0]
    token_handler_a._add_new_output(Output(address1, 40, 100))
    token_handler_a.onBatchRejected()
    assert token_handler_a.utxo_cache.un_committed == []
Пример #21
0
def test_outputs_in_order():
    o1 = Output('a', 1, 8)
    o2 = Output('a', 2, 9)
    o3 = Output('a', 9, 10)
    o4 = Output('a', 22, 11)
    o5 = Output('b', 3, 3)
    o6 = Output('b', 6, 6)
    o7 = Output('b', 4, 7)

    sr = SortedItems()
    sr.add(o6)
    sr.add(o5)
    sr.add(o2)
    sr.add(o7)
    sr.add(o1)
    sr.add(o4)
    sr.add(o3)

    assert sr.sorted_list == [Output(address='a', seq_no=1, value=8), Output(address='a', seq_no=2, value=9),
                              Output(address='b', seq_no=3, value=3), Output(address='b', seq_no=4, value=7),
                              Output(address='b', seq_no=6, value=6), Output(address='a', seq_no=9, value=10),
                              Output(address='a', seq_no=22, value=11)]

    outputs = [Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=312, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=313, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=314, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=315, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=316, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=319, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=317, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=321, value=1),
               Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=318, value=1)]

    si = SortedItems()
    for o in outputs:
        si.add(o)

    assert si.sorted_list == [Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=312, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=313, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=314, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=315, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=316, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=317, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=318, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=319, value=1),
                              Output(address='2w3WMmR92ijMH3ZV9qNoAUh1i7HjCyqVbBt7e771DdwEWL1K2W', seq_no=321, value=1)]