Rebase LBRY on top of Bitcoin 0.17 #263
18 changed files with 8926 additions and 158 deletions
277
contrib/devtools/generate_json_api_jrgen.py
Executable file
277
contrib/devtools/generate_json_api_jrgen.py
Executable 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()
|
129
contrib/devtools/generate_json_api_v1.py
Executable file
129
contrib/devtools/generate_json_api_v1.py
Executable 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()
|
5118
contrib/devtools/generated/api_jrgen.json
Normal file
5118
contrib/devtools/generated/api_jrgen.json
Normal file
File diff suppressed because it is too large
Load diff
2655
contrib/devtools/generated/api_v1.json
Normal file
2655
contrib/devtools/generated/api_v1.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -247,8 +247,8 @@ public:
|
|||
consensus.BIP34Height = 21111;
|
||||
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
|
||||
// FIXME: adjust heights
|
||||
consensus.BIP65Height = 1000000;
|
||||
consensus.BIP66Height = 1000000;
|
||||
consensus.BIP65Height = 1200000;
|
||||
consensus.BIP66Height = 1200000;
|
||||
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 150;
|
||||
consensus.nPowTargetSpacing = 150;
|
||||
|
|
|
@ -33,11 +33,11 @@ const CBaseChainParams& BaseParams()
|
|||
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
|
||||
{
|
||||
if (chain == CBaseChainParams::MAIN)
|
||||
return MakeUnique<CBaseChainParams>("", 9246);
|
||||
return MakeUnique<CBaseChainParams>("", 9245);
|
||||
else if (chain == CBaseChainParams::TESTNET)
|
||||
return MakeUnique<CBaseChainParams>("testnet3", 19246);
|
||||
return MakeUnique<CBaseChainParams>("testnet3", 19245);
|
||||
else if (chain == CBaseChainParams::REGTEST)
|
||||
return MakeUnique<CBaseChainParams>("regtest", 29246);
|
||||
return MakeUnique<CBaseChainParams>("regtest", 29245);
|
||||
else
|
||||
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
|
||||
}
|
||||
|
|
|
@ -412,7 +412,7 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
|
|||
{
|
||||
nodeMapType::const_iterator itchildren = current->children.find(*itname);
|
||||
if (itchildren == current->children.end())
|
||||
return NULL;
|
||||
return nullptr;
|
||||
current = itchildren->second;
|
||||
}
|
||||
return current;
|
||||
|
@ -775,7 +775,7 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode
|
|||
current = itchild->second;
|
||||
}
|
||||
}
|
||||
assert(current != NULL);
|
||||
assert(current != nullptr);
|
||||
current->claims.swap(updatedNode->claims);
|
||||
markNodeDirty(name, current);
|
||||
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)
|
||||
{
|
||||
assert(node != NULL);
|
||||
assert(node != nullptr);
|
||||
for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild)
|
||||
{
|
||||
std::stringstream nextName;
|
||||
|
@ -808,7 +808,7 @@ bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, const std::string& name)
|
|||
return false;
|
||||
}
|
||||
node->children.clear();
|
||||
markNodeDirty(name, NULL);
|
||||
markNodeDirty(name, nullptr);
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
|
@ -823,7 +823,7 @@ bool CClaimTrie::updateHash(const std::string& name, uint256& hash)
|
|||
return false;
|
||||
current = itchild->second;
|
||||
}
|
||||
assert(current != NULL);
|
||||
assert(current != nullptr);
|
||||
assert(!hash.IsNull());
|
||||
current->hash = hash;
|
||||
markNodeDirty(name, current);
|
||||
|
@ -840,7 +840,7 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig
|
|||
return false;
|
||||
current = itchild->second;
|
||||
}
|
||||
assert(current != NULL);
|
||||
assert(current != nullptr);
|
||||
current->nHeightOfLastTakeover = nTakeoverHeight;
|
||||
markNodeDirty(name, current);
|
||||
return true;
|
||||
|
@ -961,7 +961,7 @@ void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch)
|
|||
|
||||
bool CClaimTrie::WriteToDisk()
|
||||
{
|
||||
CDBBatch batch(*const_cast<CDBWrapper*>(&db));
|
||||
CDBBatch batch(db);
|
||||
for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache)
|
||||
BatchWriteNode(batch, itcache->first, itcache->second);
|
||||
dirtyNodes.clear();
|
||||
|
@ -1011,7 +1011,7 @@ bool CClaimTrie::ReadFromDisk(bool check)
|
|||
LogPrintf("%s: Couldn't read the current height\n", __func__);
|
||||
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();
|
||||
while (pcursor->Valid())
|
||||
|
@ -1131,6 +1131,7 @@ bool CClaimTrieCacheBase::empty() const
|
|||
return base->empty() && cache.empty();
|
||||
}
|
||||
|
||||
// "position" has already been normalized if needed
|
||||
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
|
||||
|
@ -1155,13 +1156,12 @@ bool CClaimTrieCacheBase::getOriginalInfoForName(const std::string& name, CClaim
|
|||
|
||||
bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const
|
||||
{
|
||||
assert(base);
|
||||
CClaimTrieNode* currentNode = getRoot();
|
||||
nodeCacheType::iterator cachedNode;
|
||||
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
|
||||
{
|
||||
std::string sCurrentSubstring(name.begin(), itCur);
|
||||
std::string sNextSubstring(name.begin(), itCur + 1);
|
||||
const std::string sCurrentSubstring(name.begin(), itCur);
|
||||
const std::string sNextSubstring(name.begin(), itCur + 1);
|
||||
|
||||
cachedNode = cache.find(sNextSubstring);
|
||||
if (cachedNode != cache.end())
|
||||
|
@ -1194,7 +1194,7 @@ bool CClaimTrieCacheBase::insertClaimIntoTrie(const std::string& name, CClaimVal
|
|||
{
|
||||
currentNode = addNodeToCache(sCurrentSubstring, currentNode);
|
||||
}
|
||||
CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, NULL);
|
||||
CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, nullptr);
|
||||
currentNode->children[*itCur] = 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
|
||||
{
|
||||
assert(base);
|
||||
CClaimTrieNode* currentNode = getRoot();
|
||||
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?
|
||||
|
@ -1272,7 +1271,7 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
|
|||
else
|
||||
currentNode = addNodeToCache(name, currentNode);
|
||||
|
||||
assert(currentNode != NULL);
|
||||
assert(currentNode != nullptr);
|
||||
if (currentNode->claims.empty())
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1305,6 +1305,7 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
|
|||
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
|
||||
{
|
||||
// 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);
|
||||
unsigned char cNext = sName.at(nPos);
|
||||
CClaimTrieNode* tnNext = NULL;
|
||||
CClaimTrieNode* tnNext = nullptr;
|
||||
nodeCacheType::iterator cachedNode = cache.find(sNextSubstring);
|
||||
if (cachedNode != cache.end())
|
||||
tnNext = cachedNode->second;
|
||||
|
@ -1326,7 +1327,7 @@ bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned
|
|||
if (childNode != tnCurrent->children.end())
|
||||
tnNext = childNode->second;
|
||||
}
|
||||
if (tnNext == NULL)
|
||||
if (tnNext == nullptr)
|
||||
return false;
|
||||
bool fChildNullified = false;
|
||||
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())
|
||||
{
|
||||
std::swap(claim, itQueue->second);
|
||||
claim = itQueue->second;
|
||||
itQueueNameRow->second.erase(itQueueName);
|
||||
itQueueRow->second.erase(itQueue);
|
||||
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.
|
||||
return true;
|
||||
}
|
||||
|
||||
currentNode = new CClaimTrieNode(*currentNode);
|
||||
std::pair<nodeCacheType::iterator, bool> ret;
|
||||
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;
|
||||
}
|
||||
|
||||
// name has already been normalized if needed
|
||||
bool CClaimTrieCacheBase::getSupportsForName(const std::string& name, supportMapEntryType& supports) const
|
||||
{
|
||||
supportMapType::iterator cachedNode;
|
||||
cachedNode = supportCache.find(name);
|
||||
const supportMapType::iterator cachedNode = supportCache.find(name);
|
||||
if (cachedNode != supportCache.end())
|
||||
{
|
||||
supports = cachedNode->second;
|
||||
|
@ -1932,8 +1934,6 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimQueueR
|
|||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo)
|
||||
{
|
||||
// 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);
|
||||
if (itQueueRow != claimQueueCache.end())
|
||||
{
|
||||
|
@ -1987,6 +1987,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimQueueR
|
|||
expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false);
|
||||
if (itExpirationRow != expirationQueueCache.end())
|
||||
{
|
||||
// for every claim expiring right now
|
||||
for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry)
|
||||
{
|
||||
CClaimValue claim;
|
||||
|
@ -2226,13 +2227,12 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
|
|||
insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo)
|
||||
{
|
||||
LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight);
|
||||
nCurrentHeight--;
|
||||
|
||||
if (expireSupportUndo.begin() != expireSupportUndo.end())
|
||||
{
|
||||
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);
|
||||
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;
|
||||
assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false));
|
||||
if (itSupportUndo->nHeight >= 0)
|
||||
{
|
||||
// support.nValidHeight may have been changed if this was inserted before activation height
|
||||
// due to a triggered takeover, change it back to original nValidAtHeight
|
||||
support.nValidAtHeight = itSupportUndo->nHeight;
|
||||
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);
|
||||
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;
|
||||
assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false));
|
||||
// claim.nValidHeight may have been changed if this was inserted before activation height
|
||||
// due to a triggered takeover, change it back to original nValidAtHeight
|
||||
if (itInsertUndo->nHeight >= 0) // aka it became valid at this height rather than being a rename/normalization
|
||||
{
|
||||
// valid height may have been changed if this was inserted because the winning claim was abandoned; reset it here:
|
||||
claim.nValidAtHeight = itInsertUndo->nHeight;
|
||||
queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true);
|
||||
claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true);
|
||||
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;
|
||||
}
|
||||
|
@ -2295,7 +2305,7 @@ bool CClaimTrieCacheBase::finalizeDecrement() const
|
|||
block_originals.clear();
|
||||
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;
|
||||
}
|
||||
|
@ -2355,7 +2365,7 @@ int CClaimTrieCacheBase::getDelayForName(const std::string& name, const uint160&
|
|||
uint256 CClaimTrieCacheBase::getBestBlock()
|
||||
{
|
||||
if (hashBlock.IsNull())
|
||||
if (base != NULL)
|
||||
if (base != nullptr)
|
||||
hashBlock = base->hashBlock;
|
||||
return hashBlock;
|
||||
}
|
||||
|
@ -2534,7 +2544,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
|||
valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover);
|
||||
}
|
||||
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)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -142,8 +142,6 @@ typedef std::vector<CSupportValue> supportMapEntryType;
|
|||
|
||||
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
|
||||
|
||||
typedef std::pair<std::string, CClaimTrieNode> namedNodeType;
|
||||
|
||||
class CClaimTrieNode
|
||||
{
|
||||
public:
|
||||
|
@ -323,9 +321,10 @@ struct claimsForNameType
|
|||
int nLastTakeoverHeight;
|
||||
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)
|
||||
: 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(claimsForNameType&& other)
|
||||
|
@ -335,6 +334,7 @@ struct claimsForNameType
|
|||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
name = std::move(other.name);
|
||||
}
|
||||
|
||||
claimsForNameType& operator=(const claimsForNameType&) = default;
|
||||
claimsForNameType& operator=(claimsForNameType&& other)
|
||||
{
|
||||
|
@ -347,6 +347,8 @@ struct claimsForNameType
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~claimsForNameType() {}
|
||||
};
|
||||
|
||||
class CClaimTrieCacheBase;
|
||||
|
@ -381,7 +383,6 @@ public:
|
|||
bool supportEmpty() const;
|
||||
bool supportQueueEmpty() const;
|
||||
bool expirationQueueEmpty() const;
|
||||
bool supportExpirationQueueEmpty() const;
|
||||
|
||||
void setExpirationTime(int t);
|
||||
|
||||
|
@ -409,6 +410,7 @@ public:
|
|||
int nCurrentHeight;
|
||||
int nExpirationTime;
|
||||
int nProportionalDelayFactor;
|
||||
|
||||
private:
|
||||
void clear(CClaimTrieNode* current);
|
||||
|
||||
|
@ -582,7 +584,7 @@ public:
|
|||
|
||||
CClaimTrieNode* getRoot() const
|
||||
{
|
||||
nodeCacheType::iterator iter = cache.find("");
|
||||
const nodeCacheType::iterator iter = cache.find("");
|
||||
return iter == cache.end() ? &(base->root) : iter->second;
|
||||
}
|
||||
|
||||
|
@ -676,7 +678,6 @@ protected:
|
|||
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
|
||||
|
||||
mutable nodeCacheType cache;
|
||||
|
||||
CClaimTrie* base;
|
||||
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
|
||||
// one greater than the height of the chain's tip
|
||||
|
|
|
@ -205,6 +205,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
|
|||
|
||||
if (nCurrentHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
|
||||
|
||||
std::cout << "RUNNING NORMALIZATION NOW" << std::endl;
|
||||
// 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
|
||||
|
||||
|
|
|
@ -79,8 +79,11 @@ struct Params {
|
|||
int nNormalizedNameForkHeight;
|
||||
int64_t nPowTargetSpacing;
|
||||
int64_t nPowTargetTimespan;
|
||||
/** how long it took claims to expire before the hard fork */
|
||||
int64_t nOriginalClaimExpirationTime;
|
||||
/** how long it takes claims to expire after the hard fork */
|
||||
int64_t nExtendedClaimExpirationTime;
|
||||
/** blocks before the hard fork that changed the expiration time */
|
||||
int64_t nExtendedClaimExpirationForkHeight;
|
||||
int64_t GetExpirationTime(int64_t nHeight) const {
|
||||
return nHeight < nExtendedClaimExpirationForkHeight ?
|
||||
|
|
|
@ -225,7 +225,7 @@ public:
|
|||
~CDBWrapper();
|
||||
|
||||
CDBWrapper(const CDBWrapper&) = delete;
|
||||
CDBWrapper& operator=(const CDBWrapper&) = delete;
|
||||
/* CDBWrapper& operator=(const CDBWrapper&) = delete; */
|
||||
|
||||
template <typename K, typename V>
|
||||
bool Read(const K& key, V& value) const
|
||||
|
|
|
@ -437,7 +437,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
{
|
||||
CCoinsViewCache view(pcoinsTip.get());
|
||||
const Coin& coin = view.AccessCoin(txin.prevout);
|
||||
int nTxinHeight = coin.nHeight;
|
||||
CScript scriptPubKey;
|
||||
if (coin.out.IsNull()) {
|
||||
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());
|
||||
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);
|
||||
spentClaims.push_back(entry);
|
||||
|
@ -485,7 +484,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
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__);
|
||||
}
|
||||
|
@ -518,7 +517,8 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
spentClaimsType::iterator 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;
|
||||
}
|
||||
if (itSpent != spentClaims.end())
|
||||
|
|
11
src/pow.cpp
11
src/pow.cpp
|
@ -18,7 +18,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||
if (pindexLast == nullptr)
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= 277299)
|
||||
if (params.fPowAllowMinDifficultyBlocks &&
|
||||
pindexLast->nHeight >= params.nAllowMinDiffMinHeight &&
|
||||
pindexLast->nHeight < params.nAllowMinDiffMaxHeight)
|
||||
{
|
||||
// Special difficulty rule for testnet:
|
||||
// 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){
|
||||
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.
|
||||
int blockstogoback = params.DifficultyAdjustmentInterval()-1;
|
||||
if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
|
||||
blockstogoback = params.DifficultyAdjustmentInterval();
|
||||
int blockstogoback = params.DifficultyAdjustmentInterval();
|
||||
blockstogoback = std::min(blockstogoback, pindexLast->nHeight);
|
||||
|
||||
int nHeightFirst = pindexLast->nHeight - blockstogoback;
|
||||
assert(nHeightFirst >= 0);
|
||||
|
|
|
@ -91,7 +91,7 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
|||
"Result: \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"
|
||||
" {\n"
|
||||
" \"claimId\" (string) the claimId of the claim\n"
|
||||
|
@ -100,6 +100,7 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
|||
" \"amount\" (numeric) txout amount\n"
|
||||
" \"height\" (numeric) the height of the block in which this transaction is located\n"
|
||||
" \"value\" (string) the value of this claim\n"
|
||||
" \"name\" (string) the original name of this claim (before normalization)\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());
|
||||
}
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.pushKV("value", sValue);
|
||||
claim.pushKV("value", HexStr(vvchParams[1].begin(), vvchParams[1].end()));
|
||||
}
|
||||
std::string targetName;
|
||||
CClaimValue targetClaim;
|
||||
if (pclaimTrie->getClaimById(itClaims->claimId, targetName, targetClaim))
|
||||
claim.push_back(Pair("name", targetName));
|
||||
|
||||
claims.push_back(claim);
|
||||
}
|
||||
|
||||
UniValue nodeObj(UniValue::VOBJ);
|
||||
nodeObj.pushKV("name", name);
|
||||
nodeObj.pushKV("normalized_name", name);
|
||||
nodeObj.pushKV("claims", claims);
|
||||
nodes.push_back(nodeObj);
|
||||
}
|
||||
|
@ -249,7 +254,7 @@ static UniValue getclaimtrie(const JSONRPCRequest& request)
|
|||
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);
|
||||
if (coin.IsSpent())
|
||||
|
@ -267,14 +272,16 @@ static bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint&
|
|||
}
|
||||
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)
|
||||
{
|
||||
sValue = std::string(vvchParams[2].begin(), vvchParams[2].end());
|
||||
}
|
||||
sValue = HexStr(vvchParams[2].begin(), vvchParams[2].end());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static UniValue getvalueforname(const JSONRPCRequest& request)
|
||||
|
@ -282,7 +289,7 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
|
|||
if (request.fHelp || request.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"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"
|
||||
"1. \"name\" (string) the name to look up\n"
|
||||
"2. \"blockhash\" (string, optional) get the value\n"
|
||||
|
@ -299,7 +306,8 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
|
|||
"\"n\" (numeric) vout value\n"
|
||||
"\"amount\" (numeric) txout amount\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);
|
||||
|
||||
|
@ -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)
|
||||
|
||||
std::string sValue;
|
||||
if (!getValueForClaim(coinsCache, claim.outPoint, sValue))
|
||||
if (!getValueForOutPoint(coinsCache, claim.outPoint, sValue))
|
||||
return ret;
|
||||
|
||||
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("effective amount", nEffectiveAmount);
|
||||
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;
|
||||
}
|
||||
|
||||
typedef std::pair<CClaimValue, std::vector<CSupportValue> > claimAndSupportsType;
|
||||
typedef std::map<uint160, claimAndSupportsType> claimSupportMapType;
|
||||
|
||||
UniValue supportToJSON(const CSupportValue& support)
|
||||
UniValue supportToJSON(const CCoinsViewCache& coinsCache, const CSupportValue& support)
|
||||
{
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
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("nValidAtHeight", support.nValidAtHeight));
|
||||
ret.push_back(Pair("nAmount", support.nAmount));
|
||||
std::string value;
|
||||
if (getValueForOutPoint(coinsCache, support.outPoint, value))
|
||||
ret.push_back(Pair("value", value));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -355,7 +372,7 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffe
|
|||
|
||||
UniValue supportObjs(UniValue::VARR);
|
||||
for (const auto& support: supports)
|
||||
supportObjs.push_back(supportToJSON(support));
|
||||
supportObjs.push_back(supportToJSON(coinsCache, support));
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("claimId", itClaimsAndSupports->first.GetHex());
|
||||
|
@ -365,10 +382,16 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffe
|
|||
result.pushKV("nValidAtHeight", claim.nValidAtHeight);
|
||||
result.pushKV("nAmount", claim.nAmount);
|
||||
std::string sValue;
|
||||
if (getValueForClaim(coinsCache, claim.outPoint, sValue))
|
||||
if (getValueForOutPoint(coinsCache, claim.outPoint, sValue))
|
||||
result.pushKV("value", sValue);
|
||||
result.pushKV("nEffectiveAmount", nEffectiveAmount);
|
||||
result.pushKV("supports", supportObjs);
|
||||
|
||||
std::string targetName;
|
||||
CClaimValue targetClaim;
|
||||
if (pclaimTrie->getClaimById(claim.claimId, targetName, targetClaim))
|
||||
result.push_back(Pair("name", targetName));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -389,6 +412,7 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
|
|||
"Result:\n"
|
||||
"{\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"
|
||||
" {\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"
|
||||
" \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\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"
|
||||
" \"supports\" : [ (array of object) supports for this claim\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"
|
||||
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
|
||||
" \"nAmount\" (numeric) the amount of the support\n"
|
||||
" \"value\" (string) the metadata of the support if any\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
|
@ -446,13 +471,14 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
|
|||
{
|
||||
claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId);
|
||||
if (itClaimAndSupports == claimSupportMap.end())
|
||||
unmatchedSupports.push_back(supportToJSON(*itSupports));
|
||||
unmatchedSupports.push_back(supportToJSON(coinsCache, *itSupports));
|
||||
else
|
||||
itClaimAndSupports->second.second.push_back(*itSupports);
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight);
|
||||
result.pushKV("normalized_name", claimsForName.name);
|
||||
|
||||
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"
|
||||
"Result:\n"
|
||||
"{\n"
|
||||
" \"name\" (string) the name of the claim\n"
|
||||
" \"value\" (string) claim metadata\n"
|
||||
" \"name\" (string) the original name of the claim (before normalization)\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"
|
||||
" \"txid\" (string) the hash of the transaction which has successfully claimed this name\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"
|
||||
" \"valid at height\" (numeric) the height at which the support is valid\n"
|
||||
" \"amount\" (numeric) the amount of the support\n"
|
||||
" \"value\" (string) the metadata of the support if any\n"
|
||||
" ]\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"
|
||||
|
@ -509,8 +537,10 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
|
|||
|
||||
std::string sValue;
|
||||
claim.pushKV("name", name);
|
||||
if (trieCache.shouldNormalize())
|
||||
claim.push_back(Pair("normalized_name", trieCache.normalizeClaimName(name, true)));
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
if (getValueForClaim(coinsCache, claimValue.outPoint, sValue))
|
||||
if (getValueForOutPoint(coinsCache, claimValue.outPoint, sValue))
|
||||
claim.pushKV("value", sValue);
|
||||
claim.pushKV("claimId", claimValue.claimId.GetHex());
|
||||
claim.pushKV("txid", claimValue.outPoint.hash.GetHex());
|
||||
|
@ -525,6 +555,8 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
|
|||
supportEntry.pushKV("height", support.nHeight);
|
||||
supportEntry.pushKV("valid at height", support.nValidAtHeight);
|
||||
supportEntry.pushKV("amount", support.nAmount);
|
||||
if (getValueForOutPoint(coinsCache, support.outPoint, sValue))
|
||||
claim.pushKV("value", sValue);
|
||||
supportList.pushKVs(supportEntry);
|
||||
}
|
||||
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"
|
||||
" \"claim type\" (string) 'claim' or 'support'\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"
|
||||
" \"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"
|
||||
|
@ -653,22 +686,22 @@ UniValue getclaimsfortx(const JSONRPCRequest& request)
|
|||
o.pushKV("name", sName);
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
uint160 claimId = ClaimIdHash(hash, i);
|
||||
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)
|
||||
{
|
||||
uint160 claimId(vvchParams[1]);
|
||||
std::string sValue(vvchParams[2].begin(), vvchParams[2].end());
|
||||
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)
|
||||
{
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
o.pushKV("supported claimId", supportedClaimId.GetHex());
|
||||
if (vvchParams.size() > 2)
|
||||
o.pushKV("supported value", HexStr(vvchParams[2].begin(), vvchParams[2].end()));
|
||||
}
|
||||
if (nHeight > 0)
|
||||
{
|
||||
|
@ -850,6 +883,24 @@ UniValue getnameproof(const JSONRPCRequest& request)
|
|||
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[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
|
@ -863,6 +914,7 @@ static const CRPCCommand commands[] =
|
|||
{ "Claimtrie", "getclaimsfortx", &getclaimsfortx, { "txid" } },
|
||||
{ "Claimtrie", "getnameproof", &getnameproof, { "name","blockhash"} },
|
||||
{ "Claimtrie", "getclaimbyid", &getclaimbyid, { "claimId" } },
|
||||
{ "Claimtrie", "checknormalization", &checknormalization, { "name" }},
|
||||
};
|
||||
|
||||
void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC)
|
||||
|
|
|
@ -19,6 +19,8 @@ enum isminetype
|
|||
ISMINE_NO = 0,
|
||||
ISMINE_WATCH_ONLY = 1,
|
||||
ISMINE_SPENDABLE = 2,
|
||||
ISMINE_CLAIM = 4,
|
||||
ISMINE_SUPPORT = 8,
|
||||
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
|
||||
};
|
||||
/** used for bitflags of isminetype */
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
|
||||
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_false(false);
|
||||
|
||||
|
@ -130,6 +131,7 @@ struct ClaimTrieChainFixture{
|
|||
std::vector<int> marks;
|
||||
int coinbase_txs_used;
|
||||
int unique_block_counter;
|
||||
int normalization_original;
|
||||
unsigned int num_txs;
|
||||
unsigned int num_txs_for_next_block;
|
||||
|
||||
|
@ -142,15 +144,16 @@ struct ClaimTrieChainFixture{
|
|||
ClaimTrieChainFixture():
|
||||
expirationForkHeight(Params().GetConsensus().nExtendedClaimExpirationForkHeight),
|
||||
originalExpiration(Params().GetConsensus().nOriginalClaimExpirationTime),
|
||||
extendedExpiration(Params().GetConsensus().nExtendedClaimExpirationTime)
|
||||
extendedExpiration(Params().GetConsensus().nExtendedClaimExpirationTime),
|
||||
unique_block_counter(0), normalization_original(-1)
|
||||
{
|
||||
fRequireStandard = false;
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->nCurrentHeight, chainActive.Height() + 1);
|
||||
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 = 0;
|
||||
coinbase_txs_used = 0;
|
||||
unique_block_counter = 0;
|
||||
// generate coinbases to spend
|
||||
CreateCoinbases(40, coinbase_txs);
|
||||
}
|
||||
|
@ -158,6 +161,21 @@ struct ClaimTrieChainFixture{
|
|||
~ClaimTrieChainFixture()
|
||||
{
|
||||
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)
|
||||
|
@ -216,8 +234,8 @@ struct ClaimTrieChainFixture{
|
|||
}
|
||||
|
||||
//spend a bid into some non claimtrie related unspent
|
||||
CMutableTransaction Spend(const CTransaction &prev){
|
||||
|
||||
CMutableTransaction Spend(const CTransaction &prev)
|
||||
{
|
||||
uint32_t prevout = 0;
|
||||
CMutableTransaction tx = BuildTransaction(prev, prevout);
|
||||
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)
|
||||
{
|
||||
uint32_t prevout = 0;
|
||||
|
||||
CMutableTransaction tx = BuildTransaction(prev,prevout);
|
||||
tx.vout[0].scriptPubKey = ClaimNameScript(name, value);
|
||||
tx.vout[0].nValue = quantity;
|
||||
|
@ -275,9 +292,8 @@ struct ClaimTrieChainFixture{
|
|||
|
||||
CTransaction GetCoinbase()
|
||||
{
|
||||
auto tx = coinbase_txs[coinbase_txs_used];
|
||||
coinbase_txs_used++;
|
||||
return tx;
|
||||
assert(coinbase_txs_used + 1 < coinbase_txs.size());
|
||||
return coinbase_txs[coinbase_txs_used++];
|
||||
}
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
@ -1167,7 +1681,8 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test)
|
|||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0);
|
||||
|
||||
CMutableTransaction tx1 = BuildTransaction(fixture.GetCoinbase());
|
||||
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME
|
||||
tx1.vout[0].scriptPubKey = CScript()
|
||||
<< OP_CLAIM_NAME
|
||||
<< 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);
|
||||
|
|
|
@ -122,19 +122,19 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
|
||||
BOOST_CHECK(pclaimTrie->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));
|
||||
BOOST_CHECK(ntState.getMerkleHash() == hash1);
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash1);
|
||||
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.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused);
|
||||
BOOST_CHECK(ntState.getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
||||
ntState.flush();
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
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("tes"), tx4OutPoint, unused);
|
||||
|
||||
BOOST_CHECK(ntState1.getMerkleHash() == hash0);
|
||||
BOOST_CHECK_EQUAL(ntState1.getMerkleHash(), hash0);
|
||||
|
||||
CClaimTrieCacheTest ntState2(pclaimTrie);
|
||||
ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200));
|
||||
ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
|
||||
|
||||
BOOST_CHECK(ntState2.getMerkleHash() == hash3);
|
||||
BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
|
||||
|
||||
ntState2.flush();
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash3);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCacheTest ntState3(pclaimTrie);
|
||||
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
|
||||
BOOST_CHECK(ntState3.getMerkleHash() == hash4);
|
||||
BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
|
||||
ntState3.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash4);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCacheTest ntState4(pclaimTrie);
|
||||
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused);
|
||||
BOOST_CHECK(ntState4.getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
|
||||
ntState4.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCacheTest ntState5(pclaimTrie);
|
||||
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
|
||||
|
||||
BOOST_CHECK(ntState5.getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
|
||||
ntState5.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCacheTest ntState6(pclaimTrie);
|
||||
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
|
||||
|
||||
BOOST_CHECK(ntState6.getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
|
||||
ntState6.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
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("test2"), tx2OutPoint, unused);
|
||||
|
||||
BOOST_CHECK(ntState7.getMerkleHash() == hash0);
|
||||
BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
|
||||
ntState7.flush();
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0);
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
||||
{
|
||||
// test basic claim insertions and that get methods retreives information properly
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->empty(), true);
|
||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||
|
||||
// create and insert claim
|
||||
|
@ -223,14 +223,14 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
|||
|
||||
// try getClaimsForName, getEffectiveAmountForClaim, getInfoForName
|
||||
claimsForNameType res = ctc.getClaimsForName("test");
|
||||
BOOST_CHECK(res.claims.size() == 1);
|
||||
BOOST_CHECK(res.claims[0] == claimVal);
|
||||
BOOST_CHECK_EQUAL(res.claims.size(), 1);
|
||||
BOOST_CHECK_EQUAL(res.claims[0], claimVal);
|
||||
|
||||
BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId));
|
||||
|
||||
CClaimValue claim;
|
||||
BOOST_CHECK(ctc.getInfoForName("test", claim));
|
||||
BOOST_CHECK(claim == claimVal);
|
||||
BOOST_CHECK_EQUAL(ctc.getInfoForName("test", claim), true);
|
||||
BOOST_CHECK_EQUAL(claim, claimVal);
|
||||
|
||||
// insert a support
|
||||
CAmount supportAmount(10);
|
||||
|
@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
||||
{
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->empty(), true);
|
||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||
|
||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
|
@ -297,7 +297,8 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
|||
|
||||
int count = 0;
|
||||
|
||||
struct TestCallBack : public CNodeCallback {
|
||||
struct TestCallBack : public CNodeCallback
|
||||
{
|
||||
TestCallBack(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
@ -305,20 +306,20 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
|||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
count++;
|
||||
if (name == "test") {
|
||||
if (name == "test")
|
||||
BOOST_CHECK_EQUAL(node->claims.size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
int& count;
|
||||
} testCallback(count);
|
||||
|
||||
BOOST_CHECK(ctc.iterateTrie(testCallback));
|
||||
BOOST_CHECK_EQUAL(ctc.iterateTrie(testCallback), true);
|
||||
BOOST_CHECK_EQUAL(count, 5);
|
||||
|
||||
count = 3;
|
||||
|
||||
struct TestCallBack2 : public CNodeCallback {
|
||||
struct TestCallBack2 : public CNodeCallback
|
||||
{
|
||||
TestCallBack2(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
@ -332,7 +333,7 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
|||
int& count;
|
||||
} testCallback2(count);
|
||||
|
||||
BOOST_CHECK(!ctc.iterateTrie(testCallback2));
|
||||
BOOST_CHECK_EQUAL(ctc.iterateTrie(testCallback2), false);
|
||||
BOOST_CHECK_EQUAL(count, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -2187,7 +2187,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
spentClaimsType::iterator 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;
|
||||
}
|
||||
if (itSpent != spentClaims.end())
|
||||
|
|
Loading…
Add table
Reference in a new issue