157 lines
4.2 KiB
C++
157 lines
4.2 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include "main.h"
|
|
#include "util/test.h"
|
|
#include "zcash/History.hpp"
|
|
|
|
HistoryNode getLeafN(uint64_t block_num) {
|
|
HistoryNode node = libzcash::NewV1Leaf(
|
|
uint256(),
|
|
block_num*10,
|
|
block_num*13,
|
|
uint256(),
|
|
uint256(),
|
|
block_num,
|
|
3
|
|
);
|
|
return node;
|
|
}
|
|
|
|
TEST(History, Smoky) {
|
|
// Fake an empty view
|
|
CCoinsViewDummy fakeDB;
|
|
CCoinsViewCache view(&fakeDB);
|
|
|
|
uint32_t epochId = 0;
|
|
|
|
// Test initial value
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 0);
|
|
|
|
view.PushHistoryNode(epochId, getLeafN(1));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 1);
|
|
|
|
view.PushHistoryNode(epochId, getLeafN(2));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 3);
|
|
|
|
view.PushHistoryNode(epochId, getLeafN(3));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 4);
|
|
|
|
view.PushHistoryNode(epochId, getLeafN(4));
|
|
|
|
uint256 h4Root = view.GetHistoryRoot(epochId);
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 7);
|
|
|
|
view.PushHistoryNode(epochId, getLeafN(5));
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 8);
|
|
|
|
view.PopHistoryNode(epochId);
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epochId), 7);
|
|
EXPECT_EQ(h4Root, view.GetHistoryRoot(epochId));
|
|
}
|
|
|
|
|
|
TEST(History, EpochBoundaries) {
|
|
// Fake an empty view
|
|
CCoinsViewDummy fakeDB;
|
|
CCoinsViewCache view(&fakeDB);
|
|
|
|
// Test with the Heartwood and Canopy epochs
|
|
uint32_t epoch1 = 0xf5b9230b;
|
|
uint32_t epoch2 = 0xe9ff75a6;
|
|
|
|
view.PushHistoryNode(epoch1, getLeafN(1));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 1);
|
|
|
|
view.PushHistoryNode(epoch1, getLeafN(2));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 3);
|
|
|
|
view.PushHistoryNode(epoch1, getLeafN(3));
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 4);
|
|
|
|
view.PushHistoryNode(epoch1, getLeafN(4));
|
|
|
|
uint256 h4Root = view.GetHistoryRoot(epoch1);
|
|
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 7);
|
|
|
|
view.PushHistoryNode(epoch1, getLeafN(5));
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 8);
|
|
|
|
|
|
// Move to Canopy epoch
|
|
view.PushHistoryNode(epoch2, getLeafN(6));
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 8);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 1);
|
|
|
|
view.PushHistoryNode(epoch2, getLeafN(7));
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 8);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 3);
|
|
|
|
view.PushHistoryNode(epoch2, getLeafN(8));
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 8);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 4);
|
|
|
|
// Rolling epoch back to 1
|
|
view.PopHistoryNode(epoch2);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 3);
|
|
|
|
view.PopHistoryNode(epoch2);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 1);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 8);
|
|
|
|
// And even rolling epoch 1 back a bit
|
|
view.PopHistoryNode(epoch1);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch1), 7);
|
|
|
|
// And also rolling epoch 2 back to 0
|
|
view.PopHistoryNode(epoch2);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 0);
|
|
|
|
// Trying to truncate an empty tree is a no-op
|
|
view.PopHistoryNode(epoch2);
|
|
EXPECT_EQ(view.GetHistoryLength(epoch2), 0);
|
|
|
|
}
|
|
|
|
TEST(History, GarbageMemoryHash) {
|
|
const auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_HEARTWOOD].nBranchId;
|
|
|
|
CCoinsViewDummy fakeDB;
|
|
CCoinsViewCache view(&fakeDB);
|
|
|
|
// Hash two history nodes
|
|
HistoryNode node0 = getLeafN(1);
|
|
HistoryNode node1 = getLeafN(2);
|
|
|
|
view.PushHistoryNode(consensusBranchId, node0);
|
|
view.PushHistoryNode(consensusBranchId, node1);
|
|
|
|
uint256 historyRoot = view.GetHistoryRoot(consensusBranchId);
|
|
|
|
// Change garbage memory and re-hash nodes
|
|
CCoinsViewDummy fakeDBGarbage;
|
|
CCoinsViewCache viewGarbage(&fakeDBGarbage);
|
|
|
|
HistoryNode node0Garbage = getLeafN(1);
|
|
HistoryNode node1Garbage = getLeafN(2);
|
|
|
|
node0Garbage[NODE_SERIALIZED_LENGTH - 1] = node0[NODE_SERIALIZED_LENGTH - 1] ^ 1;
|
|
node1Garbage[NODE_SERIALIZED_LENGTH - 1] = node1[NODE_SERIALIZED_LENGTH - 1] ^ 1;
|
|
|
|
viewGarbage.PushHistoryNode(consensusBranchId, node0Garbage);
|
|
viewGarbage.PushHistoryNode(consensusBranchId, node1Garbage);
|
|
|
|
uint256 historyRootGarbage = viewGarbage.GetHistoryRoot(consensusBranchId);
|
|
|
|
// Check history root and garbage history root are equal
|
|
EXPECT_EQ(historyRoot, historyRootGarbage);
|
|
}
|