def test_serialization(): op1 = t.OutPoint(txid='c0ffee', txout_idx=0) op2 = t.OutPoint(txid='c0ffee', txout_idx=1) txin1 = t.TxIn(to_spend=op1, unlock_sig=b'oursig', unlock_pk=b'foo', sequence=1) txin2 = t.TxIn(to_spend=op2, unlock_sig=b'oursig', unlock_pk=b'foo', sequence=2) txout = t.TxOut(value=101, to_address='1zxoijw') txn1 = t.Transaction(txins=[txin1], txouts=[txout], locktime=0) txn2 = t.Transaction(txins=[txin2], txouts=[txout], locktime=0) block = t.Block(1, 'deadbeef', 'c0ffee', int(time.time()), 100, 100, [txn1, txn2]) utxo = t.UnspentTxOut(*txout, txid=txn1.id, txout_idx=0, is_coinbase=False, height=0) utxo_set = [utxo.outpoint, utxo] for obj in (op1, op2, txin1, txin2, txout, txn1, txn2, block, utxo, utxo_set): assert t.deserialize(t.serialize(obj)) == obj
def test_dependent_txns_in_single_block(): t.active_chain = [] t.mempool = {} assert t.connect_block(chain1[0]) == t.ACTIVE_CHAIN_IDX assert t.connect_block(chain1[1]) == t.ACTIVE_CHAIN_IDX assert len(t.active_chain) == 2 assert len(t.utxo_set) == 2 utxo1 = t.utxo_set[list(t.utxo_set.keys())[0]] txout1 = TxOut(value=901, to_address=utxo1.to_address) txin1 = make_txin(signing_key, utxo1.outpoint, txout1) txn1 = t.Transaction(txins=[txin1], txouts=[txout1], locktime=0) # Create a transaction that is dependent on the yet-unconfirmed transaction # above. txout2 = TxOut(value=9001, to_address=txout1.to_address) txin2 = make_txin(signing_key, t.OutPoint(txn1.id, 0), txout2) txn2 = t.Transaction(txins=[txin2], txouts=[txout2], locktime=0) # Assert that we don't accept this txn -- too early to spend the coinbase. with pytest.raises(t.TxnValidationError) as excinfo: t.validate_txn(txn2) assert 'UTXO not ready' in str(excinfo.value) t.connect_block(chain1[2]) # Now the coinbase has matured to spending. t.add_txn_to_mempool(txn1) assert txn1.id in t.mempool # In txn2, we're attempting to spend more than is available (9001 vs. 901). assert not t.add_txn_to_mempool(txn2) with pytest.raises(t.TxnValidationError) as excinfo: t.validate_txn(txn2) assert 'Spend value is more than available' in str(excinfo.value) # Recreate the transaction with an acceptable value. txout2 = TxOut(value=901, to_address=txout1.to_address) txin2 = make_txin(signing_key, t.OutPoint(txn1.id, 0), txout2) txn2 = t.Transaction(txins=[txin2], txouts=[txout2], locktime=0) t.add_txn_to_mempool(txn2) assert txn2.id in t.mempool block = t.assemble_and_solve_block( t.pubkey_to_address(signing_key.get_verifying_key().to_string())) assert t.connect_block(block) == t.ACTIVE_CHAIN_IDX assert t.active_chain[-1] == block assert block.txns[1:] == [txn1, txn2] assert txn1.id not in t.mempool assert txn2.id not in t.mempool assert t.OutPoint(txn1.id, 0) not in t.utxo_set # Spent by txn2. assert t.OutPoint(txn2.id, 0) in t.utxo_set
def test_build_spend_message(): txout = t.TxOut(value=101, to_address='1zz8w9') txin = t.TxIn(to_spend=t.OutPoint('c0ffee', 0), unlock_sig=b'oursig', unlock_pk=b'foo', sequence=1) txn = t.Transaction(txins=[txin], txouts=[txout], locktime=0) spend_msg = t.build_spend_message(txin.to_spend, txin.unlock_pk, txin.sequence, txn.txouts) assert spend_msg == ( b'677c2d8f9843d1cc456e7bfbc507c0f6d07d19c69e6bca0cbaa7bfaea4dd840a') # Adding a new output to the txn creates a new spend message. txn.txouts.append(t.TxOut(value=1, to_address='1zz')) assert t.build_spend_message(txin.to_spend, txin.unlock_pk, txin.sequence, txn.txouts) != spend_msg
def send_value(args: dict): """Send value to some address""" val, to_addr, sk = int(args['<val>']), args['<addr>'], args['signing_key'] selected = set() my_coins = list( sorted(find_utxo_for_address(args), key=lambda i: (i.value, i.height))) for coin in my_coins: selected.add(coin) if sum(i.value for i in selected) > val: break txout = t.TxOut(value=val, to_address=to_addr) logger.info(f'selected') import pdb pdb.set_trace() txn = t.Transaction( txins=[make_txin(sk, coin.outpoint, txout) for coin in selected], txouts=[txout]) logger.info(f'built txn {txn}') logger.info(f'broadcasting txn {txn.id}') send_msg(txn)
def create_object(data: dict): """ Create an object out of a dict. Args: data: Dictionary containing the data. Returns: Object that was created. """ if isinstance(data, list): return [create_object(e) for e in data] # Chains if data['__type__'] == 'Transaction': return chains.Transaction(**create_object(data['__data__'])) if data['__type__'] == 'Header': return chains.Header(**create_object(data['__data__'])) if data['__type__'] == 'Block': return chains.Block(create_object(data['__header__']), create_object(data['__transactions__'])) if data['__type__'] == 'DNS_Transaction': return chains.DNS_Transaction(**create_object(data['__data__'])) if data['__type__'] == 'DNS_Data': return chains.DNS_Data(**create_object(data['__data__'])) if data['__type__'] == 'DDosHeader': return chains.DDosHeader(**create_object(data['__data__'])) if data['__type__'] == 'DDosTransaction': return chains.DDosTransaction(**create_object(data['__data__'])) if data['__type__'] == 'DDosData': return chains.DDosData(**create_object(data['__data__'])) # General if data['__type__'] == 'Tuple': return tuple( create_object(data[f'__{i}__']) for i in range(len(data) - 1)) if data['__type__'] == 'List': return [create_object(data[f'__{i}__']) for i in range(len(data) - 1)] if data['__type__'] == 'Dict': return dict((k, create_object(v)) for (k, v) in data.items() if k != '__type__') if data['__type__'] == 'Bytes': return data['__data__'].encode(data['__encoding__']) if data['__type__'] == 'Hex-Bytes': return nacl.encoding.HexEncoder.decode(data['__data__'].encode( data['__encoding__'])) if data['__type__'] == 'SigningKey': return nacl.signing.SigningKey( data['__seed__'].encode(data['__encoding__']), nacl.encoding.HexEncoder) return data['__data__']