Пример #1
0
def build_transaction(wallet, contract: str, function: str, kwargs: dict,
                      nonce: int, processor: str, stamps: int):
    payload = {
        'contract': contract,
        'function': function,
        'kwargs': kwargs,
        'nonce': nonce,
        'processor': processor,
        'sender': wallet.verifying_key,
        'stamps_supplied': stamps,
    }

    payload = format_dictionary(
        payload)  # Sort payload in case kwargs unsorted

    assert check_format(
        payload, rules.TRANSACTION_PAYLOAD_RULES), 'Invalid payload provided!'

    true_payload = encode(decode(encode(payload)))

    signature = wallet.sign(true_payload)

    metadata = {'signature': signature, 'timestamp': int(time.time())}

    tx = {'payload': payload, 'metadata': metadata}

    return encode(format_dictionary(tx))
Пример #2
0
    def insert_block(self, b: dict):
        self.validate_block(b)

        self.cursor.execute('insert into blocks values (?, ?)', (b['hash'], b['index']))

        for transaction in b['transactions']:

            args = json.dumps(transaction['input']['payload']['arguments'])
            self.cursor.execute('insert into transaction_inputs values (?, ?, ?, ?, ?, ?, ?, ?)',
                                (transaction['hash'],
                                 b['hash'],
                                 transaction['input']['index'],
                                 transaction['input']['sender'],
                                 transaction['input']['signature'],
                                 transaction['input']['payload']['contract'],
                                 transaction['input']['payload']['function'],
                                 args))

            updates = json.dumps(transaction['output']['updates'])
            self.cursor.execute('insert into transaction_outputs values (?, ?, ?, ?, ?, ?)',
                                (transaction['hash'],
                                 b['hash'],
                                 transaction['input']['index'],
                                 transaction['output']['status'],
                                 updates,
                                 encode(transaction['output']['result'])))

        self.conn.commit()
Пример #3
0
 def set(self, key: str, value):
     k = key.encode()
     if value is None:
         self.__delitem__(key)
     else:
         v = encode(value).encode()
         self.db[k] = v
Пример #4
0
def block_from_subblocks(subblocks, previous_hash: str,
                         block_num: int) -> dict:
    block_hasher = hashlib.sha3_256()
    block_hasher.update(bytes.fromhex(previous_hash))

    deserialized_subblocks = []

    for subblock in subblocks:
        if subblock is None:
            continue

        sb = format_dictionary(subblock)
        deserialized_subblocks.append(sb)

        sb_without_sigs = deepcopy(sb)
        if sb_without_sigs.get('signatures') is not None:
            del sb_without_sigs['signatures']

        encoded_sb = encode(sb_without_sigs)

        block_hasher.update(encoded_sb.encode())

    block = {
        'hash': block_hasher.digest().hex(),
        'number': block_num,
        'previous': previous_hash,
        'subblocks': deserialized_subblocks
    }

    return block
    def __init__(self, sender, contract: str, function: str, kwargs: dict,
                 stamps: int, processor: bytes, nonce: int):

        # Stores variables in self for convenience
        self.sender = sender
        self.stamps = stamps
        self.processor = processor
        self.contract = contract
        self.function = function
        self.nonce = nonce
        self.kwargs = kwargs

        # Serializes all that it can on init
        self.struct = transaction_capnp.NewTransaction.new_message()
        self.payload = transaction_capnp.NewTransactionPayload.new_message()

        self.payload.sender = self.sender
        self.payload.processor = self.processor
        self.payload.stampsSupplied = self.stamps
        self.payload.contractName = self.contract
        self.payload.functionName = self.function
        self.payload.nonce = self.nonce

        self.payload.kwargs = encode(kwargs)

        self.payload_bytes = self.payload.to_bytes_packed()
        self.signature = None

        self.tx_signed = False
Пример #6
0
async def secure_send(msg: dict, service, wallet: Wallet, vk, ip, ctx: zmq.asyncio.Context, linger=500, cert_dir=DEFAULT_DIR):
    #if wallet.verifying_key == vk:
    #    return

    socket = ctx.socket(zmq.DEALER)
    socket.setsockopt(zmq.LINGER, linger)
    socket.setsockopt(zmq.TCP_KEEPALIVE, 1)

    socket.curve_secretkey = wallet.curve_sk
    socket.curve_publickey = wallet.curve_vk

    filename = str(cert_dir / f'{vk}.key')
    if not os.path.exists(filename):
        return None

    server_pub, _ = load_certificate(filename)

    socket.curve_serverkey = server_pub

    try:
        socket.connect(ip)
    except ZMQBaseError:
        socket.close()
        return None

    message = build_message(service=service, message=msg)

    payload = encode(message).encode()

    await socket.send(payload, flags=zmq.NOBLOCK)
    socket.close()
Пример #7
0
    def test_merkle_leaf_complex_objects_works(self):
        tx_1_raw = b'{"hash": "503fa157e4d990f78f2b032731dffb398f6ff642b6bbc305817e24dd42b33402", "result": "None", "stamps_used": 198, "state": [{"key": "rewards.S:current_votes:masternodes", "value": 20}, {"key": "rewards.S:current_votes:delegates", "value": 20}, {"key": "rewards.S:current_votes:blackhole", "value": 5}, {"key": "rewards.S:current_votes:foundation", "value": 5}, {"key": "rewards.S:current_votes:developer", "value": 450}, {"key": "rewards.S:has_voted:b0fc27299da14bc08834df9c70d73074f3e511a5a91321d4fa413f3401144918", "value": true}, {"key": "rewards.S:vote_count", "value": 5}, {"key": "rewards.S:value", "value": [{"__fixed__": "0.04"}, {"__fixed__": "0.04"}, {"__fixed__": "0.01"}, {"__fixed__": "0.01"}, {"__fixed__": "0.9"}]}, {"key": "rewards.S:election_start", "value": null}, {"key": "currency.balances:b0fc27299da14bc08834df9c70d73074f3e511a5a91321d4fa413f3401144918", "value": {"__fixed__": "535.30200000"}}], "status": 0, "transaction": {"metadata": {"signature": "ceb4630c8be71f2c0c1e059790609fafa6ed948b7fceb4bb44c36dca46848fac8d55fe27f539036fee5bda6d772fff852b622393eab593aa6dce67f93f7d8f08", "timestamp": 1601411941}, "payload": {"contract": "election_house", "function": "vote", "kwargs": {"policy": "rewards", "value": [4, 4, 1, 1, 90]}, "nonce": 3, "processor": "5b09493df6c18d17cc883ebce54fcb1f5afbd507533417fe32c006009a9c3c4a", "sender": "b0fc27299da14bc08834df9c70d73074f3e511a5a91321d4fa413f3401144918", "stamps_supplied": 999}}}'

        tx_1 = decode(tx_1_raw)

        txs = [encode(tx).encode() for tx in [tx_1]]
        expected_tree = merklize(txs)

        w = Wallet()

        input_hash = 'something'
        signature = w.sign(expected_tree[0])

        sbc = {
            'subblock': 1,
            'transactions': [tx_1],
            'input_hash': input_hash,
            'signer': w.verifying_key,
            'merkle_tree': {
                'signature': signature,
                'leaves': expected_tree
            }
        }

        s = contender.SBCInbox()

        self.assertTrue(s.sbc_is_valid(sbc, 1))
Пример #8
0
    async def handle_msg(self, _id, msg):
        # Try to deserialize the message and run it through the rpc service
        try:
            json_command = decode(msg.decode())

            self.log.info('Received command: {}'.format(json_command))

            result = self.interface.process_json_rpc_command(json_command)

        # If this fails, just set the result to None
        except Exception as e:
            self.log.info('EXCEPTION!! -> ', str(e))
            result = None

        # Try to send the message now. This persists if the socket fails.
        sent = False
        while not sent:
            try:
                msg = encode(result).encode()

                self.log.info('result sent: {}, {}'.format(msg, result))
                await self.socket.send_multipart([_id, msg])
                sent = True

            except zmq.error.ZMQError:
                self.log.info('zmq error: {}'.format(zmq.error.ZMQError))
                self.socket.close()
                self.setup_socket()
Пример #9
0
    def test_good_sbc_returns_true(self):
        tx_1 = {
            'something': 'who_cares'
        }

        tx_2 = {
            'something_else': 'who_cares'
        }

        txs = [encode(tx).encode() for tx in [tx_1, tx_2]]
        expected_tree = merklize(txs)

        w = Wallet()

        input_hash = 'something'
        signature = w.sign(expected_tree[0])

        sbc = {
            'subblock': 1,
            'transactions': [tx_1, tx_2],
            'input_hash': input_hash,
            'signer': w.verifying_key,
            'merkle_tree': {
                'signature': signature,
                'leaves': expected_tree
            }
        }

        s = contender.SBCInbox()

        self.assertTrue(s.sbc_is_valid(sbc, 1))
Пример #10
0
 def set(self, key, value):
     if value is None:
         self.__delitem__(key)
     else:
         v = encode(value)
         with self.db_writer.begin(write=True) as tx:
             tx.put(key.encode(), v.encode())
Пример #11
0
    def test_sign_works_properly(self):
        w = Wallet()

        tx = build_transaction(
            wallet=w,
            processor='b' * 64,
            stamps=123,
            nonce=0,
            contract='currency',
            function='transfer',
            kwargs={
                'amount': 123,
                'to': 'jeff'
            }
        )

        decoded = decode(tx)

        res = verify(
            w.verifying_key,
            encode(decoded['payload']),
            decoded['metadata']['signature']
        )

        self.assertTrue(res)
Пример #12
0
def check_tx_formatting(tx: dict, expected_processor: str):
    if not check_format(tx, rules.TRANSACTION_RULES):
        raise TransactionFormattingError

    if not wallet.verify(tx['payload']['sender'], encode(tx['payload']),
                         tx['metadata']['signature']):
        raise TransactionSignatureInvalid

    if tx['payload']['processor'] != expected_processor:
        raise TransactionProcessorInvalid
Пример #13
0
    def set(self, key, value):
        if value is None:
            self.__delitem__(key)
        else:
            v = encode(value)
            filename = self._key_to_file(key)

            os.makedirs(filename.parents[0], exist_ok=True)

            with open(filename, 'w') as f:
                f.write(v)
Пример #14
0
 def set(self, key, value):
     if value is None:
         self.__delitem__(key)
     else:
         v = encode(value)
         self.db.update_one(
             {'_id': key},
             {'$set': {
                 'v': v
             }},
             upsert=True,
         )
Пример #15
0
        async def request(msg):
            msg = encode(msg).encode()

            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('ipc:///tmp/router')

            await socket.send(msg)

            resp = await socket.recv()

            resp = decode(resp)

            return resp
Пример #16
0
    def test_environment_variables_are_working_as_they_should(self):
        test_contract = '''
a = Variable()
b = Variable()
c = Variable()

@export
def capture():
    a.set(block_hash)
    b.set(block_num)
    c.set(now)
        '''

        self.client.submit(test_contract, name='testing')

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

        tx_batch = transaction_list_to_transaction_batch([tx.struct],
                                                         wallet=Wallet())
        w = Wallet()
        b = Delegate(socket_base='tcp://127.0.0.1', wallet=w, ctx=self.ctx)

        now = Datetime._from_datetime(
            datetime.utcfromtimestamp(tx_batch.timestamp))

        results = b.execute_work([(tx_batch.timestamp, tx_batch)])

        tx = results[0].transactions[0]

        a, b, c = tx.state

        self.assertEqual(a.key, b'testing.a')
        self.assertEqual(
            a.value,
            b'"0000000000000000000000000000000000000000000000000000000000000000"'
        )

        self.assertEqual(b.key, b'testing.b')
        self.assertEqual(b.value, b'0')

        self.assertEqual(c.key, b'testing.c')
        self.assertEqual(c.value, encode(now).encode())
Пример #17
0
    def store_txs(self, txs: list):
        # Calculate the new hash, index, and return the results after storing
        block_hash = hash_bytes(encode(txs).encode())
        index = self.height() + 1

        block_dict = {
            'hash': block_hash,
            'index': index,
            'transactions': txs
        }

        self.insert_block(block_dict)

        return block_dict
Пример #18
0
def verify_proof(proof, pepper):
    # Proofs expire after a minute
    if not primatives.check_format(proof, rules.PROOF_MESSAGE_RULES):
        return False

    if int(time.time()) - proof['timestamp'] > PROOF_EXPIRY:
        return False

    message = [pepper, proof['ip'], proof['timestamp']]
    message_bytes = encode(message).encode()

    h = hashlib.sha3_256()
    h.update(message_bytes)

    return verify(proof['vk'], h.digest().hex(), proof['signature'])
Пример #19
0
    def verify_tx_signature(tx: dict):
        tx_payload = encode(tx['payload'])
        tx_payload_bytes = tx_payload.encode()

        signature = bytes.fromhex(tx['signature'])
        pk = bytes.fromhex(tx['sender'])

        vk = ecdsa.VerifyingKey.from_string(pk,
                                            curve=ecdsa.NIST256p,
                                            hashfunc=hashlib.sha256)
        try:
            vk.verify(signature, tx_payload_bytes)
        except ecdsa.BadSignatureError:
            return False
        return True
Пример #20
0
    def execute_work(self,
                     driver,
                     work,
                     wallet,
                     previous_block_hash,
                     current_height=0,
                     stamp_cost=20000,
                     parallelism=4):
        # Assume single threaded, single process for now.
        subblocks = []
        i = 0

        for tx_batch in work:
            results = self.execute_tx_batch(driver=driver,
                                            batch=tx_batch,
                                            timestamp=tx_batch['timestamp'],
                                            input_hash=tx_batch['input_hash'],
                                            stamp_cost=stamp_cost,
                                            bhash=previous_block_hash,
                                            num=current_height)

            if len(results) > 0:
                merkle = merklize([encode(r).encode() for r in results])
                proof = wallet.sign(merkle[0])
            else:
                merkle = merklize([bytes.fromhex(tx_batch['input_hash'])])
                proof = wallet.sign(tx_batch['input_hash'])

            merkle_tree = {'leaves': merkle, 'signature': proof}

            sbc = {
                'input_hash': tx_batch['input_hash'],
                'transactions': results,
                'merkle_tree': merkle_tree,
                'signer': wallet.verifying_key,
                'subblock': i % parallelism,
                'previous': previous_block_hash
            }

            sbc = format_dictionary(sbc)

            subblocks.append(sbc)
            i += 1

        return subblocks
Пример #21
0
def make_tx(key: ecdsa.SigningKey, contract, func, arguments={}):
    tx = {
        'sender': key.get_verifying_key().to_string().hex(),
        'signature': None,
        'payload': {
            'contract': contract,
            'function': func,
            'arguments': arguments
        }
    }

    message = encode(tx['payload']).encode()

    signature = key.sign_deterministic(message, hashlib.sha256)[:64]

    tx['signature'] = signature.hex()

    return tx
Пример #22
0
async def secure_request(msg: dict, service: str, wallet: Wallet, vk: str, ip: str, ctx: zmq.asyncio.Context,
                         linger=500, timeout=1000, cert_dir=DEFAULT_DIR):
    #if wallet.verifying_key == vk:
    #    return

    socket = ctx.socket(zmq.DEALER)
    socket.setsockopt(zmq.LINGER, linger)
    socket.setsockopt(zmq.TCP_KEEPALIVE, 1)

    socket.curve_secretkey = wallet.curve_sk
    socket.curve_publickey = wallet.curve_vk

    filename = str(cert_dir / f'{vk}.key')
    if not os.path.exists(filename):
        return None

    server_pub, _ = load_certificate(filename)

    socket.curve_serverkey = server_pub

    try:
        socket.connect(ip)
    except ZMQBaseError:
        logger.debug(f'Could not connect to {ip}')
        socket.close()
        return None

    message = build_message(service=service, message=msg)

    payload = encode(message).encode()

    await socket.send(payload)

    event = await socket.poll(timeout=timeout, flags=zmq.POLLIN)
    msg = None
    if event:
        #logger.debug(f'Message received on {ip}')
        response = await socket.recv()

        msg = decode(response)

    socket.close()

    return msg
Пример #23
0
    def sbc_is_valid(self, sbc, sb_idx=0):
        if sbc['subblock'] != sb_idx:
            self.log.error(f'Subblock Contender[{sb_idx}] is out order.')
            return False

        # Make sure signer is in the delegates
        if len(sbc['transactions']) == 0:
            message = sbc['input_hash']
        else:
            message = sbc['merkle_tree']['leaves'][0]

        valid_sig = verify(vk=sbc['signer'],
                           msg=message,
                           signature=sbc['merkle_tree']['signature'])

        if not valid_sig:
            self.log.error(
                f'Subblock Contender[{sb_idx}] from {sbc["signer"][:8]} has an invalid signature.'
            )
            return False

        if len(sbc['merkle_tree']['leaves']) > 0:
            txs = [encode(tx).encode() for tx in sbc['transactions']]
            expected_tree = merklize(txs)

            # Missing leaves, etc
            if len(sbc['merkle_tree']['leaves']) != len(expected_tree) and len(
                    sbc['transactions']) > 0:
                self.log.error('Merkle Tree Len mismatch')
                return False

            for i in range(len(expected_tree)):
                if expected_tree[i] != sbc['merkle_tree']['leaves'][i]:
                    self.log.error(
                        f'Subblock Contender[{sbc["subblock"]}] from {sbc["signer"][:8]} has an Merkle tree proof.'
                    )
                    self.log.error(expected_tree[i])
                    self.log.error(txs[i])
                    return False

        self.log.info(
            f'Subblock[{sbc["subblock"]}] from {sbc["signer"][:8]} is valid.')

        return True
Пример #24
0
    def create_proof(self):
        now = int(time.time())
        message = [self.pepper, self.ip_string, now]

        message_bytes = encode(message).encode()

        h = hashlib.sha3_256()
        h.update(message_bytes)

        signature = self.wallet.sign(h.hexdigest())

        proof = {
            'signature': signature,
            'vk': self.wallet.verifying_key,
            'timestamp': now,
            'ip': self.ip_string
        }

        return proof
Пример #25
0
async def get_variable(request, contract, variable):
    contract_code = client.raw_driver.get_contract(contract)

    if contract_code is None:
        return json({'error': '{} does not exist'.format(contract)},
                    status=404)

    key = request.args.get('key')

    if key is None:
        args = []
    else:
        args = [key]

    k = client.raw_driver.make_key(contract, variable, args)
    response = encode(client.raw_driver.get(k))

    if response is None:
        return json({'value': None}, status=404)
    else:
        return json({'value': response}, status=200)
Пример #26
0
    def test_make_tx(self):
        # nakey = nacl.signing.SigningKey.generate()
        #
        # pk = nakey.verify_key.encode().hex()

        nakey = ecdsa.SigningKey.generate(curve=ecdsa.NIST256p)
        pk = nakey.get_verifying_key().to_string().hex()

        tx = {
            'sender': pk,
            'signature': None,
            'payload': {
                'contract': 'submission',
                'function': 'submit_contract',
                'arguments': {
                    'code': 'test',
                    'name': 'stu_bucks'
                }
            }
        }

        message = encode(tx['payload']).encode()

        sig = nakey.sign_deterministic(message, hashfunc=hashlib.sha256).hex()

        tx['signature'] = sig

        made_tx = make_tx(nakey,
                          contract='submission',
                          func='submit_contract',
                          arguments={
                              'code': 'test',
                              'name': 'stu_bucks'
                          })

        self.assertEqual(made_tx, tx)
Пример #27
0
    def test_process_message_good_and_bad_sbc_doesnt_pass_to_q(self):
        ### GOOD SBC
        tx_1_1 = {
            'something': 'who_cares'
        }

        tx_1_2 = {
            'something_else': 'who_cares'
        }

        txs = [encode(tx).encode() for tx in [tx_1_1, tx_1_2]]
        expected_tree = merklize(txs)

        w = Wallet()

        input_hash = 'something'
        signature = w.sign(expected_tree[0])

        sbc_1 = {
            'subblock': 0,
            'transactions': [tx_1_1, tx_1_2],
            'input_hash': input_hash,
            'signer': w.verifying_key,
            'merkle_tree': {
                'signature': signature,
                'leaves': expected_tree
            }
        }

        ### BAD SBC
        tx_2_1 = {
            'something': 'who_cares2'
        }

        tx_2_2 = {
            'something_else': 'who_cares2'
        }

        txs = [encode(tx).encode() for tx in [tx_2_1, tx_2_2]]
        expected_tree = merklize(txs)

        w = Wallet()

        input_hash = 'something2'
        signature = w.sign(expected_tree[0])

        expected_tree[1] = 'crap'

        sbc_2 = {
            'subblock': 1,
            'transactions': [tx_2_1, tx_2_2],
            'input_hash': input_hash,
            'signer': w.verifying_key,
            'merkle_tree': {
                'signature': signature,
                'leaves': expected_tree
            }
        }

        s = contender.SBCInbox()

        loop = asyncio.get_event_loop()
        if loop.is_closed():
            loop = asyncio.new_event_loop()
        loop.run_until_complete(s.process_message([sbc_1, sbc_2]))

        self.assertEqual(s.q, [])
Пример #28
0
def tx_hash_from_tx(tx):
    h = hashlib.sha3_256()
    tx_dict = format_dictionary(tx)
    encoded_tx = encode(tx_dict).encode()
    h.update(encoded_tx)
    return h.hexdigest()
Пример #29
0
    def test_bigint_encode(self):
        si = MONGO_MIN_INT - 1
        bi = MONGO_MAX_INT + 1

        self.assertEqual('{"__big_int__":"' + str(bi) + '"}', encode(bi))
        self.assertEqual('{"__big_int__":"' + str(si) + '"}', encode(si))
Пример #30
0
    def test_int_to_bytes(self):
        i = 1000
        b = '1000'

        self.assertEqual(encode(i), b)