Ejemplo n.º 1
0
bool script::op_checksig(const message::transaction& parent_tx, 
        uint32_t input_index)
{
    if (stack_.size() < 2)
        return false;
    data_chunk pubkey = pop_stack(), signature = pop_stack();

    script script_code;
    for (operation op: operations_)
    {
        if (op.data == signature || op.code == opcode::codeseparator)
            continue;
        script_code.push_operation(op);
    }

    elliptic_curve_key key;
    key.set_public_key(pubkey);

    uint32_t hash_type = 0;
    hash_type = signature.back();
    signature.pop_back();
    BITCOIN_ASSERT(signature.size() == 70);

    if (hash_type != 1)
    {
        log_error() << "Unimplemented hash_type";
        return false;
    }

    if (input_index >= parent_tx.inputs.size())
    {
        log_fatal() << "script::op_checksig() : input_index " << input_index
                << " is out of range.";
        return false;
    }

    message::transaction tx_tmp = parent_tx;
    // Blank all other inputs' signatures
    for (message::transaction_input& input: tx_tmp.inputs)
        input.input_script = script();
    tx_tmp.inputs[input_index].input_script = script_code;

    hash_digest tx_hash = hash_transaction(tx_tmp, hash_type);
    return key.verify(tx_hash, signature);
}
bool leveldb_validate_block::fetch_orphan_transaction(
    transaction_type& tx, size_t& tx_height, const hash_digest& tx_hash)
{
    for (size_t orphan_iter = 0; orphan_iter <= orphan_index_; ++orphan_iter)
    {
        const block_type& orphan_block =
            orphan_chain_[orphan_iter]->actual();
        for (const transaction_type& orphan_tx: orphan_block.transactions)
        {
            if (hash_transaction(orphan_tx) == tx_hash)
            {
                tx = orphan_tx;
                tx_height = fork_index_ + orphan_iter + 1;
                return true;
            }
        }
    }
    return false;
}
Ejemplo n.º 3
0
bool leveldb_common::save_block(
    uint32_t height, const block_type& serial_block)
{
    leveldb_transaction_batch batch;
    // Write block header + tx hashes
    data_chunk raw_block_data(
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    // Downcast to base header type so serializer selects that.
    auto header_end = satoshi_save(
        serial_block.header, raw_block_data.begin());
    BITCOIN_ASSERT(std::distance(raw_block_data.begin(), header_end) == 80);
    auto serial_hashes = make_serializer(header_end);
    // Write the number of transactions...
    serial_hashes.write_4_bytes(serial_block.transactions.size());
    // ... And now the tx themselves.
    for (uint32_t tx_index = 0;
        tx_index < serial_block.transactions.size(); ++tx_index)
    {
        const transaction_type& block_tx =
            serial_block.transactions[tx_index];
        const hash_digest& tx_hash = hash_transaction(block_tx);
        if (!save_transaction(batch, height, tx_index, tx_hash, block_tx))
        {
            log_fatal(LOG_BLOCKCHAIN) << "Could not save transaction";
            return false;
        }
        serial_hashes.write_hash(tx_hash);
    }
    BITCOIN_ASSERT(serial_hashes.iterator() ==
        raw_block_data.begin() + 80 + 4 +
            serial_block.transactions.size() * hash_digest_size);
    data_chunk raw_height = uncast_type(height);
    hash_digest block_hash = hash_block_header(serial_block.header);
    // Write block header
    batch.block.Put(slice(raw_height), slice(raw_block_data));
    batch.block_hash.Put(slice_block_hash(block_hash), slice(raw_height));
    // Execute batches.
    db_.write(batch);
    // Sync stealth database.
    db_stealth_->sync(height);
    return true;
}
Ejemplo n.º 4
0
bool leveldb_common::get_transaction(leveldb_tx_info& tx_info,
    const hash_digest& tx_hash, bool read_parent, bool read_tx)
{
    // First we try to read the bytes from the database.
    std::string value;
    leveldb::Status status = db_.tx->Get(
        leveldb::ReadOptions(), slice(tx_hash), &value);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "get_transaction("
            << tx_hash << "): " << status.ToString();
        return false;
    }
    // Read the parent block height and our index in that block (if neccessary).
    BITCOIN_ASSERT(value.size() > 8);
    if (read_parent)
    {
        auto deserial = make_deserializer(value.begin(), value.begin() + 8);
        tx_info.height = deserial.read_4_bytes();
        tx_info.index = deserial.read_4_bytes();
    }
    if (!read_tx)
        return true;
    // Read the actual transaction (if neccessary).
    try
    {
        BITCOIN_ASSERT(value.size() > 8);
        satoshi_load(value.begin() + 8, value.end(), tx_info.tx);
    }
    catch (end_of_stream)
    {
        return false;
    }
    BITCOIN_ASSERT(satoshi_raw_size(tx_info.tx) + 8 == value.size());
    BITCOIN_ASSERT(hash_transaction(tx_info.tx) == tx_hash);
    return true;
}
void block_database::store(const block_type& block)
{
    const size_t height = index_.size();
    // Write block data.
    const hash_digest key = hash_block_header(block.header);
    const size_t number_txs = block.transactions.size();
    const size_t value_size = 80 + 4 + 4 + number_txs * hash_size;
    auto write = [&](uint8_t* data)
    {
        satoshi_save(block.header, data);
        auto serial = make_serializer(data + 80);
        serial.write_4_bytes(height);
        serial.write_4_bytes(number_txs);
        for (const transaction_type& tx: block.transactions)
        {
            const hash_digest tx_hash = hash_transaction(tx);
            serial.write_hash(tx_hash);
        }
    };
    const position_type position = map_.store(key, value_size, write);
    // Write height -> position mapping.
    write_position(position);
}
Ejemplo n.º 6
0
/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) 
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
block_type step(const block_point& root, const block_point& head, size_t n)
{
    std::cout << "Stepping " << n << std::endl;
    transaction_type coinbase_tx = create_coinbase(public_key());
    const block_type* prev_blk = &head.blk;
    static hash_digest txh6 = null_hash;
    if (n == 4)
    {
        prev_blk = lookup(root, {0, 0, 0});
        output_point prevout{
            hash_transaction(root.prefix_chain[2].transactions[0]), 0};
        transaction_type tx = construct_transaction(prevout);
        txh6 = hash_transaction(tx);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    else if (n == 5)
    {
        prev_blk = lookup(root, {0, 0, 0, 0});
    }
    else if (n == 6)
    {
        output_point prevout{
            hash_transaction(root.prefix_chain[1].transactions[0]), 0};
        transaction_type tx = construct_transaction(prevout);
        txh6 = hash_transaction(tx);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    else if (n == 7)
    {
        BITCOIN_ASSERT(txh6 != null_hash);
        output_point prevout{txh6, 0};
        transaction_type tx = construct_transaction(prevout);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    else if (n == 8)
    {
        prev_blk = lookup(root, {0, 0, 0});
    }
    else if (n == 9)
    {
        BITCOIN_ASSERT(txh6 != null_hash);
        output_point prevout{txh6, 0};
        transaction_type tx = construct_transaction(prevout);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    else if (n == 11)
    {
        prev_blk = lookup(root, {0, 0, 0, 1});
    }
    else if (n == 15)
    {
        // Attempt double spend.
        output_point prevout{
            hash_transaction(root.prefix_chain[2].transactions[0]), 0};
        transaction_type tx = construct_transaction(prevout);
        txh6 = hash_transaction(tx);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    else if (n == 16)
    {
        prev_blk = lookup(root, {0, 0, 0, 2, 0});
    }
    else if (n == 20)
    {
        BITCOIN_ASSERT(txh6 != null_hash);
        output_point prevout{txh6, 0};
        transaction_type tx = construct_transaction(prevout);
        return mine_next(*prev_blk, {coinbase_tx, tx});
    }
    return mine_next(*prev_blk, {coinbase_tx});
}