2017-09-05 13:44:41 +02:00
|
|
|
/*
|
2017-11-09 19:34:51 +01:00
|
|
|
* This file is part of the Flowee project
|
2021-06-20 22:44:44 +02:00
|
|
|
* Copyright (C) 2017,2019 Tom Zander <tom@flowee.org>
|
2017-09-05 13:44:41 +02:00
|
|
|
*
|
|
|
|
|
* 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/>.
|
|
|
|
|
*/
|
2018-01-15 15:26:12 +00:00
|
|
|
#include "FastUndoBlock.h"
|
2017-09-05 13:44:41 +02:00
|
|
|
|
2019-03-11 14:47:12 +01:00
|
|
|
#include <streaming/streams.h>
|
2017-09-05 13:44:41 +02:00
|
|
|
#include <undo.h>
|
2018-07-23 18:05:43 +02:00
|
|
|
#include <streaming/MessageBuilder.h>
|
2017-09-05 13:44:41 +02:00
|
|
|
#include <streaming/BufferPool.h>
|
|
|
|
|
|
2018-07-23 18:05:43 +02:00
|
|
|
enum UndoBlockSpec
|
2017-09-05 13:44:41 +02:00
|
|
|
{
|
2018-07-23 18:05:43 +02:00
|
|
|
End = 0,
|
|
|
|
|
StartBlock = 0x10, // with block-hash as arg
|
|
|
|
|
/// an item that was inserted into the UTXO, that when undone will be removed
|
|
|
|
|
RMTxId,
|
|
|
|
|
RMTxOutIndex,
|
|
|
|
|
/// an item that was deleted from the UTXO, that when undo will be re-inserted.
|
|
|
|
|
InsTxId,
|
|
|
|
|
InsTxOutIndex,
|
|
|
|
|
InsBlockHeight,
|
|
|
|
|
InsOffsetInBlock
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-05 13:44:41 +02:00
|
|
|
|
|
|
|
|
FastUndoBlock::FastUndoBlock(const Streaming::ConstBuffer &rawBlock)
|
2018-07-23 18:05:43 +02:00
|
|
|
: m_data(rawBlock),
|
|
|
|
|
m_parser(m_data)
|
2017-09-05 13:44:41 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:05:43 +02:00
|
|
|
FastUndoBlock::Item FastUndoBlock::nextItem()
|
2017-09-05 13:44:41 +02:00
|
|
|
{
|
2018-07-23 18:05:43 +02:00
|
|
|
FastUndoBlock::Item answer;
|
|
|
|
|
auto type = m_parser.next();
|
|
|
|
|
while (type == Streaming::FoundTag) {
|
|
|
|
|
switch (m_parser.tag()) {
|
|
|
|
|
case End:
|
|
|
|
|
return answer;
|
|
|
|
|
case StartBlock: break;
|
|
|
|
|
case RMTxId:
|
|
|
|
|
answer.prevTxId = m_parser.uint256Data();
|
|
|
|
|
break;
|
|
|
|
|
case RMTxOutIndex:
|
|
|
|
|
answer.outputIndex = m_parser.intData();
|
|
|
|
|
return answer;
|
|
|
|
|
case InsTxId:
|
|
|
|
|
answer.prevTxId = m_parser.uint256Data();
|
|
|
|
|
break;
|
|
|
|
|
case InsTxOutIndex:
|
|
|
|
|
answer.outputIndex = m_parser.intData();
|
|
|
|
|
break;
|
|
|
|
|
case InsBlockHeight:
|
|
|
|
|
answer.blockHeight = m_parser.intData();
|
|
|
|
|
break;
|
|
|
|
|
case InsOffsetInBlock:
|
2018-10-13 21:21:25 +02:00
|
|
|
answer.offsetInBlock = m_parser.intData();
|
2018-07-23 18:05:43 +02:00
|
|
|
return answer;
|
|
|
|
|
default:
|
|
|
|
|
assert(false);
|
|
|
|
|
return answer;
|
|
|
|
|
}
|
|
|
|
|
type = m_parser.next();
|
2017-09-05 13:44:41 +02:00
|
|
|
}
|
2018-07-23 18:05:43 +02:00
|
|
|
return answer;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-21 21:42:01 +02:00
|
|
|
void FastUndoBlock::restartStream()
|
|
|
|
|
{
|
|
|
|
|
m_parser = Streaming::MessageParser(m_data);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-21 15:13:56 +01:00
|
|
|
UndoBlockBuilder::UndoBlockBuilder(const uint256 &blockId, const std::shared_ptr<Streaming::BufferPool> &pool)
|
|
|
|
|
: m_pool(pool)
|
2018-07-23 18:05:43 +02:00
|
|
|
{
|
2023-12-21 15:13:56 +01:00
|
|
|
if (m_pool.get() == nullptr)
|
|
|
|
|
m_pool = std::make_shared<Streaming::BufferPool>();
|
2018-07-23 18:05:43 +02:00
|
|
|
m_pool->reserve(40);
|
2023-12-21 15:13:56 +01:00
|
|
|
Streaming::MessageBuilder builder(m_pool);
|
2018-07-23 18:05:43 +02:00
|
|
|
builder.add(StartBlock, blockId);
|
|
|
|
|
m_data.push_back(builder.buffer());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UndoBlockBuilder::append(const std::deque<FastUndoBlock::Item> &items)
|
|
|
|
|
{
|
|
|
|
|
m_pool->reserve(items.size() * 60);
|
2023-12-21 15:13:56 +01:00
|
|
|
Streaming::MessageBuilder builder(m_pool);
|
2018-07-23 18:05:43 +02:00
|
|
|
for (auto item : items) {
|
|
|
|
|
if (item.isInsert()) { // in undo that means we remember the reverse action
|
|
|
|
|
builder.add(RMTxId, item.prevTxId);
|
|
|
|
|
builder.add(RMTxOutIndex, item.outputIndex);
|
|
|
|
|
} else {
|
|
|
|
|
builder.add(InsTxId, item.prevTxId);
|
|
|
|
|
builder.add(InsTxOutIndex, item.outputIndex);
|
|
|
|
|
builder.add(InsBlockHeight, item.blockHeight);
|
|
|
|
|
builder.add(InsOffsetInBlock, item.offsetInBlock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_data.push_back(builder.buffer());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::deque<Streaming::ConstBuffer> UndoBlockBuilder::finish() const
|
|
|
|
|
{
|
|
|
|
|
return m_data;
|
2017-09-05 13:44:41 +02:00
|
|
|
}
|