コード例 #1
0
def test_paymentchannel_typical_zeroconf():
    # Create mocked dependencies
    bc = mock.MockBlockchain()
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(), bc)
    db = database.Sqlite3Database(":memory:")

    # Link the mock blockchain to the mock payment channel server as it is a
    # non-injected dependency.
    mock.MockPaymentChannelServer.blockchain = bc
    # Clear mock payment channel server channels.
    mock.MockPaymentChannelServer.channels = {}

    # Open a payment channel with 100000 deposit, default expiration, and 30000 fee
    pc = paymentchannel.PaymentChannel.open(db, wallet, bc, 'mock://test',
                                            100000, DEFAULT_EXPIRATION, 30000,
                                            True)

    # Assert payment channel properties
    expected_state = {}
    expected_state['url'] = "mock://test/" + pc.deposit_txid
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['ready'] = True
    expected_state['balance'] = 100000
    expected_state['deposit'] = 100000
    expected_state['fee'] = 30000
    expected_state['creation_time'] = lambda pc: pc.creation_time > 0
    expected_state['expiration_time'] = int(pc.creation_time +
                                            DEFAULT_EXPIRATION)
    expected_state['expired'] = False
    expected_state['refund_tx'] = lambda pc: pc.refund_tx
    expected_state['refund_txid'] = lambda pc: pc.refund_txid
    expected_state['deposit_tx'] = lambda pc: pc.deposit_tx
    expected_state['deposit_txid'] = lambda pc: pc.deposit_txid
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_paymentchannel_state(expected_state, pc)

    # Make a few payments and close the channel
    pc.pay(1)
    pc.pay(1)
    pc.pay(1)
    pc.close()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['ready'] = False
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    expected_state['balance'] = 96998
    expected_state['spend_txid'] = lambda pc: pc.spend_txid
    assert_paymentchannel_state(expected_state, pc)
コード例 #2
0
def test_paymentchannel_typical():
    # Create mocked dependencies
    bc = mock.MockBlockchain()
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(), bc)
    db = database.Sqlite3Database(":memory:")

    # Link the mock blockchain to the mock payment channel server as it is a
    # non-injected dependency.
    mock.MockPaymentChannelServer.blockchain = bc
    # Clear mock payment channel server channels.
    mock.MockPaymentChannelServer.channels = {}

    # Open a payment channel with 100000 deposit, default expiration, and 30000 fee
    pc = paymentchannel.PaymentChannel.open(db, wallet, bc, 'mock://test',
                                            100000, DEFAULT_EXPIRATION, 30000,
                                            False)

    # Assert payment channel properties
    expected_state = {}
    expected_state['url'] = "mock://test/" + pc.deposit_txid
    expected_state[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_DEPOSIT
    expected_state['ready'] = False
    expected_state['balance'] = 100000
    expected_state['deposit'] = 100000
    expected_state['fee'] = 30000
    expected_state['creation_time'] = lambda pc: pc.creation_time > 0
    expected_state['expiration_time'] = int(pc.creation_time +
                                            DEFAULT_EXPIRATION)
    expected_state['expired'] = False
    expected_state['refund_tx'] = lambda pc: pc.refund_tx
    expected_state['refund_txid'] = lambda pc: pc.refund_txid
    expected_state['deposit_tx'] = lambda pc: pc.deposit_tx
    expected_state['deposit_txid'] = lambda pc: pc.deposit_txid
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_paymentchannel_state(expected_state, pc)

    # Check database
    with db:
        assert db.list() == [pc.url]
        assert db.read(pc.url)

    # Check blockchain
    assert bc.check_confirmed(pc.deposit_txid) is False
    assert bc.lookup_tx(pc.deposit_txid) == pc.deposit_tx

    # Try premature payment
    with pytest.raises(paymentchannel.NotReadyError):
        pc.pay(1)

    # Try premature close
    with pytest.raises(paymentchannel.NotReadyError):
        pc.close()

    # Sync payment channel
    pc.sync()
    expected_state[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_DEPOSIT
    expected_state['ready'] = False
    assert_paymentchannel_state(expected_state, pc)

    # Confirm deposit
    bc.mock_confirm(pc.deposit_txid)

    # Sync payment channel
    pc.sync()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['ready'] = True
    assert_paymentchannel_state(expected_state, pc)

    # Try excess payment
    with pytest.raises(paymentchannel.InsufficientBalanceError):
        pc.pay(pc.balance + 1)

    # Try premature close
    with pytest.raises(paymentchannel.NoPaymentError):
        pc.close()

    # Make regular payments
    assert pc.pay(1500)
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    expected_state['balance'] = 97000
    assert_paymentchannel_state(expected_state, pc)
    assert pc.pay(1)
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    expected_state['balance'] = 96999
    assert_paymentchannel_state(expected_state, pc)
    assert pc.pay(15)
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    expected_state['balance'] = 96984
    assert_paymentchannel_state(expected_state, pc)
    assert pc.pay(20000)
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    expected_state['balance'] = 76984
    assert_paymentchannel_state(expected_state, pc)

    # Close payment channel
    pc.close()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['ready'] = False
    expected_state['spend_txid'] = str(mock.MockPaymentChannelServer.channels[
        pc.deposit_txid]['payment_tx'].hash)
    assert_paymentchannel_state(expected_state, pc)

    # Sync payment channel
    pc.sync()
    assert_paymentchannel_state(expected_state, pc)

    # Confirm spend
    bc.mock_confirm(pc.spend_txid)

    # Sync payment channel
    pc.sync()
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['spend_tx'] = mock.MockPaymentChannelServer.channels[
        pc.deposit_txid]['payment_tx'].to_hex()
    assert_paymentchannel_state(expected_state, pc)

    # Try payment on closed channel
    with pytest.raises(paymentchannel.ClosedError):
        pc.pay(1)
コード例 #3
0
def test_paymentchannel_expiration():
    # Create mocked dependencies
    bc = mock.MockBlockchain()
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(), bc)
    db = database.Sqlite3Database(":memory:")

    # Link the mock blockchain to the mock payment channel server as it is a
    # non-injected dependency.
    mock.MockPaymentChannelServer.blockchain = bc
    # Clear mock payment channel server channels.
    mock.MockPaymentChannelServer.channels = {}

    # Open a payment channel with 100000 deposit, default expiration, and 30000 fee
    pc = paymentchannel.PaymentChannel.open(db, wallet, bc, 'mock://test',
                                            100000, DEFAULT_EXPIRATION, 30000,
                                            False)

    # Confirm the deposit tx
    bc.mock_confirm(pc.deposit_txid)
    pc.sync()

    # Assert payment channel properties
    expected_state = {}
    expected_state['url'] = "mock://test/" + pc.deposit_txid
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['ready'] = True
    expected_state['balance'] = 100000
    expected_state['deposit'] = 100000
    expected_state['fee'] = 30000
    expected_state['creation_time'] = lambda pc: pc.creation_time > 0
    expected_state['expiration_time'] = int(pc.creation_time +
                                            DEFAULT_EXPIRATION)
    expected_state['expired'] = False
    expected_state['refund_tx'] = lambda pc: pc.refund_tx
    expected_state['refund_txid'] = lambda pc: pc.refund_txid
    expected_state['deposit_tx'] = lambda pc: pc.deposit_tx
    expected_state['deposit_txid'] = lambda pc: pc.deposit_txid
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_paymentchannel_state(expected_state, pc)

    # Make a few payments
    pc.pay(1)
    pc.pay(1)
    pc.pay(1)

    # Check payment channel properties
    expected_state['balance'] = 96998
    expected_state['expired'] = False
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    assert_paymentchannel_state(expected_state, pc)

    # Monkey-patch time.time() for expiration
    orig_time_time = time.time
    time.time = lambda: pc.expiration_time + paymentchannel.PaymentChannel.REFUND_BROADCAST_TIME_OFFSET + 1

    # Check payment channel properties
    expected_state['expired'] = True
    assert_paymentchannel_state(expected_state, pc)

    # Sync to trigger a refund
    pc.sync()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['ready'] = False
    expected_state['expired'] = True
    expected_state['spend_txid'] = lambda pc: pc.refund_txid
    assert_paymentchannel_state(expected_state, pc)

    # Confirm refund tx
    bc.mock_confirm(pc.refund_txid)

    # Sync
    pc.sync()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['spend_tx'] = lambda pc: pc.refund_tx

    # Restore time.time()
    time.time = orig_time_time
コード例 #4
0
def test_paymentchannel_serverside_close():
    # Create mocked dependencies
    bc = mock.MockBlockchain()
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(), bc)
    db = database.Sqlite3Database(":memory:")

    # Link the mock blockchain to the mock payment channel server as it is a
    # non-injected dependency.
    mock.MockPaymentChannelServer.blockchain = bc
    # Clear mock payment channel server channels.
    mock.MockPaymentChannelServer.channels = {}

    # Open a payment channel with 100000 deposit, 86400 seconds expiration, and 30000 fee
    pc = paymentchannel.PaymentChannel.open(db, wallet, bc, 'mock://test',
                                            100000, 86400, 30000, False)

    # Confirm the deposit tx
    bc.mock_confirm(pc.deposit_txid)
    pc.sync()

    # Assert payment channel properties
    expected_state = {}
    expected_state['url'] = "mock://test/" + pc.deposit_txid
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['ready'] = True
    expected_state['balance'] = 100000
    expected_state['deposit'] = 100000
    expected_state['fee'] = 30000
    expected_state['creation_time'] = lambda pc: pc.creation_time > 0
    expected_state['expiration_time'] = int(pc.creation_time + 86400)
    expected_state['expired'] = False
    expected_state['refund_tx'] = lambda pc: pc.refund_tx
    expected_state['refund_txid'] = lambda pc: pc.refund_txid
    expected_state['deposit_tx'] = lambda pc: pc.deposit_tx
    expected_state['deposit_txid'] = lambda pc: pc.deposit_txid
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_paymentchannel_state(expected_state, pc)

    # Make a few payments
    pc.pay(1)
    pc.pay(1)
    pc.pay(1)

    # Check payment channel properties
    expected_state['balance'] = 96998
    expected_state['expired'] = False
    expected_state['payment_tx'] = lambda pc: pc.payment_tx
    assert_paymentchannel_state(expected_state, pc)

    # Close the channel server-side by broadcasting the last payment tx
    bc.broadcast_tx(mock.MockPaymentChannelServer.channels[pc.deposit_txid]
                    ['payment_tx'].to_hex())

    # Sync
    pc.sync()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['ready'] = False
    expected_state['spend_txid'] = lambda pc: pc.spend_txid
    assert_paymentchannel_state(expected_state, pc)

    # Confirm payment tx
    bc.mock_confirm(pc.spend_txid)

    # Sync
    pc.sync()

    # Check payment channel properties
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['spend_tx'] = lambda pc: pc.spend_tx
    assert_paymentchannel_state(expected_state, pc)
コード例 #5
0
def test_statemachine_create():
    """Test state machine transitions from initial state OPENING.

        Valid transitions:
            OPENING -> CONFIRMING_DEPOSIT   via create()
            OPENING -> READY                via create()

        Invalid transitions:
            OPENING -> OUTSTANDING          via pay()
            OPENING -> READY                via pay_ack() or pay_nack()
            OPENING -> CONFIRMING_SPEND     via close()
            OPENING -> CLOSED               via finalize()

    """
    # Create state machine
    model_data = {
        'url': 'test',
    }
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(),
                                             mock.MockBlockchain())
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Expected state machine state
    expected_state = {}
    expected_state['state'] = statemachine.PaymentChannelState.OPENING
    expected_state['balance_amount'] = None
    expected_state['deposit_amount'] = None
    expected_state['fee_amount'] = None
    expected_state['creation_time'] = None
    expected_state['expiration_time'] = None
    expected_state['deposit_tx_utxo_index'] = None
    expected_state['deposit_tx'] = None
    expected_state['deposit_txid'] = None
    expected_state['deposit_txid_signature'] = None
    expected_state['refund_tx'] = None
    expected_state['refund_txid'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None

    # Assert state machine state
    assert_statemachine_state(expected_state, sm)

    # Check invalid transition OPENING -> READY via confirm()
    with pytest.raises(statemachine.StateTransitionError):
        sm.confirm()
    # Check invalid transition OPENING -> OUTSTANDING via pay()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay(1)
    # Check invalid transition OPENING -> READY via pay_ack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_ack()
    # Check invalid transition OPENING -> READY via pay_nack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_nack()
    # Check invalid transition OPENING -> CONFIRMING_SPEND via close()
    with pytest.raises(statemachine.StateTransitionError):
        sm.close(None)
    # Check invalid transition OPENING -> CLOSED via finalize()
    with pytest.raises(statemachine.StateTransitionError):
        sm.finalize("")

    # Channel parameters
    merchant_public_key = mock.MockPaymentChannelServer.PRIVATE_KEY.public_key.to_hex(
    )
    deposit_amount = 100000
    expiration_time = 1450223410
    fee_amount = 10000

    # Check valid transition OPENING -> CONFIRMING_DEPOSIT via create()
    (deposit_tx, redeem_script) = sm.create(merchant_public_key,
                                            deposit_amount,
                                            expiration_time,
                                            fee_amount,
                                            zeroconf=False)
    assert deposit_tx == "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100efbcffe9c800c517232c5f4417482a650c8e23a5171a3d02f94961355a8c232a022070bef91a8c956e70b673631806971994e8d0745977961c3972bbbaebc0254957012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0168b901000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    assert redeem_script == "63210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac"  # nopep8
    expected_state[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_DEPOSIT
    expected_state['balance_amount'] = 100000
    expected_state['deposit_amount'] = 100000
    expected_state['fee_amount'] = 10000
    expected_state['creation_time'] = lambda sm: sm.creation_time > 0
    expected_state['expiration_time'] = 1450223410
    expected_state['deposit_tx_utxo_index'] = 0
    expected_state[
        'deposit_tx'] = "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100efbcffe9c800c517232c5f4417482a650c8e23a5171a3d02f94961355a8c232a022070bef91a8c956e70b673631806971994e8d0745977961c3972bbbaebc0254957012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0168b901000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    expected_state[
        'deposit_txid'] = "ec822c4539a8b12f80fe921669b79adf6439ede3669ee4d42d1199d1f9868e72"
    expected_state[
        'deposit_txid_signature'] = "3045022100fa23cba0e65d48ddf2e98fa64bb578f9ae3642f416462f3f991162b56dca428702205dbcf1f067034cf31564fa6c665397c2fb1c99a47afe1105fc1847e07c5ceb41"  # nopep8
    expected_state[
        'refund_tx'] = "0100000001728e86f9d199112dd4e49e66e3ed3964df9ab7691692fe802fb1a839452c82ec000000009c473044022025a91aed42aa97486a5592face6e17f0249c90d8ca16d8fcf9db1bf3201e6e4002206374bb2fa72f424afa702e23fc161961c7ba539727093abf0caf079eef38686f0101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacfeffffff0158920100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'refund_txid'] = "5efe2f7db01b74efc71054ead6ad96203d55f6cbf8172039b718c244200f7127"
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Check valid transition OPENING -> READY via create() with zeroconf=True
    (deposit_tx, redeem_script) = sm.create(merchant_public_key,
                                            deposit_amount,
                                            expiration_time,
                                            fee_amount,
                                            zeroconf=True)
    assert deposit_tx == "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100efbcffe9c800c517232c5f4417482a650c8e23a5171a3d02f94961355a8c232a022070bef91a8c956e70b673631806971994e8d0745977961c3972bbbaebc0254957012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0168b901000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    assert redeem_script == "63210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.READY
    assert_statemachine_state(expected_state, sm)
コード例 #6
0
def test_statemachine_finalize():
    """Test state machine finalize.

    Valid transitions:
        CONFIRMING_SPEND -> CLOSED  via finalize()
        READY -> CLOSED             via finalize()

    """
    # Create state machine
    model_data = {
        'url':
        'test',
        'state':
        statemachine.PaymentChannelState.CONFIRMING_SPEND,
        'creation_time':
        42,
        'deposit_tx':
        bitcoin.Transaction.from_hex(
            "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"
        ),  # nopep8
        'refund_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
        ),  # nopep8
        'payment_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"
        ),  # nopep8
        'spend_tx':
        None,
        'spend_txid':
        None,
        'min_output_amount':
        1000,
    }
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(),
                                             mock.MockBlockchain())
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Assert state machine state
    expected_state = {}
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['balance_amount'] = 78998
    expected_state['deposit_amount'] = 100000
    expected_state['fee_amount'] = 10000
    expected_state['creation_time'] = lambda sm: sm.creation_time > 0
    expected_state['expiration_time'] = 1450223410
    expected_state['deposit_tx_utxo_index'] = 0
    expected_state[
        'deposit_tx'] = "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    expected_state[
        'deposit_txid'] = "7e1a558c84abd5aaf57999557f4a7205d4b69241b7c9cab6c0795fdd663a51ef"
    expected_state[
        'deposit_txid_signature'] = "30450221008f51b6565a8ee67c32529ed840116c44e1f60a628c51ac59720cc8c6df1b5eab02204ccc32c89f81425f483c64c6f8dd77e57eefd3b6a5b7548d1875f5ef3f86cf27"  # nopep8
    expected_state[
        'refund_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'refund_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    expected_state[
        'payment_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_statemachine_state(expected_state, sm)

    # Valid finalize with refund tx
    sm.finalize(
        "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
    )  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['balance_amount'] = 100000
    expected_state[
        'spend_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'spend_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Valid finalize with payment tx
    sm.finalize(
        "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e00000000e5483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01483045022100ee02cd312b33e78d7dd6d9044f47577a224038fa731ad34ca0ea4870575d6223022073124ecd6c63042ec6a99b34ba6d926524c6491fb1440eaa21177329f542e97501514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"
    )  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['balance_amount'] = 78998
    expected_state[
        'spend_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e00000000e5483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01483045022100ee02cd312b33e78d7dd6d9044f47577a224038fa731ad34ca0ea4870575d6223022073124ecd6c63042ec6a99b34ba6d926524c6491fb1440eaa21177329f542e97501514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state[
        'spend_txid'] = "247412297242f1849a9fd8ef7b1acabdb07465da32ab5240d8ba425876a43104"
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Invalid finalize with wrong refund tx
    with pytest.raises(statemachine.InvalidTransactionError):
        sm.finalize(
            "010000000191efdfed621ebd3b3ad4044097086c5df75589f424261bfec6371e186a86725d010000009c47304402204ececbed85c20f3bae5393d68d1717cb258a9532e9976bf1e75103b1876427010220273c1440fff7b330d41407f83f871fcaf178ea0a413045424a48825821736aae0101004c50632102f1fff97def324ddea032fed4c8249113b8dce12aaf614d11bb833e587072c8a9ad6704a9a07056b1756821026179020dba5ad8275cf6389a85a00c08f3597bb8617af8148f249a4cd719ab39ac0000000001888a0100000000001976a914314d768ce14fc1f5dffdac1e4a0ed13705d4a4a688aca9a07056"
        )  # nopep8

    # Invalid finalize with wrong payment tx
    with pytest.raises(statemachine.InvalidTransactionError):
        sm.finalize(
            "010000000191efdfed621ebd3b3ad4044097086c5df75589f424261bfec6371e186a86725d01000000e4473044022049d1f41a867aa84266a1f5d2f6283d2b1e6ee07d068a098615d7a7868a96ed78022060c798cbb4740277cb095c399fb10ebd2716894c203527b0e6e3ed797400d10701483045022100de7c4c35c263cc2e1df1f2b06925225a72b9cb28e3b8bae4db7b078a1e4ac25c022031103dbe8993e94daa119d4c78e0bf52d3513e152d8b5bc192f8cb26ac3c683901514c50632102f1fff97def324ddea032fed4c8249113b8dce12aaf614d11bb833e587072c8a9ad6704a9a07056b1756821026179020dba5ad8275cf6389a85a00c08f3597bb8617af8148f249a4cd719ab39acffffffff02a0860100000000001976a914ffffb9d45c6cb46133f55a83c2fde9edb1c5f50688ace8030000000000001976a914314d768ce14fc1f5dffdac1e4a0ed13705d4a4a688ac00000000"
        )  # nopep8

    # Invalid finalize with half-signed payment tx
    with pytest.raises(statemachine.InvalidTransactionError):
        sm.finalize(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"
        )  # nopep8

    # Invalid finalize with invalid tx
    with pytest.raises(statemachine.InvalidTransactionError):
        sm.finalize(
            "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"
        )  # nopep8

    # Valid transition CLOSED -> CLOSED via finalize()
    # Finalize with valid payment
    sm.finalize(
        "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e00000000e5483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01483045022100ee02cd312b33e78d7dd6d9044f47577a224038fa731ad34ca0ea4870575d6223022073124ecd6c63042ec6a99b34ba6d926524c6491fb1440eaa21177329f542e97501514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"
    )  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['balance_amount'] = 78998
    expected_state[
        'spend_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e00000000e5483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01483045022100ee02cd312b33e78d7dd6d9044f47577a224038fa731ad34ca0ea4870575d6223022073124ecd6c63042ec6a99b34ba6d926524c6491fb1440eaa21177329f542e97501514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state[
        'spend_txid'] = "247412297242f1849a9fd8ef7b1acabdb07465da32ab5240d8ba425876a43104"
    assert_statemachine_state(expected_state, sm)
    # Finalize with refund
    sm.finalize(
        "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
    )  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    expected_state['balance_amount'] = 100000
    expected_state[
        'spend_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'spend_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    assert_statemachine_state(expected_state, sm)

    # Invalid transition CLOSED -> OUTSTANDING via pay()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay(1)
    # Invalid transition CLOSED -> READY via pay_ack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_ack()
    # Invalid transition CLOSED -> READY via pay_nack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_nack()
    # Invalid transition CLOSED -> CONFIRMING_DEPOSIT via close()
    with pytest.raises(statemachine.StateTransitionError):
        sm.close(None)
コード例 #7
0
def test_statemachine_close():
    """Test state machine close.

    Valid transitions:
        READY -> CONFIRMING_SPEND           via close()
        OUTSTANDING -> CONFIRMING_SPEND     via close()

    """
    # Create state machine
    model_data = {
        'url':
        'test',
        'state':
        statemachine.PaymentChannelState.READY,
        'creation_time':
        42,
        'deposit_tx':
        bitcoin.Transaction.from_hex(
            "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"
        ),  # nopep8
        'refund_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
        ),  # nopep8
        'payment_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"
        ),  # nopep8
        'spend_tx':
        None,
        'spend_txid':
        None,
        'min_output_amount':
        1000,
    }
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(),
                                             mock.MockBlockchain())
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Assert state machine state
    expected_state = {}
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 78998
    expected_state['deposit_amount'] = 100000
    expected_state['fee_amount'] = 10000
    expected_state['creation_time'] = lambda sm: sm.creation_time > 0
    expected_state['expiration_time'] = 1450223410
    expected_state['deposit_tx_utxo_index'] = 0
    expected_state[
        'deposit_tx'] = "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    expected_state[
        'deposit_txid'] = "7e1a558c84abd5aaf57999557f4a7205d4b69241b7c9cab6c0795fdd663a51ef"
    expected_state[
        'deposit_txid_signature'] = "30450221008f51b6565a8ee67c32529ed840116c44e1f60a628c51ac59720cc8c6df1b5eab02204ccc32c89f81425f483c64c6f8dd77e57eefd3b6a5b7548d1875f5ef3f86cf27"  # nopep8
    expected_state[
        'refund_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'refund_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    expected_state[
        'payment_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_statemachine_state(expected_state, sm)

    # Valid transition READY -> CONFIRMING_SPEND via close(None)
    sm.close(None)
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state['spend_txid'] = None
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Valid transition READY -> CONFIRMING_SPEND via close(<txid>)
    sm.close(
        "afb48fb7c8f09a846b44df91f0704464785e61ef14da34e8a9b95cb0c1866968")
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state[
        'spend_txid'] = "afb48fb7c8f09a846b44df91f0704464785e61ef14da34e8a9b95cb0c1866968"
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['spend_txid'] = None

    # Valid transition OUTSTANDING -> CONFIRMING_SPEND via close(<txid>)
    sm.pay(1)
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)
    sm.close(
        "afb48fb7c8f09a846b44df91f0704464785e61ef14da34e8a9b95cb0c1866968")
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    expected_state[
        'spend_txid'] = "afb48fb7c8f09a846b44df91f0704464785e61ef14da34e8a9b95cb0c1866968"
    assert_statemachine_state(expected_state, sm)
コード例 #8
0
def test_statemachine_pay():
    """Test state machine paying, transitions from
            READY -> OUTSTANDING -> READY.
    """
    # Create state machine
    model_data = {
        'url':
        'test',
        'state':
        statemachine.PaymentChannelState.READY,
        'creation_time':
        42,
        'deposit_tx':
        bitcoin.Transaction.from_hex(
            "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"
        ),  # nopep8
        'refund_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
        ),  # nopep8
        'payment_tx':
        None,
        'spend_tx':
        None,
        'spend_txid':
        None,
        'min_output_amount':
        1000,
    }
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(),
                                             mock.MockBlockchain())
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Assert state machine state
    expected_state = {}
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 100000
    expected_state['deposit_amount'] = 100000
    expected_state['fee_amount'] = 10000
    expected_state['creation_time'] = lambda sm: sm.creation_time > 0
    expected_state['expiration_time'] = 1450223410
    expected_state['deposit_tx_utxo_index'] = 0
    expected_state[
        'deposit_tx'] = "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    expected_state[
        'deposit_txid'] = "7e1a558c84abd5aaf57999557f4a7205d4b69241b7c9cab6c0795fdd663a51ef"
    expected_state[
        'deposit_txid_signature'] = "30450221008f51b6565a8ee67c32529ed840116c44e1f60a628c51ac59720cc8c6df1b5eab02204ccc32c89f81425f483c64c6f8dd77e57eefd3b6a5b7548d1875f5ef3f86cf27"  # nopep8
    expected_state[
        'refund_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'refund_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_statemachine_state(expected_state, sm)

    # Test initial payment with amount 1
    payment_tx = sm.pay(1)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100e0758baae39dfb1c4402c37a3382ae96a34786734265ea2bc94977299dfd2573022047957838a067ad0bbd575ec219e71c1c750685f6a70da3baa9d294c8a8202d7b01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff02e8030000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488aca0860100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # But nack it
    sm.pay_nack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    assert_statemachine_state(expected_state, sm)

    # Test initial payment with amount 1, and acknowledge it
    payment_tx = sm.pay(1)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100e0758baae39dfb1c4402c37a3382ae96a34786734265ea2bc94977299dfd2573022047957838a067ad0bbd575ec219e71c1c750685f6a70da3baa9d294c8a8202d7b01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff02e8030000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488aca0860100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # Acknowledge it
    sm.pay_ack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 99000
    expected_state['payment_tx'] = payment_tx
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    expected_state['balance_amount'] = 100000
    expected_state['payment_tx'] = None

    # Test initial payment with amount PAYMENT_TX_MIN_OUTPUT_AMOUNT + 2
    payment_tx = sm.pay(1001)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009b47304402201638d4ca0760ce75d9aaf514f870076f2d68c43bcfcbed308ffe983b9d6f062e022036a5b377f2e32810bc235aaab2a885055fb6ff0348e25a8720b1c48ec228d3a301514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff02e9030000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac9f860100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # Acknowledge it
    sm.pay_ack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 98999
    expected_state['payment_tx'] = payment_tx
    assert_statemachine_state(expected_state, sm)

    # Test subsequent payment of 20000
    payment_tx = sm.pay(20000)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c4830450221009d19b49f540af728a3ce978bad1c4bf6d162a6f24f74dd11bde72e706521c08a02200ce0dd828018741434f74ee7a4c7bfb9e74c56d20246966b3a893d8bb13c871101514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff0209520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7f380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # But nack it
    sm.pay_nack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    assert_statemachine_state(expected_state, sm)

    # Test subsequent payment of 20000
    payment_tx = sm.pay(20000)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c4830450221009d19b49f540af728a3ce978bad1c4bf6d162a6f24f74dd11bde72e706521c08a02200ce0dd828018741434f74ee7a4c7bfb9e74c56d20246966b3a893d8bb13c871101514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff0209520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7f380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # Acknowledge it
    sm.pay_ack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 78999
    expected_state['payment_tx'] = payment_tx
    assert_statemachine_state(expected_state, sm)

    # Test excess payment of 80000
    with pytest.raises(statemachine.InsufficientBalanceError):
        payment_tx = sm.pay(80000)

    # Test excess payment of 79000
    with pytest.raises(statemachine.InsufficientBalanceError):
        payment_tx = sm.pay(79000)

    # Test subsequent payment of 1
    payment_tx = sm.pay(1)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c483045022100bd2a89446c9d5985ee711747f35b8e367a90eb13970aec1b3a3ad11e01da7ac602205405fe99d5fe590fb13f0b7698e306e3bbcdd83855e156eb8e9a8901f887229f01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff020a520000000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ac7e380100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # Acknowledge it
    sm.pay_ack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 78998
    expected_state['payment_tx'] = payment_tx
    assert_statemachine_state(expected_state, sm)

    # Test remainder payment
    payment_tx = sm.pay(78998)
    assert payment_tx == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009b4730440220064f50737f894e97d8f1c49b07f9206caacfeeb5f6fd0ff4a0fe1cce5668cdbf02207bbe2a71627d38c1c524c7b68b4c77ffb7b5edb78c0cb1dd8516ddf7d766acfc01514c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacffffffff02a0860100000000001976a914a5f30391271dfccc133d321960ffe1dccc88e1b488ace8030000000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac00000000"  # nopep8
    expected_state['state'] = statemachine.PaymentChannelState.OUTSTANDING
    assert_statemachine_state(expected_state, sm)

    # Acknowledge it
    sm.pay_ack()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    expected_state['balance_amount'] = 0
    expected_state['payment_tx'] = payment_tx
    assert_statemachine_state(expected_state, sm)
コード例 #9
0
def test_statemachine_confirm():
    """Test state machine transitions from state CONFIRMING_DEPOSIT.

        Valid transitions:
            CONFIRMING_DEPOSIT -> READY             via confirm()
            CONFIRMING_DEPOSIT -> CONFIRMING_SPEND  via close()
            CONFIRMING_DEPOSIT -> CLOSED            via finalize()

        Invalid transitions:
            CONFIRMING_DEPOSIT -> READY             via pay_ack() or pay_nack()
            CONFIRMING_DEPOSIT -> OUTSTANDING       via pay()

    """
    # Create state machine
    model_data = {
        'url':
        'test',
        'state':
        statemachine.PaymentChannelState.CONFIRMING_DEPOSIT,
        'creation_time':
        42,
        'deposit_tx':
        bitcoin.Transaction.from_hex(
            "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"
        ),  # nopep8
        'refund_tx':
        bitcoin.Transaction.from_hex(
            "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
        ),  # nopep8
        'payment_tx':
        None,
        'spend_tx':
        None,
        'spend_txid':
        None,
        'min_output_amount':
        1000,
    }
    wallet = walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(),
                                             mock.MockBlockchain())
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Assert state machine state
    expected_state = {}
    expected_state[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_DEPOSIT
    expected_state['balance_amount'] = 100000
    expected_state['deposit_amount'] = 100000
    expected_state['fee_amount'] = 10000
    expected_state['creation_time'] = lambda sm: sm.creation_time > 0
    expected_state['expiration_time'] = 1450223410
    expected_state['deposit_tx_utxo_index'] = 0
    expected_state[
        'deposit_tx'] = "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8
    expected_state[
        'deposit_txid'] = "7e1a558c84abd5aaf57999557f4a7205d4b69241b7c9cab6c0795fdd663a51ef"
    expected_state[
        'deposit_txid_signature'] = "30450221008f51b6565a8ee67c32529ed840116c44e1f60a628c51ac59720cc8c6df1b5eab02204ccc32c89f81425f483c64c6f8dd77e57eefd3b6a5b7548d1875f5ef3f86cf27"  # nopep8
    expected_state[
        'refund_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'refund_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    expected_state['payment_tx'] = None
    expected_state['spend_tx'] = None
    expected_state['spend_txid'] = None
    assert_statemachine_state(expected_state, sm)

    # Check invalid transition CONFIRMING_DEPOSIT -> OUTSTANDING via pay()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay(1)
    # Check invalid transition CONFIRMING_DEPOSIT -> READY via pay_ack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_ack()
    # Check invalid transition CONFIRMING_DEPOSIT -> READY via pay_nack()
    with pytest.raises(statemachine.StateTransitionError):
        sm.pay_nack()

    # Check valid transition CONFIRMING_DEPOSIT -> READY via confirm()
    sm.confirm()
    expected_state['state'] = statemachine.PaymentChannelState.READY
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Check valid transition CONFIRMING_DEPOSIT -> CONFIRMING_SPEND via close()
    sm.close(
        "2654e56291a542e99d26e1d2ba34d455031517453b6c7ae256c62e151ddc41cc")
    expected_state[
        'spend_txid'] = "2654e56291a542e99d26e1d2ba34d455031517453b6c7ae256c62e151ddc41cc"
    expected_state['state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    assert_statemachine_state(expected_state, sm)

    # Reset state machine
    model = statemachine.PaymentChannelModel(**model_data)
    sm = statemachine.PaymentChannelStateMachine(model, wallet)

    # Check valid transition OPENING -> CLOSED via finalize()
    sm.finalize(
        "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"
    )  # nopep8
    expected_state[
        'spend_tx'] = "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009c47304402207c866a5d8d46c767975c95b9fa65051578898445c85f367c4d6b56c6b795491102202db45315bfd27aa19bd7156aa70aed48ebe331c88297711ff675da5ff069f7b90101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dac0000000001888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8
    expected_state[
        'spend_txid'] = "e49cef2fbaf7b6590eb502e4b143f24d5d95ca2e255b166f3b40bef786a32bba"
    expected_state['state'] = statemachine.PaymentChannelState.CLOSED
    assert_statemachine_state(expected_state, sm)
コード例 #10
0
def test_paymentchannelclient():
    # Create mocked dependencies
    wallet = mock.MockTwo1Wallet()
    db = database.Sqlite3Database(":memory:")
    bc = mock.MockBlockchain()

    # Link the mock blockchain to the mock payment channel server as it is a
    # non-injected dependency.
    mock.MockPaymentChannelServer.blockchain = bc
    # Clear mock payment channel server channels.
    mock.MockPaymentChannelServer.channels = {}

    # Create a payment channel client
    pc = paymentchannelclient.PaymentChannelClient(wallet,
                                                   _database=db,
                                                   _blockchain=bc)

    # Check channel list
    assert pc.list() == []

    # Open a payment channel with 100000 deposit, default expiration, and 10000 fee
    url1 = pc.open('mock://test', 100000, DEFAULT_EXPIRATION, 10000, False)

    # Open a payment channel with 300000 deposit, 500000 seconds expiration, and 20000 fee
    url2 = pc.open('mock://test', 300000, 500000, 20000, True)

    # Check channel list
    assert len(pc.list()) == 2

    # Check url1 properties
    status = pc.status(url1)
    url1_expected_status = {}
    url1_expected_status[
        'url'] = lambda status: "mock://test/" + status.deposit_txid
    url1_expected_status[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_DEPOSIT
    url1_expected_status['ready'] = False
    url1_expected_status['balance'] = 100000
    url1_expected_status['deposit'] = 100000
    url1_expected_status['fee'] = 10000
    url1_expected_status[
        'creation_time'] = lambda status: status.creation_time > 0
    url1_expected_status['expiration_time'] = int(status.creation_time +
                                                  DEFAULT_EXPIRATION)
    url1_expected_status['expired'] = False
    url1_expected_status['deposit_txid'] = lambda status: status.deposit_txid
    url1_expected_status['spend_txid'] = None
    assert_paymentchannel_status(url1_expected_status, status)

    # Check url2 properties
    status = pc.status(url2)
    url2_expected_status = {}
    url2_expected_status[
        'url'] = lambda status: "mock://test/" + status.deposit_txid
    url2_expected_status['state'] = statemachine.PaymentChannelState.READY
    url2_expected_status['ready'] = True
    url2_expected_status['balance'] = 300000
    url2_expected_status['deposit'] = 300000
    url2_expected_status['fee'] = 20000
    url2_expected_status[
        'creation_time'] = lambda status: status.creation_time > 0
    url2_expected_status['expiration_time'] = int(status.creation_time +
                                                  500000)
    url2_expected_status['expired'] = False
    url2_expected_status['deposit_txid'] = lambda status: status.deposit_txid
    url2_expected_status['spend_txid'] = None
    assert_paymentchannel_status(url2_expected_status, status)

    # Try premature close on url1
    with pytest.raises(paymentchannel.NotReadyError):
        pc.close(url1)

    # Try premature pay on url1
    with pytest.raises(paymentchannel.NotReadyError):
        pc.pay(url1, 1)

    # Confirm url1 deposit
    bc.mock_confirm(pc.status(url1).deposit_txid)

    # Sync channels
    pc.sync()

    # Check url1 readiness
    status = pc.status(url1)
    url1_expected_status['state'] = statemachine.PaymentChannelState.READY
    url1_expected_status['ready'] = True
    assert_paymentchannel_status(url1_expected_status, status)

    # Try to pay to an invalid channel
    with pytest.raises(paymentchannelclient.NotFoundError):
        pc.pay("foo", 1)

    # Try to pay excess amount
    with pytest.raises(paymentchannel.InsufficientBalanceError):
        pc.pay(url1, 500000)

    # Try to close without payment
    with pytest.raises(paymentchannel.NoPaymentError):
        pc.close(url1)

    # Pay to both channels
    pc.pay(url1, 1500)
    pc.pay(url2, 3500)
    pc.pay(url1, 123)
    pc.pay(url2, 1)
    pc.pay(url1, 400)
    pc.pay(url2, 10000)
    pc.pay(url1, 20)
    pc.pay(url2, 3123)

    # Check url1 properties
    status = pc.status(url1)
    url1_expected_status['balance'] = 96457
    assert_paymentchannel_status(url1_expected_status, status)

    # Check url2 properties
    status = pc.status(url2)
    url2_expected_status['balance'] = 283376
    assert_paymentchannel_status(url2_expected_status, status)

    # Close url1
    pc.close(url1)

    # Check url1 properties
    status = pc.status(url1)
    url1_expected_status[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    url1_expected_status['ready'] = False
    url1_expected_status['spend_txid'] = str(
        mock.MockPaymentChannelServer.channels[
            status.deposit_txid]['payment_tx'].hash)
    assert_paymentchannel_status(url1_expected_status, status)

    # Confirm close
    bc.mock_confirm(status.spend_txid)

    # Sync
    pc.sync()

    # Check url1 properties
    status = pc.status(url1)
    url1_expected_status['state'] = statemachine.PaymentChannelState.CLOSED
    assert_paymentchannel_status(url1_expected_status, status)

    # Check url2 properties
    status = pc.status(url2)
    assert_paymentchannel_status(url2_expected_status, status)

    # Close url2 server-side
    bc.broadcast_tx(mock.MockPaymentChannelServer.channels[status.deposit_txid]
                    ['payment_tx'].to_hex())

    # Sync
    pc.sync()

    # Check url1 properties
    status = pc.status(url1)
    assert_paymentchannel_status(url1_expected_status, status)

    # Try pay after close on url1
    with pytest.raises(paymentchannel.ClosedError):
        pc.pay(url1, 1)

    # Check url2 properties
    status = pc.status(url2)
    url2_expected_status[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    url2_expected_status['ready'] = False
    url2_expected_status['spend_txid'] = str(
        mock.MockPaymentChannelServer.channels[
            status.deposit_txid]['payment_tx'].hash)
    assert_paymentchannel_status(url2_expected_status, status)

    # Confirm close
    bc.mock_confirm(status.spend_txid)

    # Sync
    pc.sync()

    # Check url1 properties
    status = pc.status(url1)
    assert_paymentchannel_status(url1_expected_status, status)

    # Check url2 properties
    status = pc.status(url2)
    url2_expected_status['state'] = statemachine.PaymentChannelState.CLOSED
    assert_paymentchannel_status(url2_expected_status, status)

    # Open a payment channel with 400000 deposit, 500000 seconds expiration, and 20000 fee
    url3 = pc.open('mock://test', 400000, 500000, 20000, True)

    # Check url3 properties
    status = pc.status(url3)
    url3_expected_status = {}
    url3_expected_status['url'] = 'mock://test/' + status.deposit_txid
    url3_expected_status['state'] = statemachine.PaymentChannelState.READY
    url3_expected_status['ready'] = True
    url3_expected_status['balance'] = 400000
    url3_expected_status['deposit'] = 400000
    url3_expected_status['fee'] = 20000
    url3_expected_status[
        'creation_time'] = lambda status: status.creation_time > 0
    url3_expected_status['expiration_time'] = int(status.creation_time +
                                                  500000)
    url3_expected_status['expired'] = False
    url3_expected_status['deposit_txid'] = lambda status: status.deposit_txid
    url3_expected_status['spend_txid'] = None
    assert_paymentchannel_status(url3_expected_status, status)

    # Monkey-patch time.time() for expiration
    orig_time_time = time.time
    time.time = lambda: status.expiration_time + paymentchannel.PaymentChannel.REFUND_BROADCAST_TIME_OFFSET + 1

    # Sync
    pc.sync()

    # Check url3 properties
    status = pc.status(url3, include_txs=True)
    url3_expected_status[
        'state'] = statemachine.PaymentChannelState.CONFIRMING_SPEND
    url3_expected_status['ready'] = False
    url3_expected_status['expired'] = True
    url3_expected_status['spend_txid'] = str(
        bitcoin.Transaction.from_hex(status.transactions.refund_tx).hash)
    assert_paymentchannel_status(url3_expected_status, status)

    # Confirm refund
    bc.mock_confirm(status.spend_txid)

    # Sync
    pc.sync()

    # Check url3 properties
    status = pc.status(url3, include_txs=True)
    url3_expected_status['state'] = statemachine.PaymentChannelState.CLOSED
    assert_paymentchannel_status(url3_expected_status, status)

    # Restore time.time()
    time.time = orig_time_time

    # Ensure all channels are closed
    for url in pc.list():
        assert pc.status(url).state == statemachine.PaymentChannelState.CLOSED
コード例 #11
0
import codecs
import pytest

import two1.bitcoin as bitcoin
import two1.channels.statemachine as statemachine
import two1.channels.walletwrapper as walletwrapper
import tests.channels.mock as mock


@pytest.fixture(params=[
    walletwrapper.Two1WalletWrapper(mock.MockTwo1Wallet(), mock.MockBlockchain())
])
def wallet(request):
    return request.param


def test_walletwrapper(wallet):
    # Check get_public_key()
    assert wallet.get_public_key().compressed_bytes == bitcoin.PublicKey.from_hex("04ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dc3ad232846aad9dc0ecc9328a79956522f532ef9e67435bdc05900cf9f4d1383").compressed_bytes  # nopep8

    # Payment Channel with 100000 deposit, 1000 minimum output, 10000 fee
    redeem_script = statemachine.PaymentChannelRedeemScript(
        mock.MockPaymentChannelServer.PRIVATE_KEY.public_key, mock.MockTwo1Wallet.PRIVATE_KEY.public_key, 1450223410)

    # Check create_deposit_tx()
    deposit_tx = wallet.create_deposit_tx(redeem_script.address(), 100000 + 1000, 10000)
    assert deposit_tx.to_hex() == "010000000119de54dd7043927219cca4c06cc8b94c7c862b6486b0f989ea4c6569fb34383d010000006b483045022100c45e5bd8d00caa1cd3ad46e078ec132c9c505b3168d1d1ffe6285cf054f54ed302203ea12c4203ccee8a9de616cc22f081eed47a78660ce0a01cb3a97e302178a573012103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dffffffff0198b101000000000017a9149bc3354ccfd998cf16628449b940e6914210f1098700000000"  # nopep8

    # Check create_refund_tx()
    refund_tx = wallet.create_refund_tx(deposit_tx, redeem_script, redeem_script.expiration_time, 10000)
    assert refund_tx.to_hex() == "0100000001ef513a66dd5f79c0b6cac9b74192b6d405724a7f559979f5aad5ab848c551a7e000000009d483045022100d00fb043ab32361c4e574e4f7f59ba0b3d1c2fbe758c3d26555cb3748e3270050220729cb95327245aa6f428f87b1e13cbc9c82dfa6dbc2bac0fc4641fc720dc0b220101004c5063210316f5d704b828c3252432886a843649730e08ae01bbbd5c6bde63756d7f54f961ad670432a77056b175682103ee071c95cb772e57a6d8f4f987e9c61b857e63d9f3b5be7a84bdba0b5847099dacfeffffff01888a0100000000001976a914b42fb00f78266bba89feee86036df44401320fba88ac32a77056"  # nopep8