Files
tomFlowee 0a2e552168 Move more logic over to byte-array based Block
This introduces a new BlockHeader helper class which Block and
MutableBlock can both produce, which helps a lot of methods to
be ported to no longer be dependent on us using a MutableBlock
object, which is too costly to use when we have no intention
to alter the block.
2026-04-20 22:21:18 +02:00

148 lines
5.1 KiB
C++

/*
* This file is part of the Flowee project
* Copyright (C) 2017-2021 Tom Zander <tom@flowee.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FLOWEE_PRIMITIVES_BLOCK_H
#define FLOWEE_PRIMITIVES_BLOCK_H
#include "primitives/Tx.h"
#include "primitives/BlockHeader.h"
#include <streaming/ConstBuffer.h>
#include <uint256.h>
#include <vector>
namespace Streaming {
class BufferPool;
}
class MutableBlock;
class BlockHeaderFields;
/**
* @brief The Block class is a Bitcoin Block in canonical form.
* The Block object is a thin wrapper around a buffer of data which is known to be a Bitcoin block.
* The class provides access to all parts of the block as expected, but it has no parsing or loading state
* that it has to go through before you can access it. As such deep-copying is always cheap.
*
* @see MutableBlock, Tx
*/
class Block
{
public:
/// Create invalid block
Block();
/// Constructs a block from a buffer, notice that the buffer has to be at least 80 bytes as that is the block header size.
Block(const Streaming::ConstBuffer &rawBlock);
Block(const Block &other) = default;
/// returns the version of the block.
int32_t blockVersion() const;
/// Returns the hash pointer of the previous block in the chain.
uint256 previousBlockId() const;
/// returns the hash of the merkele root.
uint256 merkleRoot() const;
/// retuns the timestamp, as contained in the block header.
uint32_t timestamp() const;
/// retuns the bits field, as contained in the block header.
uint32_t bits() const;
/// retuns the nonce field, as contained in the block header.
uint32_t nonce() const;
/// calculates and returns hash.
uint256 createHash() const;
/// Returns if this block has a header and a list of transactions.
inline bool isFullBlock() const {
return m_data.size() > 80;
}
/// Returns if this block has any data at all.
inline bool isEmpty() const {
return m_data.isEmpty();
}
/// Returns if this block has at least enough data for a header.
inline bool hasHeader() const {
return m_data.size() >= 80;
}
/// Populate the transactions() array, throws exception on failure.
/// This method should only ever be called once on a Block.
void findTransactions();
/**
* Find, the slow way, a transaction by txid.
* This will walk over the entire block and hash each transaction in order
* to find a match with /a txid.
* The CTORlayout boolean tells us if this block has sorted transactionIDs
* because if it does we can stop looking earlier.
*/
Tx findTransaction(const uint256 &txid, bool CTORlayout) const;
/// Return transactions. @see findTransactions();
inline const std::vector<Tx> &transactions() const {
return m_transactions;
}
/// return the total size of this block.
inline int size() const {
return m_data.size();
}
/// For backwards compatibility with old code, load a MutableBlock and return it.
MutableBlock createOldBlock() const;
/**
* @brief fromOldBlock saves the old block in a buffer which it returns a Block instance with.
* @param block the old block-header, which can be discarded afterwards.
* @param pool an optional bufferPool, if not passed a local one will be created.
* @return the newly created Block
*/
static Block fromOldBlock(const BlockHeader &header, Streaming::BufferPool *pool = 0);
/**
* @brief fromOldBlock saves the old block-header in a buffer which it returns a Block instance with.
* @param block the old block, which can be discarded afterwards.
* @param pool an optional bufferPool, if not passed a local one will be created.
* @return the newly created Block
*/
static Block fromOldBlock(const BlockHeaderFields &block, Streaming::BufferPool *pool = 0);
/**
* @brief fromOldBlock saves the old block in a buffer which it returns a Block instance with.
* @param block the old block, which can be discarded afterwards.
* @param pool an optional bufferPool, if not passed a local one will be created.
* @return the newly created Block
*/
static Block fromOldBlock(const MutableBlock &block, Streaming::BufferPool *pool = 0);
/// \internal
inline Streaming::ConstBuffer data() const {
return m_data;
}
Block &operator=(const Block &other) = default;
BlockHeader header() const;
private:
Streaming::ConstBuffer m_data;
std::vector<Tx> m_transactions;
};
#endif