cpp test suite for cryptoconditions integration

This commit is contained in:
Scott Sadler
2018-04-01 21:18:01 -03:00
parent 563581aff4
commit 4c121ffdb0
19 changed files with 336 additions and 465 deletions

View File

@@ -0,0 +1,226 @@
#include <cryptoconditions.h>
#include <gtest/gtest.h>
#include "base58.h"
#include "key.h"
#include "komodo_cc.h"
#include "primitives/transaction.h"
#include "script/interpreter.h"
#include "script/serverchecker.h"
#define VCH(a,b) std::vector<unsigned char>(a, a + b)
std::string pubkey = "0205a8ad0c1dbc515f149af377981aab58b836af008d4d7ab21bd76faf80550b47";
std::string secret = "UxFWWxsf1d7w7K5TvAWSkeX4H95XQKwdwGv49DXwWUTzPTTjHBbU";
CKey notaryKey;
char ccjsonerr[1000] = "\0";
#define CCFromJson(o,s) \
o = cc_conditionFromJSONString(s, ccjsonerr); \
if (!o) FAIL() << "bad json: " << ccjsonerr;
CScript CCPubKey(const CC *cond) {
unsigned char buf[1000];
size_t len = cc_conditionBinary(cond, buf);
return CScript() << VCH(buf, len) << OP_CHECKCRYPTOCONDITION;
}
CScript CCSig(const CC *cond) {
unsigned char buf[1000];
size_t len = cc_fulfillmentBinary(cond, buf, 1000);
auto ffill = VCH(buf, len);
ffill.push_back(SIGHASH_ALL);
return CScript() << ffill;
}
void CCSign(CMutableTransaction &tx, CC *cond) {
tx.vin.resize(1);
PrecomputedTransactionData txdata(tx);
uint256 sighash = SignatureHash(CCPubKey(cond), tx, 0, SIGHASH_ALL, 0, 0, &txdata);
int out = cc_signTreeSecp256k1Msg32(cond, notaryKey.begin(), sighash.begin());
tx.vin[0].scriptSig = CCSig(cond);
}
class CCTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
SelectParams(CBaseChainParams::REGTEST);
// Notary key
CBitcoinSecret vchSecret;
// this returns false due to network prefix mismatch but works anyway
vchSecret.SetString(secret);
notaryKey = vchSecret.GetKey();
}
virtual void SetUp() {
// enable CC
ASSETCHAINS_CC = 1;
}
};
TEST_F(CCTest, testIsPayToCryptoCondition)
{
CScript s = CScript() << VCH("a", 1);
ASSERT_FALSE(s.IsPayToCryptoCondition());
s = CScript() << VCH("a", 1) << OP_CHECKCRYPTOCONDITION;
ASSERT_TRUE(s.IsPayToCryptoCondition());
s = CScript() << OP_CHECKCRYPTOCONDITION;
ASSERT_FALSE(s.IsPayToCryptoCondition());
}
TEST_F(CCTest, testMayAcceptCryptoCondition)
{
CC *cond;
// ok
CCFromJson(cond, R"!!(
{ "type": "threshold-sha-256",
"threshold": 2,
"subfulfillments": [
{ "type": "secp256k1-sha-256", "publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH" }
]
})!!");
ASSERT_TRUE(CCPubKey(cond).MayAcceptCryptoCondition());
// prefix not allowed
CCFromJson(cond, R"!!(
{ "type": "prefix-sha-256",
"prefix": "abc",
"maxMessageLength": 10,
"subfulfillment":
{ "type": "secp256k1-sha-256", "publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH" }
})!!");
ASSERT_FALSE(CCPubKey(cond).MayAcceptCryptoCondition());
// has no signature nodes
CCFromJson(cond, R"!!(
{ "type": "threshold-sha-256",
"threshold": 1,
"subfulfillments": [
{ "type": "eval-sha-256", "method": "test", "params": "" },
{ "type": "eval-sha-256", "method": "test", "params": "" }
]
})!!");
ASSERT_FALSE(CCPubKey(cond).MayAcceptCryptoCondition());
}
TEST_F(CCTest, testVerifyCryptoCondition)
{
CC *cond;
ScriptError error;
CMutableTransaction mtxTo;
auto Verify = [&] (const CC *cond) {
CAmount amount;
CTransaction txTo(mtxTo);
PrecomputedTransactionData txdata(txTo);
auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, txdata);
return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error);
};
// ok
CCFromJson(cond, R"!!({
"type": "secp256k1-sha-256",
"publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH"
})!!");
CCSign(mtxTo, cond);
ASSERT_TRUE(Verify(cond));
// has signature nodes
CCFromJson(cond, R"!!({
"type": "threshold-sha-256",
"threshold": 1,
"subfulfillments": [
{ "type": "preimage-sha-256", "preimage": "" },
{ "type": "secp256k1-sha-256", "publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH" }
]
})!!");
cond->threshold = 2;
CCSign(mtxTo, cond);
ASSERT_TRUE(Verify(cond));
// no signatures; the preimage will get encoded as a fulfillment because it's cheaper
// and the secp256k1 node will get encoded as a condition
cond->threshold = 1;
ASSERT_FALSE(Verify(cond));
// here the signature is set wrong
cond->threshold = 2;
ASSERT_TRUE(Verify(cond));
memset(cond->subconditions[1]->signature, 0, 32);
ASSERT_FALSE(Verify(cond));
}
TEST_F(CCTest, testVerifyEvalCondition)
{
CC *cond;
ScriptError error;
CMutableTransaction mtxTo;
auto Verify = [&] (const CC *cond) {
CAmount amount;
CTransaction txTo(mtxTo);
PrecomputedTransactionData txdata(txTo);
auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, txdata);
return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error);
};
// ok
CCFromJson(cond, R"!!({
"type": "threshold-sha-256",
"threshold": 2,
"subfulfillments": [
{ "type": "secp256k1-sha-256", "publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH" },
{ "type": "eval-sha-256", "method": "TestEval", "params": "" }
]})!!");
CC *ecCond = cond->subconditions[1];
ecCond->paramsBin = (unsigned char*) "TestEval";
ecCond->paramsBinLength = 8;
CCSign(mtxTo, cond); // will reorder subconditions
ASSERT_TRUE(Verify(cond));
ecCond->paramsBin = (unsigned char*) "FailEval";
ASSERT_FALSE(Verify(cond));
}
TEST_F(CCTest, testCryptoConditionsDisabled)
{
CC *cond;
ScriptError error;
CMutableTransaction mtxTo;
auto Verify = [&] (const CC *cond) {
CAmount amount;
CTransaction txTo(mtxTo);
PrecomputedTransactionData txdata(txTo);
auto checker = ServerTransactionSignatureChecker(&txTo, 0, amount, false, txdata);
return VerifyScript(CCSig(cond), CCPubKey(cond), 0, checker, 0, &error);
};
// ok
CCFromJson(cond, R"!!({
"type": "secp256k1-sha-256",
"publicKey": "AgWorQwdvFFfFJrzd5gaq1i4Nq8AjU16shvXb6+AVQtH"
})!!");
CCSign(mtxTo, cond);
ASSERT_TRUE(Verify(cond));
ASSETCHAINS_CC = 0;
ASSERT_FALSE(Verify(cond));
}