Rebase LBRY on top of Bitcoin 0.17 #263

Closed
lbrynaut wants to merge 18 commits from updated-rebase-0.17-deps into bitcoin-0.17
18 changed files with 8926 additions and 158 deletions
Showing only changes of commit 6dd2df3a0c - Show all commits

View file

@ -0,0 +1,277 @@
#!/usr/bin/env python3
import re
import subprocess as sp
import sys
import json
import urllib.request as req
import jsonschema
re_full = re.compile(r'(?P<name>^.*?$)(?P<desc>.*?)(^Argument.*?$(?P<args>.*?))?(^Result[^\n,]*?:\s*$(?P<resl>.*?))?(^Exampl.*?$(?P<exmp>.*))?', re.DOTALL | re.MULTILINE)
re_argline = re.compile(r'^("?)(?P<name>\w.*?)\1(\s*:.+?,?\s*)?\s+\((?P<type>.*?)\)\s*(?P<desc>.*?)\s*$', re.DOTALL)
def get_obj_from_dirty_text(full_object: str):
lines = full_object.splitlines()
lefts = []
i = 0
while i < len(lines):
idx = lines[i].find('(')
left = lines[i][0:idx].strip() if idx >= 0 else lines[i]
left = left.rstrip('.') # handling , ...
left = left.strip()
left = left.rstrip(',')
lefts.append(left)
while idx >= 0 and i < len(lines) - 1:
idx2 = len(re.match(r'^\s*', lines[i + 1]).group())
if idx2 > idx:
lines[i] += lines.pop(i + 1)[idx2 - 1:]
else:
break
i += 1
ret = None
try:
property_stack = []
object_stack = []
name_stack = []
last_name = None
for i in range(0, len(lines)):
left = lefts[i]
if not left:
continue
line = lines[i].strip()
arg_parsed = re_argline.fullmatch(line)
property_refined_type = 'object'
if arg_parsed is not None:
property_name, property_type, property_desc = arg_parsed.group('name', 'type', 'desc')
property_refined_type, property_required, property_child = get_type(property_type, None)
if property_refined_type is not 'array' and property_refined_type is not 'object':
property_stack[-1][property_name] = {
'type': property_refined_type,
'description': property_desc
}
else:
last_name = property_name
elif len(left) > 1:
match = re.match(r'^(\[)?"(?P<name>\w.*?)"(\])?.*', left)
last_name = match.group('name')
if match.group(1) is not None and match.group(3) is not None:
left = '['
property_refined_type = 'string'
if 'string' not in line:
raise NotImplementedError('Not implemented: ' + line)
if left.endswith('['):
object_stack.append({'type': 'array', 'items': {'type': property_refined_type}})
property_stack.append({})
name_stack.append(last_name)
elif left.endswith('{'):
object_stack.append({'type': 'object'})
property_stack.append({})
name_stack.append(last_name)
elif (left.endswith(']') and '[' not in left) or (left.endswith('}') and '{' not in left):
obj = object_stack.pop()
prop = property_stack.pop()
name = name_stack.pop()
if len(prop) > 0:
if 'items' in obj:
obj['items']['properties'] = prop
else:
obj['properties'] = prop
if len(property_stack) > 0:
if 'items' in object_stack[-1]:
object_stack[-1]['items']['type'] = obj['type']
if len(prop) > 0:
object_stack[-1]['items']['properties'] = prop
else:
if name is None:
raise RuntimeError('Not expected')
property_stack[-1][name] = obj
else:
ret = obj
if ret is not None:
if i + 1 < len(lines) - 1:
print('Ignoring this data (below the parsed object): ' + "\n".join(lines[i+1:]), file=sys.stderr)
return ret
except Exception as e:
print('Exception: ' + str(e), file=sys.stderr)
print('Unable to cope with: ' + '\n'.join(lines), file=sys.stderr)
return None
def get_type(arg_type: str, full_line: str):
if arg_type is None:
return 'string', True, None
required = 'required' in arg_type or 'optional' not in arg_type
arg_type = arg_type.lower()
if 'array' in arg_type:
return 'array', required, None
if 'numeric' in arg_type:
return 'number', required, None
if 'bool' in arg_type:
return 'boolean', required, None
if 'string' in arg_type:
return 'string', required, None
if 'object' in arg_type:
properties = get_obj_from_dirty_text(full_line) if full_line is not None else None
return 'object', required, properties
print('Unable to derive type from: ' + arg_type, file=sys.stderr)
return None, False, None
def get_default(arg_refined_type: str, arg_type: str):
if 'default=' in arg_type:
if 'number' in arg_refined_type:
return int(re.match('.*default=([^,)]+)', arg_type).group(1))
if 'string' in arg_refined_type:
return re.match('.*default=([^,)]+)', arg_type).group(1)
if 'boolean' in arg_refined_type:
if 'default=true' in arg_type:
return True
if 'default=false' in arg_type:
return False
raise NotImplementedError('Not implemented: ' + arg_type)
if 'array' in arg_type:
raise NotImplementedError('Not implemented: ' + arg_type)
return None
def parse_single_argument(line: str):
if line:
line = line.strip()
if not line or line.startswith('None'):
return None, None, False
arg_parsed = re_argline.fullmatch(line)
if arg_parsed is None:
if line.startswith('{') or line.startswith('['):
return get_obj_from_dirty_text(line), None, True
else:
print("Unparsable argument: " + line, file=sys.stderr)
descriptor = {
'type': 'array' if line.startswith('[') else 'object',
'description': line,
}
return descriptor, None, True
arg_name, arg_type, arg_desc = arg_parsed.group('name', 'type', 'desc')
if not arg_type:
raise NotImplementedError('Not implemented: ' + arg_type)
arg_refined_type, arg_required, arg_properties = get_type(arg_type, arg_desc)
if arg_properties is not None:
return arg_properties, arg_name, arg_required
arg_refined_default = get_default(arg_refined_type, arg_type)
arg_desc = re.sub('\s+', ' ', arg_desc.strip()) \
if arg_desc and arg_refined_type is not 'object' and arg_refined_type is not 'array' \
else arg_desc.strip() if arg_desc else ''
descriptor = {
'type': arg_refined_type,
'description': arg_desc,
}
if arg_refined_default is not None:
descriptor['default'] = arg_refined_default
return descriptor, arg_name, arg_required
def parse_params(args: str):
arguments = {}
requireds = []
if args:
for line in re.split('\s*\d+\.\s+', args, re.DOTALL):
descriptor, name, required = parse_single_argument(line)
if descriptor is None:
continue
if required:
requireds.append(name)
arguments[name] = descriptor
return arguments, requireds
def get_api(section_name: str, command: str, command_help: str):
parsed = re_full.fullmatch(command_help)
if parsed is None:
raise RuntimeError('Unable to resolve help format for ' + command)
name, desc, args, resl, exmp = parsed.group('name', 'desc', 'args', 'resl', 'exmp')
properties, required = parse_params(args)
result_descriptor, result_name, result_required = parse_single_argument(resl)
desc = re.sub('\s+', ' ', desc.strip()) if desc else name
example_array = exmp.splitlines() if exmp else []
ret = {
'summary': desc,
'description': example_array,
'tags': [section_name],
'params': {
'type': 'object',
'properties': properties,
'required': required
},
}
if result_descriptor is not None:
ret['result'] = result_descriptor
return ret
def write_api():
if len(sys.argv) < 2:
print("Missing required argument: <path to CLI tool>", file=sys.stderr)
sys.exit(1)
cli_tool = sys.argv[1]
result = sp.run([cli_tool, "help"], stdout=sp.PIPE, universal_newlines=True)
commands = result.stdout
sections = re.split('^==\s*(.*?)\s*==$', commands, flags=re.MULTILINE)
methods = {}
for section in sections:
if not section:
continue
lines = section.splitlines()
if len(lines) == 1:
section_name = lines[0]
continue
for command in sorted(lines[1:]):
if not command:
continue
command = command.split(' ')[0]
result = sp.run([cli_tool, "help", command], stdout=sp.PIPE, universal_newlines=True)
methods[command] = get_api(section_name, command, result.stdout)
version = sp.run([cli_tool, "--version"], stdout=sp.PIPE, universal_newlines=True)
wrapper = {
'$schema': 'https://rawgit.com/mzernetsch/jrgen/master/jrgen-spec.schema.json',
'jrgen': '1.1',
'jsonrpc': '1.0', # see https://github.com/bitcoin/bitcoin/pull/12435
'info': {
'title': 'lbrycrd RPC API',
'version': version.stdout.strip(),
'description': []
},
'definitions': {}, # for items used in $ref further down
'methods': methods,
}
schema = req.urlopen(wrapper['$schema']).read().decode('utf-8')
try:
jsonschema.validate(wrapper, schema)
except Exception as e:
print('From schema validation: ' + str(e), file=sys.stderr)
print(json.dumps(wrapper, indent=4))
if __name__ == '__main__':
write_api()

View file

@ -0,0 +1,129 @@
#!/usr/bin/env python3
import re
import subprocess as sp
import sys
import json
re_full = re.compile(r'(?P<name>^.*?$)(?P<desc>.*?)(^Argument.*?$(?P<args>.*?))?(^Result[^\n]*?:\s*$(?P<resl>.*?))?(^Exampl.*?$(?P<exmp>.*))?', re.DOTALL | re.MULTILINE)
re_argline = re.compile(r'^("?)(?P<name>.*?)\1\s+\((?P<type>.*?)\)\s*(?P<desc>.*)$', re.DOTALL)
def get_type(arg_type, full_line):
if arg_type is None:
return 'string'
arg_type = arg_type.lower()
if 'numeric' in arg_type:
return 'number'
if 'bool' in arg_type:
return 'boolean'
if 'string' in arg_type:
return 'string'
if 'object' in arg_type:
return 'object'
raise Exception('Not implemented: ' + arg_type)
def parse_params(args):
arguments = []
if args:
for line in re.split('\s*\d+\.\s+', args, re.DOTALL):
if not line or not line.strip() or line.strip().startswith('None'):
continue
arg_parsed = re_argline.fullmatch(line)
if arg_parsed is None:
raise Exception("Unparsable argument: " + line)
arg_name, arg_type, arg_desc = arg_parsed.group('name', 'type', 'desc')
if not arg_type:
raise Exception('Not implemented: ' + arg_type)
arg_required = 'required' in arg_type or 'optional' not in arg_type
arg_refined_type = get_type(arg_type, line)
arg_desc = re.sub('\s+', ' ', arg_desc.strip()) if arg_desc else []
arguments.append({
'name': arg_name,
'type': arg_refined_type,
'description': arg_desc,
'is_required': arg_required
})
return arguments
def process_examples(examples: str):
if not examples:
return []
examples = examples.strip()
splits = examples.split('\n')
result = []
inner = {}
for s in splits:
if not s:
continue
if '> curl' in s:
inner['curl'] = s.strip()
elif '> lbrycrd' in s:
inner['cli'] = s.strip()
else:
if 'title' in inner:
result.append(inner)
inner = {}
inner['title'] = s.strip()
result.append(inner)
return result
def get_api(section_name, command, command_help):
parsed = re_full.fullmatch(command_help)
if parsed is None:
raise Exception('Unable to resolve help format for ' + command)
name, desc, args, resl, exmp = parsed.group('name', 'desc', 'args', 'resl', 'exmp')
arguments = parse_params(args)
cmd_desc = re.sub('\s+', ' ', desc.strip()) if desc else ''
examp_desc = process_examples(exmp)
cmd_resl = resl.strip() if resl else None
ret = {
'name': command,
'namespace': section_name,
'description': cmd_desc,
'arguments': arguments,
'examples': examp_desc
}
if cmd_resl is not None:
ret['returns'] = cmd_resl
return ret
def write_api():
if len(sys.argv) < 2:
print("Missing required argument: <path to CLI tool>", file=sys.stderr)
sys.exit(1)
cli_tool = sys.argv[1]
result = sp.run([cli_tool, "help"], stdout=sp.PIPE, universal_newlines=True)
commands = result.stdout
sections = re.split('^==\s*(.*?)\s*==$', commands, flags=re.MULTILINE)
apis = []
for section in sections:
if not section:
continue
lines = section.splitlines()
if len(lines) == 1:
section_name = lines[0]
continue
for command in sorted(lines[1:]):
if not command:
continue
command = command.split(' ')[0]
result = sp.run([cli_tool, "help", command], stdout=sp.PIPE, universal_newlines=True)
apis.append(get_api(section_name, command, result.stdout))
print(json.dumps(apis, indent=4))
if __name__ == '__main__':
write_api()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -247,8 +247,8 @@ public:
consensus.BIP34Height = 21111; consensus.BIP34Height = 21111;
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
// FIXME: adjust heights // FIXME: adjust heights
consensus.BIP65Height = 1000000; consensus.BIP65Height = 1200000;
consensus.BIP66Height = 1000000; consensus.BIP66Height = 1200000;
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 150; consensus.nPowTargetTimespan = 150;
consensus.nPowTargetSpacing = 150; consensus.nPowTargetSpacing = 150;

View file

@ -33,11 +33,11 @@ const CBaseChainParams& BaseParams()
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain) std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{ {
if (chain == CBaseChainParams::MAIN) if (chain == CBaseChainParams::MAIN)
return MakeUnique<CBaseChainParams>("", 9246); return MakeUnique<CBaseChainParams>("", 9245);
else if (chain == CBaseChainParams::TESTNET) else if (chain == CBaseChainParams::TESTNET)
return MakeUnique<CBaseChainParams>("testnet3", 19246); return MakeUnique<CBaseChainParams>("testnet3", 19245);
else if (chain == CBaseChainParams::REGTEST) else if (chain == CBaseChainParams::REGTEST)
return MakeUnique<CBaseChainParams>("regtest", 29246); return MakeUnique<CBaseChainParams>("regtest", 29245);
else else
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
} }

View file

@ -152,7 +152,7 @@ template<typename K> bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const
{ {
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator()); boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
pcursor->SeekToFirst(); pcursor->SeekToFirst();
while (pcursor->Valid()) while (pcursor->Valid())
{ {
std::pair<char, K> key; std::pair<char, K> key;
@ -412,7 +412,7 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
{ {
nodeMapType::const_iterator itchildren = current->children.find(*itname); nodeMapType::const_iterator itchildren = current->children.find(*itname);
if (itchildren == current->children.end()) if (itchildren == current->children.end())
return NULL; return nullptr;
current = itchildren->second; current = itchildren->second;
} }
return current; return current;
@ -692,7 +692,7 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std:
{ {
if (!updateName(itcache->first, itcache->second)) if (!updateName(itcache->first, itcache->second))
{ {
LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); LogPrintf("%s: Failed to update name for: %s\n", __func__, itcache->first);
return false; return false;
} }
} }
@ -700,7 +700,7 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std:
{ {
if (!updateHash(ithash->first, ithash->second)) if (!updateHash(ithash->first, ithash->second))
{ {
LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); LogPrintf("%s: Failed to update hash for: %s\n", __func__, ithash->first);
return false; return false;
} }
} }
@ -708,7 +708,7 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std:
{ {
if (!updateTakeoverHeight(itheight->first, itheight->second)) if (!updateTakeoverHeight(itheight->first, itheight->second))
{ {
LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); LogPrintf("%s: Failed to update takeover height for: %s\n", __func__, itheight->first);
return false; return false;
} }
} }
@ -775,7 +775,7 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode
current = itchild->second; current = itchild->second;
} }
} }
assert(current != NULL); assert(current != nullptr);
current->claims.swap(updatedNode->claims); current->claims.swap(updatedNode->claims);
markNodeDirty(name, current); markNodeDirty(name, current);
for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();)
@ -799,7 +799,7 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode
bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, const std::string& name) bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, const std::string& name)
{ {
assert(node != NULL); assert(node != nullptr);
for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild)
{ {
std::stringstream nextName; std::stringstream nextName;
@ -808,7 +808,7 @@ bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, const std::string& name)
return false; return false;
} }
node->children.clear(); node->children.clear();
markNodeDirty(name, NULL); markNodeDirty(name, nullptr);
delete node; delete node;
return true; return true;
} }
@ -823,7 +823,7 @@ bool CClaimTrie::updateHash(const std::string& name, uint256& hash)
return false; return false;
current = itchild->second; current = itchild->second;
} }
assert(current != NULL); assert(current != nullptr);
assert(!hash.IsNull()); assert(!hash.IsNull());
current->hash = hash; current->hash = hash;
markNodeDirty(name, current); markNodeDirty(name, current);
@ -840,7 +840,7 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig
return false; return false;
current = itchild->second; current = itchild->second;
} }
assert(current != NULL); assert(current != nullptr);
current->nHeightOfLastTakeover = nTakeoverHeight; current->nHeightOfLastTakeover = nTakeoverHeight;
markNodeDirty(name, current); markNodeDirty(name, current);
return true; return true;
@ -961,7 +961,7 @@ void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch)
bool CClaimTrie::WriteToDisk() bool CClaimTrie::WriteToDisk()
{ {
CDBBatch batch(*const_cast<CDBWrapper*>(&db)); CDBBatch batch(db);
for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache)
BatchWriteNode(batch, itcache->first, itcache->second); BatchWriteNode(batch, itcache->first, itcache->second);
dirtyNodes.clear(); dirtyNodes.clear();
@ -1011,7 +1011,7 @@ bool CClaimTrie::ReadFromDisk(bool check)
LogPrintf("%s: Couldn't read the current height\n", __func__); LogPrintf("%s: Couldn't read the current height\n", __func__);
setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1)); setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1));
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator()); boost::scoped_ptr<CDBIterator> pcursor(db.NewIterator());
pcursor->SeekToFirst(); pcursor->SeekToFirst();
while (pcursor->Valid()) while (pcursor->Valid())
@ -1131,6 +1131,7 @@ bool CClaimTrieCacheBase::empty() const
return base->empty() && cache.empty(); return base->empty() && cache.empty();
} }
// "position" has already been normalized if needed
CClaimTrieNode* CClaimTrieCacheBase::addNodeToCache(const std::string& position, CClaimTrieNode* original) const CClaimTrieNode* CClaimTrieCacheBase::addNodeToCache(const std::string& position, CClaimTrieNode* original) const
{ {
// create a copy of the node in the cache, if new node, create empty node // create a copy of the node in the cache, if new node, create empty node
@ -1155,13 +1156,12 @@ bool CClaimTrieCacheBase::getOriginalInfoForName(const std::string& name, CClaim
bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const
{ {
assert(base);
CClaimTrieNode* currentNode = getRoot(); CClaimTrieNode* currentNode = getRoot();
nodeCacheType::iterator cachedNode; nodeCacheType::iterator cachedNode;
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
{ {
std::string sCurrentSubstring(name.begin(), itCur); const std::string sCurrentSubstring(name.begin(), itCur);
std::string sNextSubstring(name.begin(), itCur + 1); const std::string sNextSubstring(name.begin(), itCur + 1);
cachedNode = cache.find(sNextSubstring); cachedNode = cache.find(sNextSubstring);
if (cachedNode != cache.end()) if (cachedNode != cache.end())
@ -1194,7 +1194,7 @@ bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimVal
{ {
currentNode = addNodeToCache(sCurrentSubstring, currentNode); currentNode = addNodeToCache(sCurrentSubstring, currentNode);
} }
CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, NULL); CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, nullptr);
currentNode->children[*itCur] = newNode; currentNode->children[*itCur] = newNode;
currentNode = newNode; currentNode = newNode;
} }
@ -1241,7 +1241,6 @@ bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimVal
bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const
{ {
assert(base);
CClaimTrieNode* currentNode = getRoot(); CClaimTrieNode* currentNode = getRoot();
nodeCacheType::iterator cachedNode; nodeCacheType::iterator cachedNode;
assert(currentNode != nullptr); // If there is no root in either the trie or the cache, how can there be any names to remove? assert(currentNode != nullptr); // If there is no root in either the trie or the cache, how can there be any names to remove?
@ -1272,7 +1271,7 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
else else
currentNode = addNodeToCache(name, currentNode); currentNode = addNodeToCache(name, currentNode);
assert(currentNode != NULL); assert(currentNode != nullptr);
if (currentNode->claims.empty()) if (currentNode->claims.empty())
{ {
LogPrintf("%s: Asked to remove claim from node without claims\n", __func__); LogPrintf("%s: Asked to remove claim from node without claims\n", __func__);
@ -1289,7 +1288,8 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
if (!success) if (!success)
{ {
LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n); LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d\n",
__func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n);
return false; return false;
} }
@ -1305,6 +1305,7 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
return recursivePruneName(getRoot(), 0, name); return recursivePruneName(getRoot(), 0, name);
} }
// sName has already been normalized if needed
bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified) const bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified) const
{ {
// Recursively prune leaf node(s) without any claims in it and store // Recursively prune leaf node(s) without any claims in it and store
@ -1316,7 +1317,7 @@ bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned
{ {
std::string sNextSubstring = sName.substr(0, nPos + 1); std::string sNextSubstring = sName.substr(0, nPos + 1);
unsigned char cNext = sName.at(nPos); unsigned char cNext = sName.at(nPos);
CClaimTrieNode* tnNext = NULL; CClaimTrieNode* tnNext = nullptr;
nodeCacheType::iterator cachedNode = cache.find(sNextSubstring); nodeCacheType::iterator cachedNode = cache.find(sNextSubstring);
if (cachedNode != cache.end()) if (cachedNode != cache.end())
tnNext = cachedNode->second; tnNext = cachedNode->second;
@ -1326,7 +1327,7 @@ bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned
if (childNode != tnCurrent->children.end()) if (childNode != tnCurrent->children.end())
tnNext = childNode->second; tnNext = childNode->second;
} }
if (tnNext == NULL) if (tnNext == nullptr)
return false; return false;
bool fChildNullified = false; bool fChildNullified = false;
if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified))
@ -1502,7 +1503,7 @@ bool CClaimTrieCacheBase::removeClaimFromQueue(const std::string& name, const CO
} }
if (itQueue != itQueueRow->second.end()) if (itQueue != itQueueRow->second.end())
{ {
std::swap(claim, itQueue->second); claim = itQueue->second;
itQueueNameRow->second.erase(itQueueName); itQueueNameRow->second.erase(itQueueName);
itQueueRow->second.erase(itQueue); itQueueRow->second.erase(itQueue);
return true; return true;
@ -1623,6 +1624,7 @@ bool CClaimTrieCacheBase::reorderTrieNode(const std::string& name, bool fCheckTa
// The node doesn't exist, so it can't be reordered. // The node doesn't exist, so it can't be reordered.
return true; return true;
} }
currentNode = new CClaimTrieNode(*currentNode); currentNode = new CClaimTrieNode(*currentNode);
std::pair<nodeCacheType::iterator, bool> ret; std::pair<nodeCacheType::iterator, bool> ret;
ret = cache.insert(std::pair<std::string, CClaimTrieNode*>(name, currentNode)); ret = cache.insert(std::pair<std::string, CClaimTrieNode*>(name, currentNode));
@ -1658,10 +1660,10 @@ bool CClaimTrieCacheBase::reorderTrieNode(const std::string& name, bool fCheckTa
return true; return true;
} }
// name has already been normalized if needed
bool CClaimTrieCacheBase::getSupportsForName(const std::string& name, supportMapEntryType& supports) const bool CClaimTrieCacheBase::getSupportsForName(const std::string& name, supportMapEntryType& supports) const
{ {
supportMapType::iterator cachedNode; const supportMapType::iterator cachedNode = supportCache.find(name);
cachedNode = supportCache.find(name);
if (cachedNode != supportCache.end()) if (cachedNode != supportCache.end())
{ {
supports = cachedNode->second; supports = cachedNode->second;
@ -1688,7 +1690,7 @@ bool CClaimTrieCacheBase::insertSupportIntoMap(const std::string& name, CSupport
} }
cachedNode->second.push_back(support); cachedNode->second.push_back(support);
// See if this changed the biggest bid // See if this changed the biggest bid
return reorderTrieNode(name, fCheckTakeover); return reorderTrieNode(name, fCheckTakeover);
} }
bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) const bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) const
@ -1932,8 +1934,6 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimQueueR
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) std::vector<std::pair<std::string, int> >& takeoverHeightUndo)
{ {
// we don't actually modify the claimTrie here; that happens in flush // we don't actually modify the claimTrie here; that happens in flush
LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight);
claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false);
if (itQueueRow != claimQueueCache.end()) if (itQueueRow != claimQueueCache.end())
{ {
@ -1987,6 +1987,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimQueueR
expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false); expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false);
if (itExpirationRow != expirationQueueCache.end()) if (itExpirationRow != expirationQueueCache.end())
{ {
// for every claim expiring right now
for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry)
{ {
CClaimValue claim; CClaimValue claim;
@ -2226,13 +2227,12 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) std::vector<std::pair<std::string, int> >& takeoverHeightUndo)
{ {
LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight);
nCurrentHeight--; nCurrentHeight--;
if (expireSupportUndo.begin() != expireSupportUndo.end()) if (expireSupportUndo.begin() != expireSupportUndo.end())
{ {
expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true);
for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) for (supportQueueRowType::reverse_iterator itSupportExpireUndo = expireSupportUndo.rbegin(); itSupportExpireUndo != expireSupportUndo.rend(); ++itSupportExpireUndo)
{ {
insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false);
if (nCurrentHeight == itSupportExpireUndo->second.nHeight + base->nExpirationTime) if (nCurrentHeight == itSupportExpireUndo->second.nHeight + base->nExpirationTime)
@ -2240,20 +2240,23 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
} }
} }
for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) for (insertUndoType::reverse_iterator itSupportUndo = insertSupportUndo.rbegin(); itSupportUndo != insertSupportUndo.rend(); ++itSupportUndo)
{ {
supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true);
CSupportValue support; CSupportValue support;
assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false));
// support.nValidHeight may have been changed if this was inserted before activation height if (itSupportUndo->nHeight >= 0)
// due to a triggered takeover, change it back to original nValidAtHeight {
support.nValidAtHeight = itSupportUndo->nHeight; // support.nValidHeight may have been changed if this was inserted before activation height
queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); // due to a triggered takeover, change it back to original nValidAtHeight
itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support)); support.nValidAtHeight = itSupportUndo->nHeight;
itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true);
queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true);
itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support));
itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight));
}
} }
if (expireUndo.begin() != expireUndo.end()) if (!expireUndo.empty())
{ {
expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true);
for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo)
@ -2265,20 +2268,27 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
} }
} }
for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) for (insertUndoType::reverse_iterator itInsertUndo = insertUndo.rbegin(); itInsertUndo != insertUndo.rend(); ++itInsertUndo)
{ {
claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true);
CClaimValue claim; CClaimValue claim;
assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false));
// claim.nValidHeight may have been changed if this was inserted before activation height if (itInsertUndo->nHeight >= 0) // aka it became valid at this height rather than being a rename/normalization
// due to a triggered takeover, change it back to original nValidAtHeight {
claim.nValidAtHeight = itInsertUndo->nHeight; // valid height may have been changed if this was inserted because the winning claim was abandoned; reset it here:
queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); claim.nValidAtHeight = itInsertUndo->nHeight;
itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true);
itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, claim.nValidAtHeight)); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim));
queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true);
itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, claim.nValidAtHeight));
}
else
{
// no present way to delete claim from the index by name (but we read after the deletion anyway)
claimsToDelete.insert(claim);
}
} }
for (std::vector<std::pair<std::string, int> >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) for (std::vector<std::pair<std::string, int> >::reverse_iterator itTakeoverHeightUndo = takeoverHeightUndo.rbegin(); itTakeoverHeightUndo != takeoverHeightUndo.rend(); ++itTakeoverHeightUndo)
{ {
cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second;
} }
@ -2295,7 +2305,7 @@ bool CClaimTrieCacheBase::finalizeDecrement() const
block_originals.clear(); block_originals.clear();
for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache)
{ {
block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); block_originals[itCache->first] = new CClaimTrieNode(*itCache->second);
} }
return true; return true;
} }
@ -2355,7 +2365,7 @@ int CClaimTrieCacheBase::getDelayForName(const std::string& name, const uint160&
uint256 CClaimTrieCacheBase::getBestBlock() uint256 CClaimTrieCacheBase::getBestBlock()
{ {
if (hashBlock.IsNull()) if (hashBlock.IsNull())
if (base != NULL) if (base != nullptr)
hashBlock = base->hashBlock; hashBlock = base->hashBlock;
return hashBlock; return hashBlock;
} }
@ -2534,7 +2544,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover);
} }
std::vector<std::pair<unsigned char, uint256> > children; std::vector<std::pair<unsigned char, uint256> > children;
CClaimTrieNode* nextCurrent = NULL; CClaimTrieNode* nextCurrent = nullptr;
for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren)
{ {
std::stringstream ss; std::stringstream ss;

View file

@ -142,8 +142,6 @@ typedef std::vector<CSupportValue> supportMapEntryType;
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType; typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
typedef std::pair<std::string, CClaimTrieNode> namedNodeType;
class CClaimTrieNode class CClaimTrieNode
{ {
public: public:
@ -323,9 +321,10 @@ struct claimsForNameType
int nLastTakeoverHeight; int nLastTakeoverHeight;
std::string name; std::string name;
claimsForNameType(const std::vector<CClaimValue>& claims, const std::vector<CSupportValue>& supports, claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports,
int nLastTakeoverHeight, const std::string& name) int nLastTakeoverHeight, const std::string& name)
: claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight), name(name) {} : claims(std::move(claims)), supports(std::move(supports)),
nLastTakeoverHeight(nLastTakeoverHeight), name(name) {}
claimsForNameType(const claimsForNameType&) = default; claimsForNameType(const claimsForNameType&) = default;
claimsForNameType(claimsForNameType&& other) claimsForNameType(claimsForNameType&& other)
@ -335,6 +334,7 @@ struct claimsForNameType
nLastTakeoverHeight = other.nLastTakeoverHeight; nLastTakeoverHeight = other.nLastTakeoverHeight;
name = std::move(other.name); name = std::move(other.name);
} }
claimsForNameType& operator=(const claimsForNameType&) = default; claimsForNameType& operator=(const claimsForNameType&) = default;
claimsForNameType& operator=(claimsForNameType&& other) claimsForNameType& operator=(claimsForNameType&& other)
{ {
@ -347,6 +347,8 @@ struct claimsForNameType
} }
return *this; return *this;
} }
virtual ~claimsForNameType() {}
}; };
class CClaimTrieCacheBase; class CClaimTrieCacheBase;
@ -356,7 +358,7 @@ class CClaimTrie
{ {
public: public:
CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32)
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false), nCurrentHeight(0), : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false), nCurrentHeight(0),
nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime),
nProportionalDelayFactor(nProportionalDelayFactor), nProportionalDelayFactor(nProportionalDelayFactor),
root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
@ -381,7 +383,6 @@ public:
bool supportEmpty() const; bool supportEmpty() const;
bool supportQueueEmpty() const; bool supportQueueEmpty() const;
bool expirationQueueEmpty() const; bool expirationQueueEmpty() const;
bool supportExpirationQueueEmpty() const;
void setExpirationTime(int t); void setExpirationTime(int t);
@ -409,7 +410,8 @@ public:
int nCurrentHeight; int nCurrentHeight;
int nExpirationTime; int nExpirationTime;
int nProportionalDelayFactor; int nProportionalDelayFactor;
private:
private:
void clear(CClaimTrieNode* current); void clear(CClaimTrieNode* current);
const CClaimTrieNode* getNodeForName(const std::string& name) const; const CClaimTrieNode* getNodeForName(const std::string& name) const;
@ -582,7 +584,7 @@ public:
CClaimTrieNode* getRoot() const CClaimTrieNode* getRoot() const
{ {
nodeCacheType::iterator iter = cache.find(""); const nodeCacheType::iterator iter = cache.find("");
return iter == cache.end() ? &(base->root) : iter->second; return iter == cache.end() ? &(base->root) : iter->second;
} }
@ -676,7 +678,6 @@ protected:
virtual int getDelayForName(const std::string& name, const uint160& claimId) const; virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
mutable nodeCacheType cache; mutable nodeCacheType cache;
CClaimTrie* base; CClaimTrie* base;
mutable int nCurrentHeight; // Height of the block that is being worked on, which is mutable int nCurrentHeight; // Height of the block that is being worked on, which is
// one greater than the height of the chain's tip // one greater than the height of the chain's tip
@ -750,7 +751,7 @@ private:
class CClaimTrieCacheExpirationFork: public CClaimTrieCacheBase { class CClaimTrieCacheExpirationFork: public CClaimTrieCacheBase {
public: public:
CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true) CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
: CClaimTrieCacheBase(base, fRequireTakeoverHeights) {} : CClaimTrieCacheBase(base, fRequireTakeoverHeights) {}
virtual ~CClaimTrieCacheExpirationFork() {} virtual ~CClaimTrieCacheExpirationFork() {}

View file

@ -205,6 +205,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
if (nCurrentHeight == Params().GetConsensus().nNormalizedNameForkHeight) { if (nCurrentHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
std::cout << "RUNNING NORMALIZATION NOW" << std::endl;
// run the one-time upgrade of all names that need to change // run the one-time upgrade of all names that need to change
// it modifies the (cache) trie as it goes, so we need to grab everything to be modified first // it modifies the (cache) trie as it goes, so we need to grab everything to be modified first
@ -297,4 +298,4 @@ bool CClaimTrieCacheNormalizationFork::addSupportToQueues(const std::string& nam
std::string CClaimTrieCacheNormalizationFork::adjustNameForValidHeight(const std::string& name, int validHeight) const { std::string CClaimTrieCacheNormalizationFork::adjustNameForValidHeight(const std::string& name, int validHeight) const {
return normalizeClaimName(name, validHeight > Params().GetConsensus().nNormalizedNameForkHeight); return normalizeClaimName(name, validHeight > Params().GetConsensus().nNormalizedNameForkHeight);
} }

View file

@ -79,8 +79,11 @@ struct Params {
int nNormalizedNameForkHeight; int nNormalizedNameForkHeight;
int64_t nPowTargetSpacing; int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan; int64_t nPowTargetTimespan;
/** how long it took claims to expire before the hard fork */
int64_t nOriginalClaimExpirationTime; int64_t nOriginalClaimExpirationTime;
/** how long it takes claims to expire after the hard fork */
int64_t nExtendedClaimExpirationTime; int64_t nExtendedClaimExpirationTime;
/** blocks before the hard fork that changed the expiration time */
int64_t nExtendedClaimExpirationForkHeight; int64_t nExtendedClaimExpirationForkHeight;
int64_t GetExpirationTime(int64_t nHeight) const { int64_t GetExpirationTime(int64_t nHeight) const {
return nHeight < nExtendedClaimExpirationForkHeight ? return nHeight < nExtendedClaimExpirationForkHeight ?

View file

@ -225,7 +225,7 @@ public:
~CDBWrapper(); ~CDBWrapper();
CDBWrapper(const CDBWrapper&) = delete; CDBWrapper(const CDBWrapper&) = delete;
CDBWrapper& operator=(const CDBWrapper&) = delete; /* CDBWrapper& operator=(const CDBWrapper&) = delete; */
template <typename K, typename V> template <typename K, typename V>
bool Read(const K& key, V& value) const bool Read(const K& key, V& value) const

View file

@ -437,7 +437,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
{ {
CCoinsViewCache view(pcoinsTip.get()); CCoinsViewCache view(pcoinsTip.get());
const Coin& coin = view.AccessCoin(txin.prevout); const Coin& coin = view.AccessCoin(txin.prevout);
int nTxinHeight = coin.nHeight;
CScript scriptPubKey; CScript scriptPubKey;
if (coin.out.IsNull()) { if (coin.out.IsNull()) {
auto it = std::find_if(txs.begin(), txs.end(), [&txin](const CTransactionRef& tx) { auto it = std::find_if(txs.begin(), txs.end(), [&txin](const CTransactionRef& tx) {
@ -470,7 +469,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
} }
std::string name(vvchParams[0].begin(), vvchParams[0].end()); std::string name(vvchParams[0].begin(), vvchParams[0].end());
int throwaway; int throwaway;
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coin.nHeight, throwaway))
{ {
std::pair<std::string, uint160> entry(name, claimId); std::pair<std::string, uint160> entry(name, claimId);
spentClaims.push_back(entry); spentClaims.push_back(entry);
@ -485,7 +484,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
assert(vvchParams.size() == 2); assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end()); std::string name(vvchParams[0].begin(), vvchParams[0].end());
int throwaway; int throwaway;
if (!trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) if (!trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), coin.nHeight, throwaway))
{ {
LogPrintf("%s(): The support was not found in the trie or queue\n", __func__); LogPrintf("%s(): The support was not found in the trie or queue\n", __func__);
} }
@ -518,7 +517,8 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
spentClaimsType::iterator itSpent; spentClaimsType::iterator itSpent;
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
{ {
if (itSpent->first == name && itSpent->second == claimId) if ((itSpent->first == name && itSpent->second == claimId) &&
(trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)))
break; break;
} }
if (itSpent != spentClaims.end()) if (itSpent != spentClaims.end())

View file

@ -18,7 +18,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
if (pindexLast == nullptr) if (pindexLast == nullptr)
return nProofOfWorkLimit; return nProofOfWorkLimit;
if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= 277299) if (params.fPowAllowMinDifficultyBlocks &&
pindexLast->nHeight >= params.nAllowMinDiffMinHeight &&
pindexLast->nHeight < params.nAllowMinDiffMaxHeight)
{ {
// Special difficulty rule for testnet: // Special difficulty rule for testnet:
// If the new block's timestamp is twice the target block time // If the new block's timestamp is twice the target block time
@ -29,12 +31,13 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){ if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){
return nProofOfWorkLimit; return nProofOfWorkLimit;
} }
// Special difficulty rule for LBRY testnet killed at block 1100000.
} }
// Go back the full period unless it's the first retarget after genesis. // Go back the full period unless it's the first retarget after genesis.
int blockstogoback = params.DifficultyAdjustmentInterval()-1; int blockstogoback = params.DifficultyAdjustmentInterval();
if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval()) blockstogoback = std::min(blockstogoback, pindexLast->nHeight);
blockstogoback = params.DifficultyAdjustmentInterval();
int nHeightFirst = pindexLast->nHeight - blockstogoback; int nHeightFirst = pindexLast->nHeight - blockstogoback;
assert(nHeightFirst >= 0); assert(nHeightFirst >= 0);

View file

@ -91,15 +91,16 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
"Result: \n" "Result: \n"
"[\n" "[\n"
" {\n" " {\n"
" \"name\" (string) the name claimed\n" " \"normalized_name\" (string) the name of these claims (after normalization)\n"
" \"claims\": [ (array of object) the claims for this name\n" " \"claims\": [ (array of object) the claims for this name\n"
" {\n" " {\n"
" \"claimId\" (string) the claimId of the claim\n" " \"claimId\" (string) the claimId of the claim\n"
" \"txid\" (string) the txid of the claim\n" " \"txid\" (string) the txid of the claim\n"
" \"n\" (numeric) the vout value of the claim\n" " \"n\" (numeric) the vout value of the claim\n"
" \"amount\" (numeric) txout amount\n" " \"amount\" (numeric) txout amount\n"
" \"height\" (numeric) the height of the block in which this transaction is located\n" " \"height\" (numeric) the height of the block in which this transaction is located\n"
" \"value\" (string) the value of this claim\n" " \"value\" (string) the value of this claim\n"
" \"name\" (string) the original name of this claim (before normalization)\n"
" }\n" " }\n"
" ]\n" " ]\n"
" }\n" " }\n"
@ -154,14 +155,18 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
{ {
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
} }
std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); claim.pushKV("value", HexStr(vvchParams[1].begin(), vvchParams[1].end()));
claim.pushKV("value", sValue);
} }
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(itClaims->claimId, targetName, targetClaim))
claim.push_back(Pair("name", targetName));
claims.push_back(claim); claims.push_back(claim);
} }
UniValue nodeObj(UniValue::VOBJ); UniValue nodeObj(UniValue::VOBJ);
nodeObj.pushKV("name", name); nodeObj.pushKV("normalized_name", name);
nodeObj.pushKV("claims", claims); nodeObj.pushKV("claims", claims);
nodes.push_back(nodeObj); nodes.push_back(nodeObj);
} }
@ -249,7 +254,7 @@ static UniValue getclaimtrie(const JSONRPCRequest& request)
return ret; return ret;
} }
static bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue) static bool getValueForOutPoint(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue)
{ {
const Coin& coin = coinsCache.AccessCoin(out); const Coin& coin = coinsCache.AccessCoin(out);
if (coin.IsSpent()) if (coin.IsSpent())
@ -267,13 +272,15 @@ static bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint&
} }
if (op == OP_CLAIM_NAME) if (op == OP_CLAIM_NAME)
{ {
sValue = std::string(vvchParams[1].begin(), vvchParams[1].end()); sValue = HexStr(vvchParams[1].begin(), vvchParams[1].end());
return true;
} }
else if (op == OP_UPDATE_CLAIM) else if (op == OP_UPDATE_CLAIM)
{ {
sValue = std::string(vvchParams[2].begin(), vvchParams[2].end()); sValue = HexStr(vvchParams[2].begin(), vvchParams[2].end());
return true;
} }
return true; return false;
} }
@ -282,7 +289,7 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 2) if (request.fHelp || request.params.size() > 2)
throw std::runtime_error( throw std::runtime_error(
"getvalueforname \"name\"\n" "getvalueforname \"name\"\n"
"Return the value associated with a name, if one exists\n" "Return the winning value associated with a name, if one exists\n"
"Arguments:\n" "Arguments:\n"
"1. \"name\" (string) the name to look up\n" "1. \"name\" (string) the name to look up\n"
"2. \"blockhash\" (string, optional) get the value\n" "2. \"blockhash\" (string, optional) get the value\n"
@ -299,7 +306,8 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
"\"n\" (numeric) vout value\n" "\"n\" (numeric) vout value\n"
"\"amount\" (numeric) txout amount\n" "\"amount\" (numeric) txout amount\n"
"\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n" "\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n"
"\"height\" (numeric) the height of the block in which this transaction is located\n"); "\"height\" (numeric) the height of the block in which this transaction is located\n"
"\"name\" (string) the original name of this claim (before normalization)\n");
LOCK(cs_main); LOCK(cs_main);
@ -319,7 +327,7 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
return ret; // they may have asked for a name that doesn't exist (which is not an error) return ret; // they may have asked for a name that doesn't exist (which is not an error)
std::string sValue; std::string sValue;
if (!getValueForClaim(coinsCache, claim.outPoint, sValue)) if (!getValueForOutPoint(coinsCache, claim.outPoint, sValue))
return ret; return ret;
const auto nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId); const auto nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId);
@ -331,13 +339,19 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
ret.pushKV("amount", claim.nAmount); ret.pushKV("amount", claim.nAmount);
ret.pushKV("effective amount", nEffectiveAmount); ret.pushKV("effective amount", nEffectiveAmount);
ret.pushKV("height", claim.nHeight); ret.pushKV("height", claim.nHeight);
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(claim.claimId, targetName, targetClaim))
ret.push_back(Pair("name", targetName));
return ret; return ret;
} }
typedef std::pair<CClaimValue, std::vector<CSupportValue> > claimAndSupportsType; typedef std::pair<CClaimValue, std::vector<CSupportValue> > claimAndSupportsType;
typedef std::map<uint160, claimAndSupportsType> claimSupportMapType; typedef std::map<uint160, claimAndSupportsType> claimSupportMapType;
UniValue supportToJSON(const CSupportValue& support) UniValue supportToJSON(const CCoinsViewCache& coinsCache, const CSupportValue& support)
{ {
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("txid", support.outPoint.hash.GetHex())); ret.push_back(Pair("txid", support.outPoint.hash.GetHex()));
@ -345,6 +359,9 @@ UniValue supportToJSON(const CSupportValue& support)
ret.push_back(Pair("nHeight", support.nHeight)); ret.push_back(Pair("nHeight", support.nHeight));
ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight)); ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight));
ret.push_back(Pair("nAmount", support.nAmount)); ret.push_back(Pair("nAmount", support.nAmount));
std::string value;
if (getValueForOutPoint(coinsCache, support.outPoint, value))
ret.push_back(Pair("value", value));
return ret; return ret;
} }
@ -355,7 +372,7 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffe
UniValue supportObjs(UniValue::VARR); UniValue supportObjs(UniValue::VARR);
for (const auto& support: supports) for (const auto& support: supports)
supportObjs.push_back(supportToJSON(support)); supportObjs.push_back(supportToJSON(coinsCache, support));
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
result.pushKV("claimId", itClaimsAndSupports->first.GetHex()); result.pushKV("claimId", itClaimsAndSupports->first.GetHex());
@ -365,10 +382,16 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffe
result.pushKV("nValidAtHeight", claim.nValidAtHeight); result.pushKV("nValidAtHeight", claim.nValidAtHeight);
result.pushKV("nAmount", claim.nAmount); result.pushKV("nAmount", claim.nAmount);
std::string sValue; std::string sValue;
if (getValueForClaim(coinsCache, claim.outPoint, sValue)) if (getValueForOutPoint(coinsCache, claim.outPoint, sValue))
result.pushKV("value", sValue); result.pushKV("value", sValue);
result.pushKV("nEffectiveAmount", nEffectiveAmount); result.pushKV("nEffectiveAmount", nEffectiveAmount);
result.pushKV("supports", supportObjs); result.pushKV("supports", supportObjs);
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(claim.claimId, targetName, targetClaim))
result.push_back(Pair("name", targetName));
return result; return result;
} }
@ -389,6 +412,7 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
"Result:\n" "Result:\n"
"{\n" "{\n"
" \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n" " \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n"
" \"normalized_name\" (string) the name of these claims after normalization\n"
" \"claims\": [ (array of object) claims for this name\n" " \"claims\": [ (array of object) claims for this name\n"
" {\n" " {\n"
" \"claimId\" (string) the claimId of this claim\n" " \"claimId\" (string) the claimId of this claim\n"
@ -397,7 +421,7 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
" \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n" " \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n"
" \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n" " \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the claim\n" " \"nAmount\" (numeric) the amount of the claim\n"
" \"value\" (string) the value of the name, if it exists\n" " \"value\" (string) the metadata of the claim\n"
" \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n" " \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n"
" \"supports\" : [ (array of object) supports for this claim\n" " \"supports\" : [ (array of object) supports for this claim\n"
" \"txid\" (string) the txid of the support\n" " \"txid\" (string) the txid of the support\n"
@ -405,6 +429,7 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
" \"nHeight\" (numeric) the height at which the support was included in the blockchain\n" " \"nHeight\" (numeric) the height at which the support was included in the blockchain\n"
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n" " \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the support\n" " \"nAmount\" (numeric) the amount of the support\n"
" \"value\" (string) the metadata of the support if any\n"
" ]\n" " ]\n"
" }\n" " }\n"
" ],\n" " ],\n"
@ -446,13 +471,14 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
{ {
claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId); claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId);
if (itClaimAndSupports == claimSupportMap.end()) if (itClaimAndSupports == claimSupportMap.end())
unmatchedSupports.push_back(supportToJSON(*itSupports)); unmatchedSupports.push_back(supportToJSON(coinsCache, *itSupports));
else else
itClaimAndSupports->second.second.push_back(*itSupports); itClaimAndSupports->second.second.push_back(*itSupports);
} }
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
result.pushKV("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight); result.pushKV("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight);
result.pushKV("normalized_name", claimsForName.name);
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports)
{ {
@ -476,8 +502,9 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
"1. \"claimId\" (string) the claimId of this claim\n" "1. \"claimId\" (string) the claimId of this claim\n"
"Result:\n" "Result:\n"
"{\n" "{\n"
" \"name\" (string) the name of the claim\n" " \"name\" (string) the original name of the claim (before normalization)\n"
" \"value\" (string) claim metadata\n" " \"normalized_name\" (string) the name of this claim (after normalization)\n"
" \"value\" (string) metadata of the claim\n"
" \"claimId\" (string) the claimId of this claim\n" " \"claimId\" (string) the claimId of this claim\n"
" \"txid\" (string) the hash of the transaction which has successfully claimed this name\n" " \"txid\" (string) the hash of the transaction which has successfully claimed this name\n"
" \"n\" (numeric) vout value\n" " \"n\" (numeric) vout value\n"
@ -490,6 +517,7 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
" \"height\" (numeric) the height at which the support was included in the blockchain\n" " \"height\" (numeric) the height at which the support was included in the blockchain\n"
" \"valid at height\" (numeric) the height at which the support is valid\n" " \"valid at height\" (numeric) the height at which the support is valid\n"
" \"amount\" (numeric) the amount of the support\n" " \"amount\" (numeric) the amount of the support\n"
" \"value\" (string) the metadata of the support if any\n"
" ]\n" " ]\n"
" \"height\" (numeric) the height of the block in which this claim transaction is located\n" " \"height\" (numeric) the height of the block in which this claim transaction is located\n"
" \"valid at height\" (numeric) the height at which the claim is valid\n" " \"valid at height\" (numeric) the height at which the claim is valid\n"
@ -509,8 +537,10 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
std::string sValue; std::string sValue;
claim.pushKV("name", name); claim.pushKV("name", name);
if (trieCache.shouldNormalize())
claim.push_back(Pair("normalized_name", trieCache.normalizeClaimName(name, true)));
CCoinsViewCache coinsCache(pcoinsTip.get()); CCoinsViewCache coinsCache(pcoinsTip.get());
if (getValueForClaim(coinsCache, claimValue.outPoint, sValue)) if (getValueForOutPoint(coinsCache, claimValue.outPoint, sValue))
claim.pushKV("value", sValue); claim.pushKV("value", sValue);
claim.pushKV("claimId", claimValue.claimId.GetHex()); claim.pushKV("claimId", claimValue.claimId.GetHex());
claim.pushKV("txid", claimValue.outPoint.hash.GetHex()); claim.pushKV("txid", claimValue.outPoint.hash.GetHex());
@ -525,6 +555,8 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
supportEntry.pushKV("height", support.nHeight); supportEntry.pushKV("height", support.nHeight);
supportEntry.pushKV("valid at height", support.nValidAtHeight); supportEntry.pushKV("valid at height", support.nValidAtHeight);
supportEntry.pushKV("amount", support.nAmount); supportEntry.pushKV("amount", support.nAmount);
if (getValueForOutPoint(coinsCache, support.outPoint, sValue))
claim.pushKV("value", sValue);
supportList.pushKVs(supportEntry); supportList.pushKVs(supportEntry);
} }
claim.pushKV("supports", supportList); claim.pushKV("supports", supportList);
@ -614,6 +646,7 @@ UniValue getclaimsfortx(const JSONRPCRequest& request)
" \"nOut\" (numeric) the index of the claim or support in the transaction's list of outputs\n" " \"nOut\" (numeric) the index of the claim or support in the transaction's list of outputs\n"
" \"claim type\" (string) 'claim' or 'support'\n" " \"claim type\" (string) 'claim' or 'support'\n"
" \"name\" (string) the name claimed or supported\n" " \"name\" (string) the name claimed or supported\n"
" \"claimId\" (string) if a claim, its ID\n"
" \"value\" (string) if a name claim, the value of the claim\n" " \"value\" (string) if a name claim, the value of the claim\n"
" \"supported txid\" (string) if a support, the txid of the supported claim\n" " \"supported txid\" (string) if a support, the txid of the supported claim\n"
" \"supported nout\" (numeric) if a support, the index of the supported claim in its transaction\n" " \"supported nout\" (numeric) if a support, the index of the supported claim in its transaction\n"
@ -653,22 +686,22 @@ UniValue getclaimsfortx(const JSONRPCRequest& request)
o.pushKV("name", sName); o.pushKV("name", sName);
if (op == OP_CLAIM_NAME) if (op == OP_CLAIM_NAME)
{ {
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
uint160 claimId = ClaimIdHash(hash, i); uint160 claimId = ClaimIdHash(hash, i);
o.pushKV("claimId", claimId.GetHex()); o.pushKV("claimId", claimId.GetHex());
o.pushKV("value", sValue); o.pushKV("value", HexStr(vvchParams[1].begin(), vvchParams[1].end()));
} }
else if (op == OP_UPDATE_CLAIM) else if (op == OP_UPDATE_CLAIM)
{ {
uint160 claimId(vvchParams[1]); uint160 claimId(vvchParams[1]);
std::string sValue(vvchParams[2].begin(), vvchParams[2].end());
o.pushKV("claimId", claimId.GetHex()); o.pushKV("claimId", claimId.GetHex());
o.pushKV("value", sValue); o.pushKV("value", HexStr(vvchParams[2].begin(), vvchParams[2].end()));
} }
else if (op == OP_SUPPORT_CLAIM) else if (op == OP_SUPPORT_CLAIM)
{ {
uint160 supportedClaimId(vvchParams[1]); uint160 supportedClaimId(vvchParams[1]);
o.pushKV("supported claimId", supportedClaimId.GetHex()); o.pushKV("supported claimId", supportedClaimId.GetHex());
if (vvchParams.size() > 2)
o.pushKV("supported value", HexStr(vvchParams[2].begin(), vvchParams[2].end()));
} }
if (nHeight > 0) if (nHeight > 0)
{ {
@ -850,6 +883,24 @@ UniValue getnameproof(const JSONRPCRequest& request)
return proofToJSON(proof); return proofToJSON(proof);
} }
UniValue checknormalization(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"checknormalization\n"
"Given an unnormalized name of a claim, return normalized version of it\n"
"Arguments:\n"
"1. \"name\" (string) the name to normalize\n"
"Result: \n"
"\"normalized\" (string) fully normalized name\n");
const bool force = true;
const std::string name = request.params[0].get_str();
CClaimTrieCache triecache(pclaimTrie);
return triecache.normalizeClaimName(name, force);
}
static const CRPCCommand commands[] = static const CRPCCommand commands[] =
{ // category name actor (function) argNames { // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ---------- // --------------------- ------------------------ ----------------------- ----------
@ -862,7 +913,8 @@ static const CRPCCommand commands[] =
{ "Claimtrie", "gettotalvalueofclaims", &gettotalvalueofclaims, { "controlling_only" } }, { "Claimtrie", "gettotalvalueofclaims", &gettotalvalueofclaims, { "controlling_only" } },
{ "Claimtrie", "getclaimsfortx", &getclaimsfortx, { "txid" } }, { "Claimtrie", "getclaimsfortx", &getclaimsfortx, { "txid" } },
{ "Claimtrie", "getnameproof", &getnameproof, { "name","blockhash"} }, { "Claimtrie", "getnameproof", &getnameproof, { "name","blockhash"} },
{ "Claimtrie", "getclaimbyid", &getclaimbyid, {"claimId"} }, { "Claimtrie", "getclaimbyid", &getclaimbyid, { "claimId" } },
{ "Claimtrie", "checknormalization", &checknormalization, { "name" }},
}; };
void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC) void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC)

View file

@ -19,6 +19,8 @@ enum isminetype
ISMINE_NO = 0, ISMINE_NO = 0,
ISMINE_WATCH_ONLY = 1, ISMINE_WATCH_ONLY = 1,
ISMINE_SPENDABLE = 2, ISMINE_SPENDABLE = 2,
ISMINE_CLAIM = 4,
ISMINE_SUPPORT = 8,
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
}; };
/** used for bitflags of isminetype */ /** used for bitflags of isminetype */

View file

@ -23,9 +23,10 @@
using namespace std; using namespace std;
BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup)
static ::CChainState g_chainstate;
static const boost::test_tools::predicate_result predicate_true(true); static const boost::test_tools::predicate_result predicate_true(true);
static const boost::test_tools::predicate_result predicate_false(false); static const boost::test_tools::predicate_result predicate_false(false);
@ -130,6 +131,7 @@ struct ClaimTrieChainFixture{
std::vector<int> marks; std::vector<int> marks;
int coinbase_txs_used; int coinbase_txs_used;
int unique_block_counter; int unique_block_counter;
int normalization_original;
unsigned int num_txs; unsigned int num_txs;
unsigned int num_txs_for_next_block; unsigned int num_txs_for_next_block;
@ -142,15 +144,16 @@ struct ClaimTrieChainFixture{
ClaimTrieChainFixture(): ClaimTrieChainFixture():
expirationForkHeight(Params().GetConsensus().nExtendedClaimExpirationForkHeight), expirationForkHeight(Params().GetConsensus().nExtendedClaimExpirationForkHeight),
originalExpiration(Params().GetConsensus().nOriginalClaimExpirationTime), originalExpiration(Params().GetConsensus().nOriginalClaimExpirationTime),
extendedExpiration(Params().GetConsensus().nExtendedClaimExpirationTime) extendedExpiration(Params().GetConsensus().nExtendedClaimExpirationTime),
unique_block_counter(0), normalization_original(-1)
{ {
fRequireStandard = false; fRequireStandard = false;
BOOST_CHECK_EQUAL(pclaimTrie->nCurrentHeight, chainActive.Height() + 1); BOOST_CHECK_EQUAL(pclaimTrie->nCurrentHeight, chainActive.Height() + 1);
pclaimTrie->setExpirationTime(originalExpiration); // in case it was changed during the test pclaimTrie->setExpirationTime(originalExpiration); // in case it was changed during the test
setNormalizationForkHeight(1000000); // Default should be dictated by Params()
num_txs_for_next_block = 0; num_txs_for_next_block = 0;
num_txs = 0; num_txs = 0;
coinbase_txs_used = 0; coinbase_txs_used = 0;
unique_block_counter = 0;
// generate coinbases to spend // generate coinbases to spend
CreateCoinbases(40, coinbase_txs); CreateCoinbases(40, coinbase_txs);
} }
@ -158,6 +161,21 @@ struct ClaimTrieChainFixture{
~ClaimTrieChainFixture() ~ClaimTrieChainFixture()
{ {
DecrementBlocks(chainActive.Height()); DecrementBlocks(chainActive.Height());
if (normalization_original >= 0)
{
const Consensus::Params& consensus = Params().GetConsensus();
const_cast<Consensus::Params&>(consensus).nNormalizedNameForkHeight = normalization_original;
}
pclaimTrie->setExpirationTime(originalExpiration); // in case it was changed during the test
}
void setNormalizationForkHeight(int targetMinusCurrent)
{
int target = chainActive.Height() + targetMinusCurrent;
const Consensus::Params& consensus = Params().GetConsensus();
if (normalization_original < 0)
normalization_original = consensus.nNormalizedNameForkHeight;
const_cast<Consensus::Params&>(consensus).nNormalizedNameForkHeight = target;
} }
bool CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate) bool CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate)
@ -216,8 +234,8 @@ struct ClaimTrieChainFixture{
} }
//spend a bid into some non claimtrie related unspent //spend a bid into some non claimtrie related unspent
CMutableTransaction Spend(const CTransaction &prev){ CMutableTransaction Spend(const CTransaction &prev)
{
uint32_t prevout = 0; uint32_t prevout = 0;
CMutableTransaction tx = BuildTransaction(prev, prevout); CMutableTransaction tx = BuildTransaction(prev, prevout);
tx.vout[0].scriptPubKey = CScript() << OP_TRUE; tx.vout[0].scriptPubKey = CScript() << OP_TRUE;
@ -231,7 +249,6 @@ struct ClaimTrieChainFixture{
CMutableTransaction MakeClaim(const CTransaction& prev, std::string name, std::string value, CAmount quantity) CMutableTransaction MakeClaim(const CTransaction& prev, std::string name, std::string value, CAmount quantity)
{ {
uint32_t prevout = 0; uint32_t prevout = 0;
CMutableTransaction tx = BuildTransaction(prev,prevout); CMutableTransaction tx = BuildTransaction(prev,prevout);
tx.vout[0].scriptPubKey = ClaimNameScript(name, value); tx.vout[0].scriptPubKey = ClaimNameScript(name, value);
tx.vout[0].nValue = quantity; tx.vout[0].nValue = quantity;
@ -275,9 +292,8 @@ struct ClaimTrieChainFixture{
CTransaction GetCoinbase() CTransaction GetCoinbase()
{ {
auto tx = coinbase_txs[coinbase_txs_used]; assert(coinbase_txs_used + 1 < coinbase_txs.size());
coinbase_txs_used++; return coinbase_txs[coinbase_txs_used++];
return tx;
} }
//create i blocks //create i blocks
@ -1087,6 +1103,504 @@ BOOST_AUTO_TEST_CASE(supports_fall_through)
BOOST_CHECK_EQUAL(is_best_claim("A", tx2), predicate_true); //tx2 support should be active now BOOST_CHECK_EQUAL(is_best_claim("A", tx2), predicate_true); //tx2 support should be active now
} }
/*
normalization
test normalization function indpendent from rest of the code
*/
BOOST_AUTO_TEST_CASE(normalization_only)
{
CClaimTrieCache ccache(pclaimTrie);
// basic ASCII casing tests
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TESt", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("tesT", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TesT", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("test", true));
BOOST_CHECK_EQUAL("test this", ccache.normalizeClaimName("Test This", true));
// test invalid utf8 bytes are returned as is
BOOST_CHECK_EQUAL("\xFF", ccache.normalizeClaimName("\xFF", true));
BOOST_CHECK_EQUAL("\xC3\x28", ccache.normalizeClaimName("\xC3\x28", true));
// ohm sign unicode code point \x2126 should be transformed to equivalent
// unicode code point \x03C9 , greek small letter omega
BOOST_CHECK_EQUAL("\xCF\x89", ccache.normalizeClaimName("\xE2\x84\xA6", true));
// cyrillic capital ef code point \x0424 should be transformed to lower case
// \x0444
BOOST_CHECK_EQUAL("\xD1\x84", ccache.normalizeClaimName("\xD0\xA4", true));
// armenian capital ben code point \x0532 should be transformed to lower case
// \x0562
BOOST_CHECK_EQUAL("\xD5\xA2", ccache.normalizeClaimName("\xD4\xB2", true));
// japanese pbu code point \x3076 should be transformed by NFD decomposition
// into \x3075 and \x3099
BOOST_CHECK_EQUAL("\xE3\x81\xB5\xE3\x82\x99",
ccache.normalizeClaimName("\xE3\x81\xB6", true));
// hangul ggwalg unicode code point \xAF51 should be transformed by NFD
// decomposition into unicode code points \x1101 \x116A \x11B0
// source: http://unicode.org/L2/L2009/09052-tr47.html
BOOST_CHECK_EQUAL("\xE1\x84\x81\xE1\x85\xAA\xE1\x86\xB0",
ccache.normalizeClaimName("\xEA\xBD\x91", true));
}
/*
normalization
check claim name normalization before the fork
check claim name normalization after the fork
*/
BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
{
ClaimTrieChainFixture fixture;
// check claim names are not normalized
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "normalizeTest", "one", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("normalizeTest", tx1), predicate_true);
fixture.DecrementBlocks(1);
BOOST_CHECK_EQUAL(pclaimTrie->getTotalNamesInTrie(), 0);
fixture.CommitTx(tx1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("normalizeTest", tx1), predicate_true);
CMutableTransaction tx2a = fixture.MakeClaim(fixture.GetCoinbase(), "Normalizetest", "one_a", 2);
CMutableTransaction tx2 = fixture.MakeUpdate(tx2a, "Normalizetest", "one", ClaimIdHash(tx2a.GetHash(), 0), 2);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("normalizeTest", tx1), predicate_true);
BOOST_CHECK_EQUAL(is_best_claim("Normalizetest", tx2), predicate_true);
fixture.setNormalizationForkHeight(2);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("normalizeTest", tx1), predicate_true);
BOOST_CHECK_EQUAL(is_best_claim("Normalizetest", tx2), predicate_true);
// Activate the fork (which rebuilds the existing claimtrie and
// cache), flattening all previously existing name clashes due to
// the normalization
fixture.IncrementBlocks(1, true);
// Post-fork, tx1 (the previous winning claim) assumes all name
// variants of what it originally was ...
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx1), predicate_true);
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("normalizetest", 3), predicate_true);
CClaimValue val;
BOOST_CHECK_EQUAL(pclaimTrie->getInfoForName("normalizeTest", val), false);
// Check equivalence of normalized claim names
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx1), predicate_true); // collapsed tx2
fixture.IncrementBlocks(1);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "NORMALIZETEST", "one", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx3), predicate_false);
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "NoRmAlIzEtEsT", 2);
fixture.IncrementBlocks(1);
// Ensure that supports work for normalized claim names
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx1), predicate_true); // effective amount is 5
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("normalizetest", 5), predicate_true);
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "foo", "bar", 1);
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "Foo", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("foo", tx4), predicate_true);
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("FOO", 2), predicate_true);
CMutableTransaction u1 = fixture.MakeUpdate(tx4, "foo", "baz", ClaimIdHash(tx4.GetHash(), 0), 1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("foo", u1), predicate_true);
CMutableTransaction u2 = fixture.MakeUpdate(tx1, "nOrmalIzEtEst", "two", ClaimIdHash(tx1.GetHash(), 0), 3);
fixture.IncrementBlocks(1);
CClaimValue tmpval;
pclaimTrie->getInfoForName("normalizetest", tmpval);
std::cout << "TX1 CLAIM: " << ClaimIdHash(tx1.GetHash(), 0) << std::endl;
std::cout << "TX3 CLAIM: " << ClaimIdHash(tx3.GetHash(), 0) << std::endl;
std::cout << "BEST CLAIM ID: " << HexStr(tmpval.claimId) << ", U2 CLAIM: " << ClaimIdHash(u2.GetHash(), 0) << std::endl;
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", u2), predicate_true);
// Add another set of unicode claims that will collapse after the fork
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "Ame\u0301lie", "amelie", 2);
fixture.IncrementBlocks(1);
CClaimValue nval1;
pclaimTrie->getInfoForName("amélie", nval1);
BOOST_CHECK_EQUAL(nval1.claimId, ClaimIdHash(tx5.GetHash(), 0));
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("amélie", 2), predicate_true);
// Check equivalence of normalized claim names
BOOST_CHECK_EQUAL(is_best_claim("amélie", tx5), predicate_true);
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "あてはまる", "jn1", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("あてはまる", tx7), predicate_true);
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "AÑEJO", "es1", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("añejo", tx8), predicate_true);
// Rewind to 1 block before the fork and be sure that the fork is no longer active
fixture.DecrementBlocks();
// Now check that our old (non-normalized) claims are 'alive' again
BOOST_CHECK_EQUAL(is_best_claim("normalizeTest", tx1), predicate_true);
BOOST_CHECK_EQUAL(is_best_claim("Normalizetest", tx1), predicate_false); // no longer equivalent
BOOST_CHECK_EQUAL(is_best_claim("Normalizetest", tx2), predicate_true);
// Create new claim
CMutableTransaction tx9 = fixture.MakeClaim(fixture.GetCoinbase(), "blah", "blah", 1);
std::string invalidUtf8("\xFF\xFF");
CMutableTransaction tx10 = fixture.MakeClaim(fixture.GetCoinbase(), invalidUtf8, "blah", 1); // invalid UTF8
// Roll forward to fork height again and check again that we're normalized
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(chainActive.Height(), Params().GetConsensus().nNormalizedNameForkHeight);
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx1), predicate_true); // collapsed tx2
BOOST_CHECK_EQUAL(is_best_claim(invalidUtf8, tx10), predicate_true);
// Rewind to 1 block before the fork and be sure that the fork is
// no longer active
fixture.DecrementBlocks(1);
BOOST_CHECK_EQUAL(is_best_claim("Normalizetest", tx2), predicate_true);
// Roll forward to fork height again and check again that we're normalized
fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(chainActive.Height(), Params().GetConsensus().nNormalizedNameForkHeight);
BOOST_CHECK_EQUAL(is_best_claim("normalizetest", tx1), predicate_true); // collapsed tx2
}
BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
{
ClaimTrieChainFixture fixture;
std::string name = "Ame\u0301lie";
std::string name_upper = "Amélie";
std::string name_normd = "amélie"; // this accented e is not actually the same as the one above; this has been "normalized"
BOOST_CHECK(name != name_upper);
// Add another set of unicode claims that will collapse after the fork
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "amilie", 2);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name_upper, "amelie", 2);
fixture.MakeClaim(fixture.GetCoinbase(), "amelie1", "amelie", 2);
fixture.IncrementBlocks(1);
CClaimValue lookupClaim;
std::string lookupName;
BOOST_CHECK(pclaimTrie->getClaimById(ClaimIdHash(tx2.GetHash(), 0), lookupName, lookupClaim));
CClaimValue nval1;
BOOST_CHECK(pclaimTrie->getInfoForName("amelie1", nval1));
// amélie is not found cause normalization still not appear
BOOST_CHECK(!pclaimTrie->getInfoForName(name_normd, nval1));
// Activate the fork (which rebuilds the existing claimtrie and
// cache), flattening all previously existing name clashes due to
// the normalization
fixture.setNormalizationForkHeight(1);
int currentHeight = chainActive.Height();
fixture.IncrementBlocks(1);
// Ok normalization fix the name problem
BOOST_CHECK(pclaimTrie->getInfoForName(name_normd, nval1));
BOOST_CHECK(nval1.nHeight == currentHeight);
BOOST_CHECK(lookupClaim == nval1);
CCoinsViewCache coins(pcoinsTip.get());
CClaimTrieCache trieCache(pclaimTrie);
CBlockIndex* pindex = chainActive.Tip();
CBlock block;
int amelieValidHeight;
BOOST_CHECK(trieCache.shouldNormalize());
BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus()));
BOOST_CHECK(g_chainstate.DisconnectBlock(block, pindex, coins, trieCache) == DisconnectResult::DISCONNECT_OK);
BOOST_CHECK(!trieCache.shouldNormalize());
BOOST_CHECK(!trieCache.spendClaim(name_normd, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
BOOST_CHECK(trieCache.spendClaim(name_upper, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
BOOST_CHECK(!pclaimTrie->getInfoForName(name, nval1));
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
insertUndoType insertUndo;
claimQueueRowType expireUndo;
insertUndoType insertSupportUndo;
supportQueueRowType expireSupportUndo;
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(trieCache.shouldNormalize());
// we cannot use getXXXForName cause the name will be normalized
struct CNameVerifierCallback : public CNodeCallback
{
const std::string& cmp;
CNameVerifierCallback(const std::string& cmp) : cmp(cmp) {}
void visit(const std::string& nodeName, const CClaimTrieNode* node)
{
BOOST_CHECK(nodeName != cmp);
}
};
CNameVerifierCallback callback(name);
trieCache.iterateTrie(callback);
}
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(5);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
fixture.IncrementBlocks(1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
fixture.IncrementBlocks(2);
BOOST_CHECK(is_best_claim("A", tx2));
fixture.IncrementBlocks(3, true);
BOOST_CHECK(is_best_claim("a", tx3));
fixture.DecrementBlocks();
BOOST_CHECK(is_best_claim("A", tx2));
}
BOOST_AUTO_TEST_CASE(normalized_activations_fall_through)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(5);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
fixture.IncrementBlocks(3);
BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 4);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "2", 3);
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "ab", "2", 2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("AB", tx1));
fixture.IncrementBlocks(3);
BOOST_CHECK(is_best_claim("ab", tx2));
BOOST_CHECK(pclaimTrie->getClaimsForName("ab").size() == 4U);
fixture.DecrementBlocks(3);
fixture.Spend(tx1);
fixture.Spend(tx2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("ab", tx3));
BOOST_CHECK(pclaimTrie->getClaimsForName("ab").size() == 2U);
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("AB", tx1));
fixture.Spend(tx1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("ab", tx2));
for (int i = 0; i < 7; i++)
{
fixture.IncrementBlocks(i, true); // well into normalized teritory
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "CD", "a", 1 + i);
fixture.IncrementBlocks(3);
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "Cd", "b", 2 + i);
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "cD", "c", 3 + i);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("cd", tx5));
fixture.Spend(tx5);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("cd", tx7));
fixture.DecrementBlocks();
}
}
BOOST_AUTO_TEST_CASE(normalization_removal_test)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
fixture.IncrementBlocks(3);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 2);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "3", 3);
CMutableTransaction sx1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "AB", 1);
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1);
CClaimTrieCache cache(pclaimTrie);
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, pclaimTrie->nCurrentHeight);
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, pclaimTrie->nCurrentHeight);
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, pclaimTrie->nCurrentHeight);
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), 1, ClaimIdHash(tx1.GetHash(), 0), pclaimTrie->nCurrentHeight);
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), 1, ClaimIdHash(tx2.GetHash(), 0), pclaimTrie->nCurrentHeight);
insertUndoType insertUndo;
claimQueueRowType expireUndo;
insertUndoType insertSupportUndo;
supportQueueRowType expireSupportUndo;
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
BOOST_CHECK(cache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(cache.getClaimsForName("ab").claims.size() == 3U);
BOOST_CHECK(cache.getClaimsForName("ab").supports.size() == 2U);
BOOST_CHECK(cache.decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(cache.undoAddSupport("AB", COutPoint(sx1.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddSupport("Ab", COutPoint(sx2.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("AB", COutPoint(tx1.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("Ab", COutPoint(tx2.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("aB", COutPoint(tx3.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.getClaimsForName("ab").claims.size() == 0U);
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_supports)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(3);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 3));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 4));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 5));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 4));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 3));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
fixture.IncrementBlocks(5);
BOOST_CHECK(best_claim_effective_amount_equals("a", 3));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_fail_on_spend)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
std::string sName1("testN");
std::string sName2("testn");
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "1", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim(sName1, tx1));
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "2", 2);
CMutableTransaction tx1s = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 2);
fixture.IncrementBlocks(2, true);
BOOST_CHECK(is_best_claim(sName2, tx1));
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
CMutableTransaction tx3s = fixture.Spend(tx1s);
fixture.IncrementBlocks(2);
BOOST_CHECK(is_best_claim(sName2, tx2));
fixture.DecrementBlocks();
BOOST_CHECK(is_best_claim(sName1, tx1));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_sort_order)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
fixture.IncrementBlocks(1);
BOOST_CHECK(!is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
BOOST_CHECK(pclaimTrie->getClaimsForName("a").size() == 3U);
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations)
{
ClaimTrieChainFixture fixture;
pclaimTrie->setExpirationTime(3);
fixture.setNormalizationForkHeight(4);
// need to see that claims expiring on the frame when we normalize aren't kept
// need to see that supports expiring on the frame when we normalize aren't kept
// need to see that claims & supports carried through the normalization fork do expire
// and that they come back correctly when we roll backwards
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "B", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx2, "B", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "C", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx3, "C", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
BOOST_CHECK(best_claim_effective_amount_equals("C", 2));
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "D", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx4, "D", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(2);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
BOOST_CHECK(best_claim_effective_amount_equals("C", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(3);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2)); // (not re-added)
}
/* /*
claim/support expiration for hard fork, but with checks for disk procedures claim/support expiration for hard fork, but with checks for disk procedures
*/ */
@ -1106,8 +1620,8 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
// Reset to disk, increment past the fork height and make sure we get // Reset to disk, increment past the fork height and make sure we get
// proper behavior // proper behavior
fixture.DecrementBlocks(2); fixture.DecrementBlocks(2);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 1);
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1,"test",1); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1);
@ -1117,10 +1631,10 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration);
BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_true); BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_true);
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test",2), predicate_true); BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test", 2), predicate_true);
fixture.IncrementBlocks(fixture.originalExpiration-1); fixture.IncrementBlocks(fixture.originalExpiration-1);
BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_true); BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_true);
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test",2), predicate_true); BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test", 2), predicate_true);
fixture.DecrementBlocks(fixture.originalExpiration-1); fixture.DecrementBlocks(fixture.originalExpiration-1);
fixture.IncrementBlocks(fixture.extendedExpiration-1); fixture.IncrementBlocks(fixture.extendedExpiration-1);
BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_false); BOOST_CHECK_EQUAL(is_best_claim("test", tx1), predicate_false);
@ -1129,15 +1643,15 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
// increment past the fork height and make sure we get proper behavior // increment past the fork height and make sure we get proper behavior
int height_of_update_before_expiration = 50; int height_of_update_before_expiration = 50;
fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration+2); fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration+2);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2", "one", 1);
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2,"test2",1); CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test2", 1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
fixture.WriteClearReadClaimTrie(); fixture.WriteClearReadClaimTrie();
CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test2","two",ClaimIdHash(tx2.GetHash(),0),1); CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1);
// increment to fork // increment to fork
fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height()); fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height());
BOOST_CHECK_EQUAL(is_best_claim("test2", u2), predicate_true); BOOST_CHECK_EQUAL(is_best_claim("test2", u2), predicate_true);
BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test2",2), predicate_true); BOOST_CHECK_EQUAL(best_claim_effective_amount_equals("test2", 2), predicate_true);
// increment to original expiration, should not be expired // increment to original expiration, should not be expired
fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration);
BOOST_CHECK_EQUAL(is_best_claim("test2", u2), predicate_true); BOOST_CHECK_EQUAL(is_best_claim("test2", u2), predicate_true);
@ -1167,9 +1681,10 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test)
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0);
CMutableTransaction tx1 = BuildTransaction(fixture.GetCoinbase()); CMutableTransaction tx1 = BuildTransaction(fixture.GetCoinbase());
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME tx1.vout[0].scriptPubKey = CScript()
<< std::vector<unsigned char>(sName1.begin(), sName1.end()) << OP_CLAIM_NAME
<< std::vector<unsigned char>(sValue1.begin(), sValue1.end()) << OP_2DROP << OP_DROP << OP_TRUE; << std::vector<unsigned char>(sName1.begin(), sName1.end())
<< std::vector<unsigned char>(sValue1.begin(), sValue1.end()) << OP_2DROP << OP_DROP << OP_TRUE;
uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0);
COutPoint tx1OutPoint(tx1.GetHash(), 0); COutPoint tx1OutPoint(tx1.GetHash(), 0);

View file

@ -122,19 +122,19 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->empty()); BOOST_CHECK(pclaimTrie->empty());
BOOST_CHECK(!ntState.empty()); BOOST_CHECK(!ntState.empty());
BOOST_CHECK(ntState.getMerkleHash() == hash1); BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash1);
ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
BOOST_CHECK(ntState.getMerkleHash() == hash1); BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash1);
ntState.insertClaimIntoTrie(std::string("tes"), CClaimValue(tx4OutPoint, hash160, 50, 100, 200)); ntState.insertClaimIntoTrie(std::string("tes"), CClaimValue(tx4OutPoint, hash160, 50, 100, 200));
BOOST_CHECK(ntState.getMerkleHash() == hash2); BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
ntState.insertClaimIntoTrie(std::string("testtesttesttest"), CClaimValue(tx5OutPoint, hash160, 50, 100, 200)); ntState.insertClaimIntoTrie(std::string("testtesttesttest"), CClaimValue(tx5OutPoint, hash160, 50, 100, 200));
ntState.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused); ntState.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused);
BOOST_CHECK(ntState.getMerkleHash() == hash2); BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
ntState.flush(); ntState.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState1(pclaimTrie); CClaimTrieCacheTest ntState1(pclaimTrie);
@ -143,52 +143,52 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
ntState1.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); ntState1.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused);
BOOST_CHECK(ntState1.getMerkleHash() == hash0); BOOST_CHECK_EQUAL(ntState1.getMerkleHash(), hash0);
CClaimTrieCacheTest ntState2(pclaimTrie); CClaimTrieCacheTest ntState2(pclaimTrie);
ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200)); ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200));
ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
BOOST_CHECK(ntState2.getMerkleHash() == hash3); BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
ntState2.flush(); ntState2.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash3);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState3(pclaimTrie); CClaimTrieCacheTest ntState3(pclaimTrie);
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200)); ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
BOOST_CHECK(ntState3.getMerkleHash() == hash4); BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
ntState3.flush(); ntState3.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash4);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState4(pclaimTrie); CClaimTrieCacheTest ntState4(pclaimTrie);
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused); ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused);
BOOST_CHECK(ntState4.getMerkleHash() == hash2); BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
ntState4.flush(); ntState4.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState5(pclaimTrie); CClaimTrieCacheTest ntState5(pclaimTrie);
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
BOOST_CHECK(ntState5.getMerkleHash() == hash2); BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
ntState5.flush(); ntState5.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState6(pclaimTrie); CClaimTrieCacheTest ntState6(pclaimTrie);
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
BOOST_CHECK(ntState6.getMerkleHash() == hash2); BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
ntState6.flush(); ntState6.flush();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCacheTest ntState7(pclaimTrie); CClaimTrieCacheTest ntState7(pclaimTrie);
@ -197,17 +197,17 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused);
ntState7.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused); ntState7.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused);
BOOST_CHECK(ntState7.getMerkleHash() == hash0); BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
ntState7.flush(); ntState7.flush();
BOOST_CHECK(pclaimTrie->empty()); BOOST_CHECK(pclaimTrie->empty());
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
} }
BOOST_AUTO_TEST_CASE(basic_insertion_info_test) BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
{ {
// test basic claim insertions and that get methods retreives information properly // test basic claim insertions and that get methods retreives information properly
BOOST_CHECK(pclaimTrie->empty()); BOOST_CHECK_EQUAL(pclaimTrie->empty(), true);
CClaimTrieCacheTest ctc(pclaimTrie); CClaimTrieCacheTest ctc(pclaimTrie);
// create and insert claim // create and insert claim
@ -223,14 +223,14 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
// try getClaimsForName, getEffectiveAmountForClaim, getInfoForName // try getClaimsForName, getEffectiveAmountForClaim, getInfoForName
claimsForNameType res = ctc.getClaimsForName("test"); claimsForNameType res = ctc.getClaimsForName("test");
BOOST_CHECK(res.claims.size() == 1); BOOST_CHECK_EQUAL(res.claims.size(), 1);
BOOST_CHECK(res.claims[0] == claimVal); BOOST_CHECK_EQUAL(res.claims[0], claimVal);
BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId)); BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId));
CClaimValue claim; CClaimValue claim;
BOOST_CHECK(ctc.getInfoForName("test", claim)); BOOST_CHECK_EQUAL(ctc.getInfoForName("test", claim), true);
BOOST_CHECK(claim == claimVal); BOOST_CHECK_EQUAL(claim, claimVal);
// insert a support // insert a support
CAmount supportAmount(10); CAmount supportAmount(10);
@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test)
BOOST_AUTO_TEST_CASE(iteratetrie_test) BOOST_AUTO_TEST_CASE(iteratetrie_test)
{ {
BOOST_CHECK(pclaimTrie->empty()); BOOST_CHECK_EQUAL(pclaimTrie->empty(), true);
CClaimTrieCacheTest ctc(pclaimTrie); CClaimTrieCacheTest ctc(pclaimTrie);
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@ -297,7 +297,8 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
int count = 0; int count = 0;
struct TestCallBack : public CNodeCallback { struct TestCallBack : public CNodeCallback
{
TestCallBack(int& count) : count(count) TestCallBack(int& count) : count(count)
{ {
} }
@ -305,20 +306,20 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
void visit(const std::string& name, const CClaimTrieNode* node) void visit(const std::string& name, const CClaimTrieNode* node)
{ {
count++; count++;
if (name == "test") { if (name == "test")
BOOST_CHECK_EQUAL(node->claims.size(), 1); BOOST_CHECK_EQUAL(node->claims.size(), 1);
}
} }
int& count; int& count;
} testCallback(count); } testCallback(count);
BOOST_CHECK(ctc.iterateTrie(testCallback)); BOOST_CHECK_EQUAL(ctc.iterateTrie(testCallback), true);
BOOST_CHECK_EQUAL(count, 5); BOOST_CHECK_EQUAL(count, 5);
count = 3; count = 3;
struct TestCallBack2 : public CNodeCallback { struct TestCallBack2 : public CNodeCallback
{
TestCallBack2(int& count) : count(count) TestCallBack2(int& count) : count(count)
{ {
} }
@ -332,7 +333,7 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
int& count; int& count;
} testCallback2(count); } testCallback2(count);
BOOST_CHECK(!ctc.iterateTrie(testCallback2)); BOOST_CHECK_EQUAL(ctc.iterateTrie(testCallback2), false);
BOOST_CHECK_EQUAL(count, 0); BOOST_CHECK_EQUAL(count, 0);
} }

View file

@ -2187,7 +2187,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
spentClaimsType::iterator itSpent; spentClaimsType::iterator itSpent;
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
{ {
if (itSpent->first == name && itSpent->second == claimId) if ((itSpent->first == name && itSpent->second == claimId) &&
(trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)))
break; break;
} }
if (itSpent != spentClaims.end()) if (itSpent != spentClaims.end())