Permalink
Browse files

[FT] Add new feature -ft-strict

In Flexible Transactions we have undefined tokens which are ignored by
current software if present. This allows nodes to stay compatible when new
tokens are invented.
For miners this policy rule should likely be turned on so transactions that
use tokens that are not yet defined will be rejected.
  • Loading branch information...
zander committed Feb 10, 2017
1 parent 7d30bcc commit 658470d332fdf67a249c586b42697352ddce2e91
Showing with 63 additions and 0 deletions.
  1. +1 −0 src/allowed_args.cpp
  2. +1 −0 src/init.cpp
  3. +25 −0 src/policy/policy.cpp
  4. +36 −0 src/test/transaction_tests.cpp
View
@@ -89,6 +89,7 @@ const std::set<std::string> BITCOIND_ARGS
"externalip",
"expeditedblock",
"flextrans",
+ "ft-strict",
"flushwallet",
"forcednsseed",
"fuzzmessagestest",
View
@@ -455,6 +455,7 @@ std::string HelpMessage(HelpMessageMode mode)
if (showDebug)
strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0");
strUsage += HelpMessageOpt("-flextrans", "Accept and relay transactions of version 4");
+ strUsage += HelpMessageOpt("-ft-strict", "On incoming FlexTrans transactions reject tx that have not specified tokens. default: false");
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), DEFAULT_GENERATE));
strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), DEFAULT_GENERATE_THREADS));
strUsage += HelpMessageOpt("-gencoinbase=<pubkey>", "When generating coins a coinbase has to be provided in the form of a public key");
View
@@ -69,6 +69,31 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
}
}
+ // In Flexible Transactions there are no-operation fields that are undefined
+ // in order to allow future expansion. Normal nodes would ignore those tags
+ // but a node (for instance a miner) may want to reject transactions that use
+ // those not yet defined ones because we know this client will always have
+ // the latest ruleset.
+ if (tx.nVersion == 4 && flexTransActive && GetBoolArg("-ft-strict", false)) {
+ CDataStream ds(0, 4);
+ tx.Serialize(ds, 0, 4);
+ std::vector<char> txData(ds.begin(), ds.end());
+ CDataStream stream(txData, 0, 4);
+ try {
+ (void) ser_readdata32(stream);
+ auto tokens = UnserializeCMFs(stream, Consensus::TxEnd, 0, 4);
+ for (unsigned int index = 0; index < tokens.size(); ++index) {
+ if (tokens[index].tag > Consensus::CoinbaseMessage) {
+ reason = "ft-strict";
+ return false;
+ }
+ }
+ } catch(std::exception &e) {
+ assert(false); // not being able to parse the thing I just saved is a coding error, not a data error.
+ return false;
+ }
+ }
+
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
@@ -741,6 +741,42 @@ BOOST_AUTO_TEST_CASE(test_version4_isStandard)
tx.nVersion = 4;
BOOST_CHECK_EQUAL(IsStandardTx(tx, reason), true);
+ // 0 simple, is standard;
+ // 1 add illegal token. not standard
+ // 2 add illegal token, but dont set flag. is standard;
+ for (int i = 0 ; i < 3; ++i) {
+ try {
+ CDataStream s(0, 4);
+ ser_writedata32(s, 4);
+ CMFToken hash(Consensus::TxInPrevHash, tx.vin[0].prevout.hash);
+ hash.Serialize(s, 0, 4);
+ CMFToken outValue(Consensus::TxOutValue, (uint64_t) 1000);
+ outValue.Serialize(s, 0, 4);
+ std::vector<char> script(tx.vout[0].scriptPubKey.begin(), tx.vout[0].scriptPubKey.end());
+ CMFToken outScript(Consensus::TxOutScript, script);
+ outScript.Serialize(s, 0, 4);
+
+ if (i >= 1) {
+ CMFToken invalidToken(10, true); // 9 is currently the max, 10 is thus a soft-fork and will be ignored
+ invalidToken.Serialize(s, 0, 4);
+ }
+ CMFToken end(Consensus::TxEnd, true);
+ end.Serialize(s, 0, 4);
+
+ std::vector<char> txData(s.begin(), s.end());
+ CDataStream stream(txData, 0, 4);
+ CTransaction tx2;
+ tx2.Unserialize(stream, 0, 4);
+
+ mapArgs.clear();
+ if (i < 2)
+ mapArgs["-ft-strict"] = "1";
+ BOOST_CHECK_EQUAL(IsStandardTx(tx2, reason), i != 1);
+ } catch (...) {
+ BOOST_CHECK(false);
+ }
+ }
+
TxUtils::disallowNewTransactions();
}

0 comments on commit 658470d

Please sign in to comment.