def make_network(masternodes,
                 delegates,
                 ctx,
                 mn_min_quorum=2,
                 del_min_quorum=2):
    mn_wallets = [Wallet() for _ in range(masternodes)]
    dl_wallets = [Wallet() for _ in range(delegates)]

    constitution = {
        'masternodes': [mn.verifying_key().hex() for mn in mn_wallets],
        'delegates': [dl.verifying_key().hex() for dl in dl_wallets],
        'masternode_min_quorum': mn_min_quorum,
        'delegate_min_quorum': del_min_quorum,
    }

    mns = []
    dls = []
    bootnodes = None
    node_count = 0
    for wallet in mn_wallets:
        driver = BlockchainDriver(driver=InMemDriver())
        # driver = IsolatedDriver()
        ipc = f'/tmp/n{node_count}'
        make_ipc(ipc)

        if bootnodes is None:
            bootnodes = [f'ipc://{ipc}']

        mn = Masternode(wallet=wallet,
                        ctx=ctx,
                        socket_base=f'ipc://{ipc}',
                        bootnodes=bootnodes,
                        constitution=deepcopy(constitution),
                        webserver_port=18080 + node_count,
                        driver=driver)

        mns.append(mn)
        node_count += 1

    for wallet in dl_wallets:
        driver = BlockchainDriver(driver=InMemDriver())
        # driver = IsolatedDriver()
        ipc = f'/tmp/n{node_count}'
        make_ipc(ipc)

        dl = Delegate(wallet=wallet,
                      ctx=ctx,
                      socket_base=f'ipc://{ipc}',
                      constitution=deepcopy(constitution),
                      bootnodes=bootnodes,
                      driver=driver)

        dls.append(dl)
        node_count += 1

    return mns, dls
Пример #2
0
class TestNode(TestCase):
    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        self.t = BlockchainDriver()
        self.c = MasterStorage()
        self.ctx = zmq.asyncio.Context()

    def tearDown(self):
        self.ctx.destroy()
        self.t.flush()
        self.c.drop_collections()
        self.loop.close()

    def test_catchup(self):
        fake_block_1 = {'blockNum': 1, 'subBlocks': []}

        fake_block_2 = {'blockNum': 2, 'subBlocks': []}
        self.c.store_block(fake_block_1)
        self.c.store_block(fake_block_2)

        mn_wallets = [Wallet() for _ in range(2)]
        dl_wallets = [Wallet() for _ in range(2)]

        constitution = {
            'masternodes': [mn.verifying_key().hex() for mn in mn_wallets],
            'delegates': [dl.verifying_key().hex() for dl in dl_wallets],
            'masternode_min_quorum': 2,
            'delegate_min_quorum': 2,
        }

        n = Node(socket_base='tcp://127.0.0.1',
                 ctx=self.ctx,
                 constitution=constitution,
                 wallet=mn_wallets[0])

        w = Wallet()
        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500)

        tasks = asyncio.gather(
            m.serve(),
            n.catchup(SocketStruct.from_string('tcp://127.0.0.1:10004')),
            stop_server(m, 1),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        print(res)
Пример #3
0
def flush(args):
    if args.storage_type == 'blocks':
        MasterStorage().drop_collections()
        print('All blocks deleted.')
    elif args.storage_type == 'state':
        BlockchainDriver().flush()
        print('State deleted.')
    elif args.storage_type == 'all':
        MasterStorage().drop_collections()
        BlockchainDriver().flush()
        print('All blocks deleted.')
        print('State deleted.')
    else:
        print('Invalid option. < blocks | state | all >')
def make_tx(processor):
    w = Wallet()
    batch = TransactionBuilder(
        sender=w.verifying_key(),
        contract='test',
        function='testing',
        kwargs={},
        stamps=1_000_000,
        processor=processor,
        nonce=0
    )

    batch.sign(w.signing_key())
    b = batch.serialize()

    tx = transaction_capnp.Transaction.from_bytes_packed(b)

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = BlockchainDriver()
    driver.set(balances_key, 1_000_000)

    return tx
Пример #5
0
    def __init__(self,
                 wallet,
                 socket_base,
                 ctx=None,
                 network_parameters=NetworkParameters(),
                 linger=500,
                 poll_timeout=200,
                 blocks: CilantroStorageDriver = None,
                 driver=BlockchainDriver()):

        self.wallet = wallet
        self.ctx = ctx or zmq.asyncio.Context()
        self.address = network_parameters.resolve(socket_base,
                                                  ServiceType.BLOCK_SERVER,
                                                  bind=True)

        super().__init__(socket_id=self.address,
                         wallet=self.wallet,
                         ctx=self.ctx,
                         linger=linger,
                         poll_timeout=poll_timeout)

        self.blocks = blocks or CilantroStorageDriver(
            key=self.wallet.signing_key())
        self.driver = driver
        self.log = get_logger('BlockServer')
def get_tx_batch():
    w = Wallet()
    tx = TransactionBuilder(
        sender='stu',
        contract='testing',
        function='set',
        kwargs={'var': 'howdy'},
        stamps=100_000,
        processor=b'\x00' * 32,
        nonce=0
    )
    tx.sign(w.signing_key())
    tx.serialize()

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = BlockchainDriver()
    driver.set(balances_key, 1_000_000)
    driver.commit()

    w = Wallet()
    tx2 = TransactionBuilder(
        sender='stu',
        contract='testing',
        function='get',
        kwargs={},
        stamps=100_000,
        processor=b'\x00' * 32,
        nonce=0
    )
    tx2.sign(Wallet().signing_key())
    tx2.serialize()

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash,
                                       config.DELIMITER,
                                       w.verifying_key().hex())

    driver = BlockchainDriver()
    driver.set(balances_key, 1_000_000)
    driver.commit()

    return transaction_list_to_transaction_batch([tx.struct, tx2.struct], wallet=Wallet())
Пример #7
0
    def setUp(self):
        self.w = Wallet()

        self.blocks = CilantroStorageDriver(key=self.w.verifying_key())
        self.driver = BlockchainDriver()

        self.ws = WebServer(wallet=self.w,
                            contracting_client=ContractingClient(),
                            blocks=self.blocks,
                            driver=n)
        self.ws.client.flush()
        self.ws.blocks.drop_collections()
Пример #8
0
 def __init__(self,
              contacts: VKBook,
              driver: BlockchainDriver = BlockchainDriver(),
              verify=True,
              allow_current_block_num=False,
              *args,
              **kwargs):
     self.q = []
     self.contacts = contacts
     self.driver = driver
     self.verify = verify
     self.quorum_ratio = 0.50
     self.allow_current_block_num = allow_current_block_num
     self.log = get_logger('NBN')
     self.signers = len(
         self.contacts.delegates
     )  # This has to be updated every block in case a delegate is added or removed
     super().__init__(*args, **kwargs)
Пример #9
0
    def __init__(self,
                 wallet: Wallet,
                 ctx: zmq.asyncio.Context,
                 blocks: CilantroStorageDriver = None,
                 state=BlockchainDriver(),
                 parameters: Parameters = None):

        self.parameters = parameters

        self.wallet = wallet
        self.ctx = ctx
        self.blocks = blocks
        self.state = state

        self.blocks_to_process = []

        self.in_catchup = False

        self.log = get_logger('Catchup')
Пример #10
0
    def __init__(self,
                 client: ContractingClient,
                 driver: BlockchainDriver = BlockchainDriver(),
                 verify=True,
                 debug=True,
                 *args,
                 **kwargs):
        self.work = {}

        self.driver = driver
        self.verify = verify

        self.client = client
        self.masternode_contract = self.client.get_contract('masternodes')

        self.todo = []
        self.accepting_work = False

        self.log = get_logger('DEL WI')
        self.log.propagate = debug

        super().__init__(*args, **kwargs)
Пример #11
0
from contracting.client import ContractingClient
from contracting.db.encoder import encode

from cilantro_ee.storage.master import MasterStorage
from cilantro_ee.storage import BlockchainDriver
from cilantro_ee.messages.capnp_impl import capnp_struct as schemas

import ast
from . import conf
from . import processor
import os
import capnp

app = Sanic(__name__)
block_driver = MasterStorage()
metadata_driver = BlockchainDriver()
client = ContractingClient()

#HTTPS
'''
from sanic_cors import CORS, cross_origin
import ssl
SSL_WEB_SERVER_PORT = 443
NUM_WORKERS = 1
ssl_cert = ''
ssl_key = ''
CORS(app, automatic_options=True)
'''

transaction_capnp = capnp.load(
    os.path.dirname(schemas.__file__) + '/transaction.capnp')
Пример #12
0
from cilantro_ee.nodes.masternode.webserver import WebServer
from cilantro_ee.crypto.wallet import Wallet
from contracting.client import ContractingClient
from cilantro_ee.storage import BlockchainDriver
from cilantro_ee.storage import CilantroStorageDriver
from cilantro_ee.crypto.transaction import TransactionBuilder
from contracting import config
from cilantro_ee.messages.capnp_impl import capnp_struct as schemas
import os
import capnp

transaction_capnp = capnp.load(
    os.path.dirname(schemas.__file__) + '/transaction.capnp')

n = BlockchainDriver()


def make_good_tx(processor):
    w = Wallet()
    balances_key = '{}{}{}{}{}'.format('currency', config.INDEX_SEPARATOR,
                                       'balances', config.DELIMITER,
                                       w.verifying_key().hex())
    n.set(balances_key, 500000)
    tx = TransactionBuilder(w.verifying_key(),
                            contract='currency',
                            function='transfer',
                            kwargs={
                                'amount': 10,
                                'to': 'jeff'
                            },
Пример #13
0
    def test_block_never_received_goes_through_adequate_consensus(self):
        a = Aggregator(wallet=Wallet(), socket_id=_socket('tcp://127.0.0.1:8888'), ctx=zmq.asyncio.Context(), driver=BlockchainDriver())

        c1 = [MockSBC('input_1', 'res_1', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_4', 3)]

        c2 = [MockSBC('input_1', 'res_1', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_4', 3)]

        c3 = [MockSBC('input_1', 'res_1', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_X', 3)]

        a.sbc_inbox.q = [c1, c2, c3]

        res = self.loop.run_until_complete(a.gather_subblocks(4, adequate_ratio=0.3))

        print(res)

        self.assertFalse(canonical.block_is_failed(res, '0' * 32, 1))
Пример #14
0
    def test_failed_block_on_one_returns_failed_block(self):
        a = Aggregator(wallet=Wallet(), socket_id=_socket('tcp://127.0.0.1:8888'), ctx=zmq.asyncio.Context(), driver=BlockchainDriver())

        c1 = [MockSBC('input_1', 'res_X', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_4', 3)]

        c2 = [MockSBC('input_1', 'res_1', 0),
                             MockSBC('input_2', 'res_X', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_4', 3)]

        c3 = [MockSBC('input_1', 'res_X', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_i', 'res_X', 2),
                             MockSBC('input_4', 'res_4', 3)]

        c4 = [MockSBC('input_1', 'res_1', 0),
                             MockSBC('input_2', 'res_2', 1),
                             MockSBC('input_3', 'res_3', 2),
                             MockSBC('input_4', 'res_X', 3)]

        a.sbc_inbox.q = [c1, c2, c3, c4]

        res = self.loop.run_until_complete(a.gather_subblocks(4))

        print(res)

        self.assertTrue(canonical.block_is_failed(res, '0' * 64, 1))
Пример #15
0
    def test_mixed_results_still_makes_quorum(self):
        a = Aggregator(wallet=Wallet(), socket_id=_socket('tcp://127.0.0.1:8888'), ctx=zmq.asyncio.Context(), driver=BlockchainDriver())

        c1 = [MockSBC('input_1', 'res_X', 0),
              MockSBC('input_2', 'res_2', 1),
              MockSBC('input_3', 'res_3', 2),
              MockSBC('input_4', 'res_4', 3)]

        c2 = [MockSBC('input_1', 'res_1', 0),
              MockSBC('input_2', 'res_X', 1),
              MockSBC('input_3', 'res_3', 2),
              MockSBC('input_4', 'res_4', 3)]

        c3 = [MockSBC('input_1', 'res_1', 0),
              MockSBC('input_2', 'res_2', 1),
              MockSBC('input_i', 'res_X', 2),
              MockSBC('input_4', 'res_4', 3)]

        c4 = [MockSBC('input_1', 'res_1', 0),
              MockSBC('input_2', 'res_2', 1),
              MockSBC('input_3', 'res_3', 2),
              MockSBC('input_4', 'res_X', 3)]

        a.sbc_inbox.q = [c1, c2, c3, c4]

        res = self.loop.run_until_complete(a.gather_subblocks(4))

        self.assertEqual(res['subBlocks'][0]['merkleLeaves'][0], 'res_1')
        self.assertEqual(res['subBlocks'][1]['merkleLeaves'][0], 'res_2')
        self.assertEqual(res['subBlocks'][2]['merkleLeaves'][0], 'res_3')
        self.assertEqual(res['subBlocks'][3]['merkleLeaves'][0], 'res_4')
Пример #16
0
 def setUp(self):
     self.loop = asyncio.new_event_loop()
     asyncio.set_event_loop(self.loop)
     self.t = BlockchainDriver()
     self.c = MasterStorage()
     self.ctx = zmq.asyncio.Context()
    def test_send_to_delegates_doesnt_hang_if_one_is_not_online(self):
        bootnodes = ['ipc:///tmp/n2', 'ipc:///tmp/n3']

        mnw1 = Wallet()
        mnw2 = Wallet()

        dw1 = Wallet()
        dw2 = Wallet()
        dw3 = Wallet()
        dw4 = Wallet()

        constitution = {
            "masternodes": {
                "vk_list": [
                    mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "delegates": {
                "vk_list": [
                    dw1.verifying_key().hex(),
                    dw2.verifying_key().hex(),
                    dw3.verifying_key().hex(),
                    dw4.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "witnesses": {},
            "schedulers": {},
            "notifiers": {},
            "enable_stamps": False,
            "enable_nonces": False
        }

        n1 = '/tmp/n1'
        make_ipc(n1)
        mn1 = Masternode(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}', bootnodes=bootnodes,
                         constitution=constitution, webserver_port=8080, overwrite=True)

        masternodes = [mnw1.verifying_key().hex(), mnw2.verifying_key().hex()]
        delegates = [dw1.verifying_key().hex(), dw2.verifying_key().hex(), dw3.verifying_key().hex(),
                     dw4.verifying_key().hex()]

        contacts = MockContacts(
            masters=masternodes,
            delegates=delegates
        )

        d1 = '/tmp/d1'
        make_ipc(d1)
        wi1 = WorkInbox(socket_id=_socket(f'ipc://{d1}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d2 = '/tmp/d2'
        make_ipc(d2)
        wi2 = WorkInbox(socket_id=_socket(f'ipc://{d2}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d3 = '/tmp/d3'
        make_ipc(d3)
        #wi3 = WorkInbox(socket_id=_socket(f'ipc://{d3}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d4 = '/tmp/d4'
        make_ipc(d4)
        wi4 = WorkInbox(socket_id=_socket(f'ipc://{d4}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        w = Wallet()
        batch = TransactionBuilder(
            sender=w.verifying_key(),
            contract='test',
            function='testing',
            kwargs={},
            stamps=1_000_000,
            processor=mnw1.verifying_key(),
            nonce=0
        )

        batch.sign(w.signing_key())
        b = batch.serialize()

        tx = transaction_capnp.Transaction.from_bytes_packed(b)

        currency_contract = 'currency'
        balances_hash = 'balances'

        balances_key = '{}{}{}{}{}'.format(currency_contract,
                                           config.INDEX_SEPARATOR,
                                           balances_hash,
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        driver = BlockchainDriver()
        driver.set(balances_key, 1_000_000)
        driver.commit()

        mn1.tx_batcher.queue.append(tx)

        mn1.network.peer_service.table.peers = {
            dw1.verifying_key().hex(): f'ipc://{d1}',
            dw2.verifying_key().hex(): f'ipc://{d2}',
            dw3.verifying_key().hex(): f'ipc://{d3}',
            dw4.verifying_key().hex(): f'ipc://{d4}'
        }

        async def late_send():
            await asyncio.sleep(0.3)
            await mn1.parameters.refresh()
            return await mn1.send_batch_to_delegates()

        async def stop():
            await asyncio.sleep(0.5)
            wi1.stop()
            wi2.stop()
            wi4.stop()
            mn1.network.stop()

        tasks = asyncio.gather(
            mn1.network.start(False),
            wi1.serve(),
            wi2.serve(),
            wi4.serve(),
            late_send(),
            stop()
        )

        _, _, _, _, r, _ = self.loop.run_until_complete(tasks)

        # Make sure the right socket failed
        for rr in r:
            if not rr[0]:
                self.assertEqual(rr[1], f'ipc://{d3}/incoming_work')

        self.assertTrue(wi1.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi2.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi4.work[mnw1.verifying_key().hex()])
Пример #18
0
class TestBlockServer(TestCase):
    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        self.t = BlockchainDriver()
        self.ctx = zmq.asyncio.Context()

    def tearDown(self):
        self.ctx.destroy()
        self.t.flush()
        self.loop.close()

    def test_get_latest_block_height(self):
        w = Wallet()
        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500,
                        driver=self.t)

        self.t.set_latest_block_num(555)

        async def get(msg):
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('tcp://127.0.0.1:10004')

            await socket.send(msg)

            res = await socket.recv()

            return res

        message = Message.get_signed_message_packed_2(
            wallet=w,
            msg_type=MessageType.LATEST_BLOCK_HEIGHT_REQUEST,
            timestamp=int(time.time()))

        tasks = asyncio.gather(
            m.serve(),
            get(message),
            stop_server(m, 0.2),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        msg_type, msg, sender, timestamp, is_verified = Message.unpack_message_2(
            res[1])

        self.assertEqual(msg.blockHeight, 555)

    def test_get_latest_block_hash(self):
        w = Wallet()
        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500)

        self.t.set_latest_block_hash(b'\xAA' * 32)

        async def get(msg):
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('tcp://127.0.0.1:10004')

            await socket.send(msg)

            res = await socket.recv()

            return res

        message = Message.get_signed_message_packed_2(
            wallet=w,
            msg_type=MessageType.LATEST_BLOCK_HASH_REQUEST,
            timestamp=int(time.time()))

        tasks = asyncio.gather(
            m.serve(),
            get(message),
            stop_server(m, 0.2),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        msg_type, msg, sender, timestamp, is_verified = Message.unpack_message_2(
            res[1])

        self.assertEqual(msg.hash, b'\xAA' * 32)

    def test_get_block_blob_by_block_data_request(self):
        block = random_txs.random_block()
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode().hex())
        c.drop_collections()

        d = canonical.block_from_subblocks([s for s in block.subBlocks],
                                           previous_hash=b'x/00' * 32,
                                           block_num=0)

        d['blockOwners'] = [secrets.token_bytes(32) for _ in range(12)]

        c.put(d)

        del d['_id']
        del d['blockOwners']

        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500,
                        driver=c)

        async def get(msg):
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('tcp://127.0.0.1:10004')

            await socket.send(msg)

            res = await socket.recv()

            return res

        message = Message.get_signed_message_packed_2(
            wallet=w, msg_type=MessageType.BLOCK_DATA_REQUEST, blockNum=0)

        tasks = asyncio.gather(
            m.serve(),
            get(message),
            stop_server(m, 0.2),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        msg_type, msg, sender, timestamp, is_verified = Message.unpack_message_2(
            res[1])

        dd = canonical.block_from_subblocks([s for s in msg.subBlocks],
                                            previous_hash=b'x/00' * 32,
                                            block_num=0)

        self.assertDictEqual(d, dd)

    def test_get_block_blob_by_block_but_failure_returns_bad_request(self):
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode().hex())
        c.drop_collections()
        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500,
                        driver=c)

        async def get(msg):
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('tcp://127.0.0.1:10004')

            await socket.send(msg)

            res = await socket.recv()

            return res

        message = Message.get_signed_message_packed_2(
            wallet=w, msg_type=MessageType.BLOCK_DATA_REQUEST, blockNum=0)

        tasks = asyncio.gather(
            m.serve(),
            get(message),
            stop_server(m, 1),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        msg_type, msg, sender, timestamp, is_verified = Message.unpack_message_2(
            res[1])
        self.assertEqual(msg_type, MessageType.BAD_REQUEST)
def transaction_is_valid(tx: transaction_capnp.Transaction,
                         expected_processor: bytes,
                         driver: BlockchainDriver,
                         strict=True,
                         tx_per_block=15):
    # Validate Signature
    if not wallet._verify(tx.payload.sender,
                          tx.payload.as_builder().to_bytes_packed(),
                          tx.metadata.signature):
        raise TransactionSignatureInvalid

    # Check nonce processor is correct
    if tx.payload.processor != expected_processor:
        raise TransactionProcessorInvalid

    # Attempt to get the current block's pending nonce
    nonce = driver.get_nonce(tx.payload.processor, tx.payload.sender) or 0

    pending_nonce = driver.get_pending_nonce(tx.payload.processor,
                                             tx.payload.sender) or nonce

    if tx.payload.nonce - nonce > tx_per_block or pending_nonce - nonce >= tx_per_block:
        raise TransactionTooManyPendingException

    # Strict mode requires exact sequence matching (1, 2, 3, 4). This is for masternodes
    if strict:
        if tx.payload.nonce != pending_nonce:
            raise TransactionNonceInvalid
        pending_nonce += 1

    # However, some of those tx's might fail verification and never make it to delegates. Thus,
    # delegates shouldn't be as concerned. (1, 2, 4) should be valid for delegates.
    else:
        if tx.payload.nonce < pending_nonce:
            raise TransactionNonceInvalid
        pending_nonce = tx.payload.nonce + 1

    # Validate Stamps
    if tx.payload.stampsSupplied < 0:
        raise TransactionStampsNegative

    currency_contract = 'currency'
    balances_hash = 'balances'

    balances_key = '{}{}{}{}{}'.format(currency_contract,
                                       config.INDEX_SEPARATOR,
                                       balances_hash, config.DELIMITER,
                                       tx.payload.sender.hex())

    balance = driver.get(balances_key)
    if balance is None:
        balance = 0

    stamp_to_tau = driver.get_var('stamp_cost', 'S', ['value'])
    if stamp_to_tau is None:
        stamp_to_tau = 1

    if balance * stamp_to_tau < tx.payload.stampsSupplied:
        print("bal -> {}, stamp2tau - > {}, txpayload -> {}".format(
            balance, stamp_to_tau, tx.payload.stampsSupplied))
        raise TransactionSenderTooFewStamps

    # Prevent people from sending their entire balances for free by checking if that is what they are doing.
    if tx.payload.contractName == 'currency' and tx.payload.functionName == 'transfer':
        kwargs = decode(tx.payload.kwargs)
        amount = kwargs.get('amount')

        # If you have less than 2 transactions worth of tau after trying to send your amount, fail.
        if ((balance - amount) * stamp_to_tau) / 3000 < 2:
            print(f'BAL IS: {((balance - amount) * stamp_to_tau) / 3000}')
            raise TransactionSenderTooFewStamps

    if tx.payload.contractName == 'submission' and tx.payload.functionName == 'submit_contract':
        kwargs = decode(tx.payload.kwargs)
        name = kwargs.get('name')

        if type(name) != str:
            raise TransactionContractNameInvalid

        if not name.startswith('con_'):
            raise TransactionContractNameInvalid

    driver.set_pending_nonce(tx.payload.processor, tx.payload.sender,
                             pending_nonce)
Пример #20
0
class TestTXValidity(TestCase):
    def setUp(self):
        self.nonce_manager = BlockchainDriver()
        self.nonce_manager.flush()

    def tearDown(self):
        self.nonce_manager.flush()

    def test_processor_incorrect_returns_false(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)
        given_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=given_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionProcessorInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_processor_is_expected_but_nonce_is_incorrect_returns_false(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_processor_and_nonce_correct_increments_pending_nonce_by_one(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=10000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        pending_nonce = self.nonce_manager.get_pending_nonce(expected_processor, w.verifying_key())

        self.assertEqual(pending_nonce, 1)

    def test_all_but_wallet_signed_returns_false(self):
        w = Wallet()
        x = Wallet()

        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=0,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(x.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionSignatureInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_all_but_proof_valid_returns_false(self):
        w = Wallet()

        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=0,
                                processor=expected_processor,
                                nonce=0)

        tx.proof = b'\00' * 32
        tx.proof_generated = True

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionPOWProofInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_processor_and_nonce_correct_but_not_enough_stamps_returns_false(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionSenderTooFewStamps):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           tx.payload.sender.hex())

        balance = self.nonce_manager.get(balances_key) or 0

        self.assertEqual(balance, 0)

    def test_all_valid_with_stamps_when_balance_is_set(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           tx.payload.sender.hex())

        self.nonce_manager.set(balances_key, 500000)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
        balance = self.nonce_manager.get(balances_key) or 0

        self.assertEqual(balance, 500000)

    def test_multiple_nonces_in_sequence_all_verify(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=2)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=3)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_non_sequence_fails_in_strict_mode(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=2)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=5)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_greater_than_passes_in_no_strict_mode(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=1)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=2)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=5)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager,
                             strict=False)

    def test_non_strict_fails_if_same_nonce(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager,
                             strict=False)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager,
                                 strict=False)

    def test_strict_fails_if_same_nonce(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionNonceInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_tx_nonce_minus_nonce_less_than_tx_per_block(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        self.nonce_manager.set_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=1)
        self.nonce_manager.set_pending_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=2)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=2)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_tx_nonce_minus_nonce_greater_than_tx_per_block_fails(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        self.nonce_manager.set_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=1)
        self.nonce_manager.set_pending_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=10)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=20)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionTooManyPendingException):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_nonce_minus_pending_nonce_equal_tx_per_block_fails(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        self.nonce_manager.set_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=1)
        self.nonce_manager.set_pending_nonce(processor=expected_processor, sender=w.verifying_key(), nonce=16)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=16)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionTooManyPendingException):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_15_in_row_valid_16th_not_due_to_tx_per_block_failing(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        for i in range(15):
            tx = TransactionBuilder(w.verifying_key(),
                                    contract='currency',
                                    function='transfer',
                                    kwargs={'amount': 10, 'to': 'jeff'},
                                    stamps=500000,
                                    processor=expected_processor,
                                    nonce=i)

            tx.sign(w.signing_key())
            tx_bytes = tx.serialize()
            tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 10, 'to': 'jeff'},
                                stamps=500000,
                                processor=expected_processor,
                                nonce=15)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionTooManyPendingException):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_sending_transfer_of_all_money_fails(self):
        self.nonce_manager.set_var('stamp_cost', 'S', ['value'], value=3000)
        stamp_to_tau = self.nonce_manager.get_var('stamp_cost', 'S', ['value'])

        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)
        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 500000, 'to': 'jeff'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionSenderTooFewStamps):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_sending_transfer_of_most_money_fails_if_only_one_transfer_in_stamps_left(self):
        self.nonce_manager.set_var('stamp_cost', 'S', ['value'], value=3000)
        stamp_to_tau = self.nonce_manager.get_var('stamp_cost', 'S', ['value'])

        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)
        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 499999, 'to': 'jeff'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionSenderTooFewStamps):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_sending_transfer_of_most_money_doesnt_fail_if_enough_stamps(self):
        self.nonce_manager.set_var('stamp_cost', 'S', ['value'], value=3000)

        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)
        tx = TransactionBuilder(w.verifying_key(),
                                contract='currency',
                                function='transfer',
                                kwargs={'amount': 499990, 'to': 'jeff'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_submission_not_prepended_with_con_throws_error(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='submission',
                                function='submit_contract',
                                kwargs={'name': 'bad_name', 'code': 'blah'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionContractNameInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_submission_not_str_throws_error(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='submission',
                                function='submit_contract',
                                kwargs={'name': 123, 'code': 'blah'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        with self.assertRaises(transaction.TransactionContractNameInvalid):
            transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)

    def test_submission_prepended_with_con_succeeds(self):
        w = Wallet()
        expected_processor = secrets.token_bytes(32)

        balances_key = '{}{}{}{}{}'.format('currency',
                                           config.INDEX_SEPARATOR,
                                           'balances',
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        self.nonce_manager.set(balances_key, 500000)

        tx = TransactionBuilder(w.verifying_key(),
                                contract='submission',
                                function='submit_contract',
                                kwargs={'name': 'con_bad_name', 'code': 'blah'},
                                stamps=3000,
                                processor=expected_processor,
                                nonce=0)

        tx.sign(w.signing_key())
        tx_bytes = tx.serialize()
        tx_struct = transaction_capnp.NewTransaction.from_bytes_packed(tx_bytes)

        transaction_is_valid(tx=tx_struct, expected_processor=expected_processor, driver=self.nonce_manager)
Пример #21
0
 def setUp(self):
     self.nonce_manager = BlockchainDriver()
     self.nonce_manager.flush()
Пример #22
0
 def setUp(self):
     self.ctx = zmq.asyncio.Context()
     self.loop = asyncio.get_event_loop()
     driver = BlockchainDriver()
     driver.flush()