mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-12 16:17:53 +00:00
Namespace creation security fixes.
This commit is contained in:
commit
afd37169e7
@ -4,7 +4,7 @@ define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 16)
|
||||
define(_CLIENT_VERSION_REVISION, 6)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, false)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2020)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Kevacoin Core]])
|
||||
|
@ -122,24 +122,27 @@ public:
|
||||
consensus.nPowTargetSpacing = 2.0 * 60; // Two minutes
|
||||
consensus.fPowAllowMinDifficultyBlocks = false;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nRuleChangeActivationThreshold = 6048; // 75% of 8064
|
||||
consensus.nMinerConfirmationWindow = 8064; // nPowTargetTimespan / nPowTargetSpacing * 4
|
||||
consensus.nRuleChangeActivationThreshold = 1620; // 75% of 2160
|
||||
consensus.nMinerConfirmationWindow = 2160; // 3 days
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
|
||||
|
||||
// Deployment of BIP68, BIP112, and BIP113.
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1485561600; // January 28, 2017
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = -1; // Consensus::BIP9Deployment::ALWAYS_ACTIVE
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1517356801; // January 31st, 2018
|
||||
|
||||
// Deployment of SegWit (BIP141, BIP143, and BIP147)
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1485561600; // January 28, 2017
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = -1; // Consensus::BIP9Deployment::ALWAYS_ACTIVE
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1517356801; // January 31st, 2018
|
||||
|
||||
// Deployment of NsFix
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].bit = 3;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nStartTime = 1594771200; // 07/15/2020 @ 12:00am
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nTimeout = 1598745600; // 08/30/2020 @ 12:00am
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000999a6a433f7");
|
||||
|
||||
@ -211,30 +214,33 @@ public:
|
||||
consensus.BIP34Hash = uint256S("0xa8dbaa66a9266348f6527fe528efea73227d51938befb81d5a1521cebd319c4a"); // Genesis
|
||||
consensus.BIP65Height = 1;
|
||||
consensus.BIP66Height = 1;
|
||||
consensus.RandomXHeight = 6030;
|
||||
consensus.RandomXHeight = 3;
|
||||
consensus.powLimit = uint256S("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 2.0 * 60; // Two minutes
|
||||
consensus.nPowTargetSpacing = 2.0 * 60; // Two minutes
|
||||
consensus.fPowAllowMinDifficultyBlocks = true;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
|
||||
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
|
||||
consensus.fPowNoRetargeting = true;
|
||||
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
|
||||
consensus.nMinerConfirmationWindow = 144; // nPowTargetTimespan / nPowTargetSpacing
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
|
||||
|
||||
// Deployment of BIP68, BIP112, and BIP113.
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1483228800; // January 1, 2017
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = -1; // Consensus::BIP9Deployment::ALWAYS_ACTIVE
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1517356801; // January 31st, 2018
|
||||
|
||||
// Deployment of SegWit (BIP141, BIP143, and BIP147)
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1483228800; // January 1, 2017
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = -1; // Consensus::BIP9Deployment::ALWAYS_ACTIVE
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1517356801; // January 31st, 2018
|
||||
|
||||
// Deployment of NsFix
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].bit = 3;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nStartTime = 1594771200; // 07/15/2020 @ 12:00am
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nTimeout = 1598745600; // 08/30/2020 @ 12:00am
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000000000001000");
|
||||
|
||||
@ -312,15 +318,22 @@ public:
|
||||
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
|
||||
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
|
||||
//consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
|
||||
// Deployment of NsFix
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].bit = 3;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nStartTime = 1517356801; // January 31st, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_NSFIX].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x00");
|
||||
|
||||
|
@ -18,6 +18,7 @@ enum DeploymentPos
|
||||
DEPLOYMENT_TESTDUMMY,
|
||||
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
|
||||
DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147.
|
||||
DEPLOYMENT_NSFIX, // Deployment of fix of Keva namespace creation.
|
||||
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
|
||||
MAX_VERSION_BITS_DEPLOYMENTS
|
||||
};
|
||||
|
@ -144,9 +144,9 @@ bool CKevaMemPool::validateNamespace(const CTransaction& tx, const valtype& name
|
||||
if (tx.vin.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
valtype kevaNamespace = ToByteVector(Hash160(ToByteVector(tx.vin[0].prevout.hash)));
|
||||
const std::vector<unsigned char>& ns_prefix = Params().Base58Prefix(CChainParams::KEVA_NAMESPACE);
|
||||
kevaNamespace.insert(kevaNamespace.begin(), ns_prefix.begin(), ns_prefix.end());
|
||||
valtype kevaNamespace;
|
||||
bool nsFixEnabled = IsNsFixEnabled(chainActive.Tip(), Params().GetConsensus());
|
||||
CKevaScript::generateNamespace(tx.vin[0].prevout.hash, tx.vin[0].prevout.n, kevaNamespace, Params(), nsFixEnabled);
|
||||
return kevaNamespace == nameSpace;
|
||||
}
|
||||
|
||||
@ -336,7 +336,17 @@ CheckKevaTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
if (nameOpOut.getOpNamespaceDisplayName().size () > MAX_VALUE_LENGTH) {
|
||||
return state.Invalid (error ("CheckKevaTransaction: display name value too long"));
|
||||
}
|
||||
return true;
|
||||
|
||||
LOCK(cs_main);
|
||||
bool nsFixEnabled = IsNsFixEnabled(chainActive.Tip(), Params().GetConsensus());
|
||||
if (!nsFixEnabled) {
|
||||
// This is a historic bug.
|
||||
return true;
|
||||
}
|
||||
// Make sure the namespace Id is correctly derived from vin[0].
|
||||
valtype expectedNamespace;
|
||||
CKevaScript::generateNamespace(tx.vin[0].prevout.hash, tx.vin[0].prevout.n, expectedNamespace, Params(), true);
|
||||
return expectedNamespace == nameOpOut.getOpNamespace();
|
||||
}
|
||||
|
||||
assert(nameOpOut.isAnyUpdate());
|
||||
|
@ -7,7 +7,9 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <script/keva.h>
|
||||
#include <keva/common.h>
|
||||
#include <hash.h>
|
||||
#include <validation.h>
|
||||
|
||||
const std::string CKevaScript::KEVA_DISPLAY_NAME_KEY = "_KEVA_NS_";
|
||||
|
||||
@ -103,7 +105,20 @@ CScript CKevaScript::buildKevaNamespace(const CScript& addr, const valtype& name
|
||||
return prefix + addr;
|
||||
}
|
||||
|
||||
CScript CKevaScript::replaceKevaNamespace(const CScript& oldScript, const uint256& txId, valtype& kaveNamespace, const CChainParams& params)
|
||||
void CKevaScript::generateNamespace(const uint256& txId, int n, valtype& kevaNamespace, const CChainParams& params, bool nsFixEnabled)
|
||||
{
|
||||
auto vin = ToByteVector(txId);
|
||||
if (nsFixEnabled) {
|
||||
// The UXTO is vin and the number. This is the correct way to generate unique namespace.
|
||||
auto nVal = ValtypeFromString(std::to_string(n));
|
||||
vin.insert(vin.end(), nVal.begin(), nVal.end());
|
||||
}
|
||||
kevaNamespace = ToByteVector(Hash160(vin));
|
||||
const std::vector<unsigned char>& ns_prefix = params.Base58Prefix(CChainParams::KEVA_NAMESPACE);
|
||||
kevaNamespace.insert(kevaNamespace.begin(), ns_prefix.begin(), ns_prefix.end());
|
||||
}
|
||||
|
||||
CScript CKevaScript::replaceKevaNamespace(const CScript& oldScript, const uint256& txId, int n, valtype& kaveNamespace, const CChainParams& params, bool nsFixEnabled)
|
||||
{
|
||||
CKevaScript kevaOp(oldScript);
|
||||
if (!kevaOp.isNamespaceRegistration()) {
|
||||
@ -112,10 +127,6 @@ CScript CKevaScript::replaceKevaNamespace(const CScript& oldScript, const uint25
|
||||
}
|
||||
|
||||
const valtype& displayName = kevaOp.getOpNamespaceDisplayName();
|
||||
kaveNamespace = ToByteVector(Hash160(ToByteVector(txId)));
|
||||
|
||||
const std::vector<unsigned char>& ns_prefix = params.Base58Prefix(CChainParams::KEVA_NAMESPACE);
|
||||
kaveNamespace.insert(kaveNamespace.begin(), ns_prefix.begin(), ns_prefix.end());
|
||||
CKevaScript::generateNamespace(txId, n, kaveNamespace, params, nsFixEnabled);
|
||||
return CKevaScript::buildKevaNamespace(kevaOp.getAddress(), kaveNamespace, displayName);
|
||||
}
|
||||
|
||||
|
@ -273,8 +273,9 @@ public:
|
||||
*/
|
||||
static CScript buildKevaDelete(const CScript& addr, const valtype& nameSpace, const valtype& key);
|
||||
|
||||
static void generateNamespace(const uint256& txId, int n, valtype& kaveNamespace, const CChainParams& params, bool nsFixEnabled);
|
||||
|
||||
static CScript replaceKevaNamespace(const CScript& oldScript, const uint256& txId, valtype& kaveNamespace, const CChainParams& params);
|
||||
static CScript replaceKevaNamespace(const CScript& oldScript, const uint256& txId, int n, valtype& kaveNamespace, const CChainParams& params, bool nsFixEnabled);
|
||||
|
||||
};
|
||||
|
||||
|
@ -66,13 +66,19 @@ BOOST_AUTO_TEST_CASE(keva_scripts)
|
||||
|
||||
const uint256 txId = uint256S("0x78f49add562dc33e4cd61aa45c54012509ed4a53308908dd07f5634437939273");
|
||||
valtype actualNamespace;
|
||||
script = CKevaScript::replaceKevaNamespace(script, txId, actualNamespace, Params());
|
||||
int n = 99999;
|
||||
script = CKevaScript::replaceKevaNamespace(script, txId, n, actualNamespace, Params(), true);
|
||||
const CKevaScript opReplace(script);
|
||||
BOOST_CHECK(opReplace.isKevaOp());
|
||||
BOOST_CHECK(opReplace.getAddress() == addr);
|
||||
BOOST_CHECK(!opReplace.isAnyUpdate());
|
||||
BOOST_CHECK(opReplace.getKevaOp() == OP_KEVA_NAMESPACE);
|
||||
valtype expectedNamespace = ToByteVector(Hash160(ToByteVector(txId)));
|
||||
|
||||
auto vin = ToByteVector(txId);
|
||||
auto nVal = ValtypeFromString(std::to_string(n));
|
||||
vin.insert(vin.end(), nVal.begin(), nVal.end());
|
||||
|
||||
valtype expectedNamespace = ToByteVector(Hash160(ToByteVector(vin)));
|
||||
const std::vector<unsigned char>& ns_prefix = Params().Base58Prefix(CChainParams::KEVA_NAMESPACE);
|
||||
expectedNamespace.insert(expectedNamespace.begin(), ns_prefix.begin(), ns_prefix.end());
|
||||
BOOST_CHECK(opReplace.getOpNamespace() == expectedNamespace);
|
||||
|
@ -3120,6 +3120,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsNsFixEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_NSFIX, versionbitscache) == THRESHOLD_ACTIVE);
|
||||
}
|
||||
|
||||
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
|
@ -412,6 +412,9 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
||||
/** Check whether witness commitments are required for block. */
|
||||
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
|
||||
|
||||
/** Check whether Keva namespace creation fix is enabled. */
|
||||
bool IsNsFixEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
|
||||
|
||||
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
|
||||
bool RewindBlockIndex(const CChainParams& params);
|
||||
|
||||
|
@ -17,6 +17,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
|
||||
{
|
||||
/*.name =*/ "segwit",
|
||||
/*.gbt_force =*/ true,
|
||||
},
|
||||
{
|
||||
/*.name =*/ "nsfix",
|
||||
/*.gbt_force =*/ true,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2952,7 +2952,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
CScript dummyScript = iter->scriptPubKey;
|
||||
CKevaScript kevaOp(dummyScript);
|
||||
if (kevaOp.isKevaOp() && kevaOp.isNamespaceRegistration()) {
|
||||
iter->scriptPubKey = CKevaScript::replaceKevaNamespace(dummyScript, coin.outpoint.hash, kevaNamespace, Params());
|
||||
bool nsFixEnabled = IsNsFixEnabled(chainActive.Tip(), Params().GetConsensus());
|
||||
iter->scriptPubKey = CKevaScript::replaceKevaNamespace(dummyScript, coin.outpoint.hash, coin.outpoint.n, kevaNamespace, Params(), nsFixEnabled);
|
||||
kevaDummyReplaced = true;
|
||||
break;
|
||||
}
|
||||
|
99
test/functional/feature_keva_ns.py
Executable file
99
test/functional/feature_keva_ns.py
Executable file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016-2017 The Bitcoin Core developers
|
||||
# Copyright (c) 2018-2019 The Kevacoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the Key-Value Store."""
|
||||
|
||||
from test_framework.blocktools import witness_script, send_to_witness
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from io import BytesIO
|
||||
from string import Template
|
||||
import decimal
|
||||
import re
|
||||
import json
|
||||
|
||||
class DecimalEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, decimal.Decimal):
|
||||
return float(o)
|
||||
return super(DecimalEncoder, self).default(o)
|
||||
|
||||
class KevaTest(BitcoinTestFramework):
|
||||
|
||||
def sync_generate(self, node, num):
|
||||
self.sync_all()
|
||||
node.generate(num)
|
||||
self.sync_all()
|
||||
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[1], 0)
|
||||
connect_nodes(self.nodes[2], 0)
|
||||
self.sync_all()
|
||||
|
||||
def dumpTx(self, tx):
|
||||
print(json.dumps(self.nodes[0].decoderawtransaction(self.nodes[0].getrawtransaction(tx)), indent=4, cls=DecimalEncoder))
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].generate(2)
|
||||
hash = self.nodes[0].getbestblockhash()
|
||||
# THRESHOLD_DEFINED
|
||||
assert(self.nodes[0].getblock(hash)['versionHex'] == '20000000')
|
||||
|
||||
self.nodes[0].generate(150)
|
||||
hash = self.nodes[0].getbestblockhash()
|
||||
# THRESHOLD_STARTED
|
||||
assert(self.nodes[0].getblock(hash)['versionHex'] == '20000008')
|
||||
|
||||
self.nodes[0].generate(150)
|
||||
hash = self.nodes[0].getbestblockhash()
|
||||
# THRESHOLD_LOCKED_IN
|
||||
assert(self.nodes[0].getblock(hash)['versionHex'] == '20000008')
|
||||
|
||||
self.nodes[0].generate(150)
|
||||
hash = self.nodes[0].getbestblockhash()
|
||||
# THRESHOLD_ACITVE
|
||||
assert(self.nodes[0].getblock(hash)['versionHex'] == '20000000')
|
||||
|
||||
addr1 = self.nodes[1].getnewaddress()
|
||||
addr2 = self.nodes[2].getnewaddress()
|
||||
amount = Template('{"$addr1":1,"$addr2":1}').substitute(addr1=addr1, addr2=addr2)
|
||||
amountJson = json.loads(amount)
|
||||
self.nodes[0].sendmany("", amountJson)
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
ns1 = (self.nodes[1].keva_namespace('NS 1'))["namespaceId"]
|
||||
ns2 = (self.nodes[2].keva_namespace('NS 2'))["namespaceId"]
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
# Since nsfix is enabled, the namespace will be the different.
|
||||
assert(ns1 != ns2)
|
||||
|
||||
# The namespace should be created.
|
||||
assert((self.nodes[0].keva_filter(ns1))[0]["value"] == 'NS 1')
|
||||
assert((self.nodes[0].keva_filter(ns2))[0]["value"] == 'NS 2')
|
||||
|
||||
self.nodes[1].keva_put(ns1, 'key', 'value 1')
|
||||
self.nodes[2].keva_put(ns2, 'key', 'value 2')
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
assert((self.nodes[0].keva_get(ns1, 'key'))["value"] == 'value 1')
|
||||
assert((self.nodes[0].keva_get(ns2, 'key'))["value"] == 'value 2')
|
||||
|
||||
self.nodes[0].generate(20)
|
||||
ns3 = (self.nodes[1].keva_namespace('NS 3'))["namespaceId"]
|
||||
ns4 = (self.nodes[2].keva_namespace('NS 4'))["namespaceId"]
|
||||
assert(ns3 != ns4)
|
||||
|
||||
# The namespace should be created.
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
assert((self.nodes[0].keva_filter(ns3))[0]["value"] == 'NS 3')
|
||||
assert((self.nodes[0].keva_filter(ns4))[0]["value"] == 'NS 4')
|
||||
|
||||
if __name__ == '__main__':
|
||||
KevaTest().main()
|
61
test/functional/feature_keva_ns_bug.py
Executable file
61
test/functional/feature_keva_ns_bug.py
Executable file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016-2017 The Bitcoin Core developers
|
||||
# Copyright (c) 2018-2019 The Kevacoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the Key-Value Store."""
|
||||
|
||||
from test_framework.blocktools import witness_script, send_to_witness
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from io import BytesIO
|
||||
from string import Template
|
||||
import decimal
|
||||
import re
|
||||
import json
|
||||
|
||||
class DecimalEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, decimal.Decimal):
|
||||
return float(o)
|
||||
return super(DecimalEncoder, self).default(o)
|
||||
|
||||
class KevaTest(BitcoinTestFramework):
|
||||
|
||||
def sync_generate(self, node, num):
|
||||
self.sync_all()
|
||||
node.generate(num)
|
||||
self.sync_all()
|
||||
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[1], 0)
|
||||
connect_nodes(self.nodes[2], 0)
|
||||
self.sync_all()
|
||||
|
||||
def dumpTx(self, tx):
|
||||
print(json.dumps(self.nodes[0].decoderawtransaction(self.nodes[0].getrawtransaction(tx)), indent=4, cls=DecimalEncoder))
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].generate(101)
|
||||
addr1 = self.nodes[1].getnewaddress()
|
||||
addr2 = self.nodes[2].getnewaddress()
|
||||
amount = Template('{"$addr1":1,"$addr2":1}').substitute(addr1=addr1, addr2=addr2)
|
||||
amountJson = json.loads(amount)
|
||||
self.nodes[0].sendmany("", amountJson)
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
ns1 = (self.nodes[1].keva_namespace('NS 1'))["namespaceId"]
|
||||
ns2 = (self.nodes[2].keva_namespace('NS 2'))["namespaceId"]
|
||||
self.sync_generate(self.nodes[0], 1)
|
||||
# Before nsfix is enabled, the namespace will be the same.
|
||||
# This is a historic bug.
|
||||
assert(ns1 == ns2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
KevaTest().main()
|
Loading…
Reference in New Issue
Block a user