Hush Full Node software. We were censored from Github, this is where all development happens now. https://hush.is
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

260 lines
7.0 KiB

// Copyright (c) 2019-2020 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <cryptoconditions.h>
#include <gtest/gtest.h>
#include "cc/eval.h"
#include "importcoin.h"
#include "base58.h"
#include "core_io.h"
#include "key.h"
#include "main.h"
#include "primitives/transaction.h"
#include "script/cc.h"
#include "script/interpreter.h"
#include "script/serverchecker.h"
#include "txmempool.h"
#include "testutils.h"
extern Eval* EVAL_TEST;
namespace TestCoinImport {
static uint8_t testNum = 0;
class TestCoinImport : public ::testing::Test, public Eval {
public:
CMutableTransaction burnTx; std::vector<uint8_t> rawproof;
std::vector<CTxOut> payouts;
TxProof proof;
uint256 MoMoM;
CMutableTransaction importTx;
uint32_t testCcid = 2;
std::string testSymbol = "PIZZA";
CAmount amount = 100;
void SetImportTx() {
burnTx.vout.resize(0);
burnTx.vout.push_back(MakeBurnOutput(amount, testCcid, testSymbol, payouts,rawproof));
importTx = CMutableTransaction(MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts));
MoMoM = burnTx.GetHash(); // TODO: an actual branch
}
uint32_t GetAssetchainsCC() const { return testCcid; }
std::string GetAssetchainsSymbol() const { return testSymbol; }
bool GetProofRoot(uint256 hash, uint256 &momom) const
{
if (MoMoM.IsNull()) return false;
momom = MoMoM;
return true;
}
protected:
static void SetUpTestCase() { setupChain(); }
virtual void SetUp() {
ASSETCHAINS_CC = 1;
EVAL_TEST = this;
std::vector<uint8_t> fakepk;
fakepk.resize(33);
fakepk.begin()[0] = testNum++;
payouts.push_back(CTxOut(amount, CScript() << fakepk << OP_CHECKSIG));
SetImportTx();
}
void TestRunCCEval(CMutableTransaction mtx)
{
CTransaction importTx(mtx);
PrecomputedTransactionData txdata(importTx);
ServerTransactionSignatureChecker checker(&importTx, 0, 0, false, txdata);
CValidationState verifystate;
if (!VerifyCoinImport(importTx.vin[0].scriptSig, checker, verifystate))
printf("TestRunCCEval: %s\n", verifystate.GetRejectReason().data());
}
};
TEST_F(TestCoinImport, testProcessImportThroughPipeline)
{
CValidationState mainstate;
CTransaction tx(importTx);
// first should work
acceptTxFail(tx);
// should fail in mempool
ASSERT_FALSE(acceptTx(tx, mainstate));
EXPECT_EQ("already in mempool", mainstate.GetRejectReason());
// should be in persisted UTXO set
generateBlock();
ASSERT_FALSE(acceptTx(tx, mainstate));
EXPECT_EQ("already have coins", mainstate.GetRejectReason());
ASSERT_TRUE(pcoinsTip->HaveCoins(tx.GetHash()));
// Now disconnect the block
CValidationState invalstate;
if (!InvalidateBlock(invalstate, chainActive.Tip())) {
FAIL() << invalstate.GetRejectReason();
}
ASSERT_FALSE(pcoinsTip->HaveCoins(tx.GetHash()));
// should be back in mempool
ASSERT_FALSE(acceptTx(tx, mainstate));
EXPECT_EQ("already in mempool", mainstate.GetRejectReason());
}
TEST_F(TestCoinImport, testImportTombstone)
{
CValidationState mainstate;
// By setting an unspendable output, there will be no addition to UTXO
// Nonetheless, we dont want to be able to import twice
payouts[0].scriptPubKey = CScript() << OP_RETURN;
SetImportTx();
MoMoM = burnTx.GetHash(); // TODO: an actual branch
CTransaction tx(importTx);
// first should work
acceptTxFail(tx);
// should be in persisted UTXO set
generateBlock();
ASSERT_FALSE(acceptTx(tx, mainstate));
EXPECT_EQ("import tombstone exists", mainstate.GetRejectReason());
ASSERT_TRUE(pcoinsTip->HaveCoins(burnTx.GetHash()));
// Now disconnect the block
CValidationState invalstate;
if (!InvalidateBlock(invalstate, chainActive.Tip())) {
FAIL() << invalstate.GetRejectReason();
}
// Tombstone should be gone from utxo set
ASSERT_FALSE(pcoinsTip->HaveCoins(burnTx.GetHash()));
// should be back in mempool
ASSERT_FALSE(acceptTx(tx, mainstate));
EXPECT_EQ("already in mempool", mainstate.GetRejectReason());
}
TEST_F(TestCoinImport, testNoVouts)
{
importTx.vout.resize(0);
TestRunCCEval(importTx);
EXPECT_EQ("too-few-vouts", state.GetRejectReason());
}
TEST_F(TestCoinImport, testInvalidParams)
{
std::vector<uint8_t> payload = E_MARSHAL(ss << EVAL_IMPORTCOIN; ss << 'a');
importTx.vin[0].scriptSig = CScript() << payload;
TestRunCCEval(importTx);
EXPECT_EQ("invalid-params", state.GetRejectReason());
}
TEST_F(TestCoinImport, testNonCanonical)
{
importTx.nLockTime = 10;
TestRunCCEval(importTx);
EXPECT_EQ("non-canonical", state.GetRejectReason());
}
TEST_F(TestCoinImport, testInvalidBurnOutputs)
{
burnTx.vout.resize(0);
MoMoM = burnTx.GetHash(); // TODO: an actual branch
CTransaction tx = MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts);
TestRunCCEval(tx);
EXPECT_EQ("invalid-burn-tx", state.GetRejectReason());
}
TEST_F(TestCoinImport, testInvalidBurnParams)
{
burnTx.vout.back().scriptPubKey = CScript() << OP_RETURN << E_MARSHAL(ss << VARINT(testCcid));
MoMoM = burnTx.GetHash(); // TODO: an actual branch
CTransaction tx = MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts);
TestRunCCEval(tx);
EXPECT_EQ("invalid-burn-tx", state.GetRejectReason());
}
TEST_F(TestCoinImport, testWrongChainId)
{
testCcid = 0;
TestRunCCEval(importTx);
EXPECT_EQ("importcoin-wrong-chain", state.GetRejectReason());
}
TEST_F(TestCoinImport, testInvalidBurnAmount)
{
burnTx.vout.back().nValue = 0;
MoMoM = burnTx.GetHash(); // TODO: an actual branch
CTransaction tx = MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts);
TestRunCCEval(tx);
EXPECT_EQ("invalid-burn-amount", state.GetRejectReason());
}
TEST_F(TestCoinImport, testPayoutTooHigh)
{
importTx.vout[1].nValue = 101;
TestRunCCEval(importTx);
EXPECT_EQ("payout-too-high", state.GetRejectReason());
}
TEST_F(TestCoinImport, testAmountInOpret)
{
importTx.vout[0].nValue = 1;
TestRunCCEval(importTx);
EXPECT_EQ("non-canonical", state.GetRejectReason());
}
TEST_F(TestCoinImport, testInvalidPayouts)
{
importTx.vout[1].nValue = 40;
importTx.vout.push_back(importTx.vout[0]);
TestRunCCEval(importTx);
EXPECT_EQ("wrong-payouts", state.GetRejectReason());
}
TEST_F(TestCoinImport, testCouldntLoadMomom)
{
MoMoM.SetNull();
TestRunCCEval(importTx);
EXPECT_EQ("coudnt-load-momom", state.GetRejectReason());
}
TEST_F(TestCoinImport, testMomomCheckFail)
{
MoMoM.SetNull();
MoMoM.begin()[0] = 1;
TestRunCCEval(importTx);
EXPECT_EQ("momom-check-fail", state.GetRejectReason());
}
TEST_F(TestCoinImport, testGetCoinImportValue)
{
ASSERT_EQ(100, GetCoinImportValue(importTx));
}
} /* namespace TestCoinImport */