mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-06-16 18:19:40 +08:00
WIP: Namedb: fix bugs and logic errors in preorder, register, update,
and namespace_preorder.
This commit is contained in:
@@ -3,18 +3,34 @@
|
||||
"""
|
||||
Blockstore
|
||||
~~~~~
|
||||
:copyright: (c) 2015 by Openname.org
|
||||
:license: MIT, see LICENSE for more details.
|
||||
copyright: (c) 2014 by Halfmoon Labs, Inc.
|
||||
copyright: (c) 2015 by Blockstack.org
|
||||
|
||||
This file is part of Blockstore
|
||||
|
||||
Blockstore is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Blockstore is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Blockstore. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import json
|
||||
import traceback
|
||||
import binascii
|
||||
import hashlib
|
||||
import math
|
||||
|
||||
from collections import defaultdict
|
||||
from ..config import NAMESPACE_DEFAULT, MIN_OP_LENGTHS, OPCODES, MAGIC_BYTES, TESTSET
|
||||
from ..config import NAMESPACE_DEFAULT, MIN_OP_LENGTHS, OPCODES, MAGIC_BYTES, TESTSET, MAX_NAMES_PER_SENDER, EXPIRATION_PERIOD, NAME_PREORDER, NAMESPACE_PREORDER
|
||||
from ..operations import build_namespace_define
|
||||
from ..hashing import *
|
||||
|
||||
import virtualchain
|
||||
log = virtualchain.session.log
|
||||
@@ -66,14 +82,20 @@ class BlockstoreDBIterator(object):
|
||||
Serialize a name record:
|
||||
make it sortable on the name (names are unique, so this imposes
|
||||
a total order on the set of serialized name records), and include the
|
||||
owner's script_pubkey and profile hash.
|
||||
owner's script_pubkey, profile hash, and revocation status.
|
||||
"""
|
||||
|
||||
profile_hash = name_record.get('value_hash', "")
|
||||
revoked_string = ""
|
||||
|
||||
if profile_hash is None:
|
||||
profile_hash = ""
|
||||
|
||||
if name_record['revoked']:
|
||||
revoked_string = "-revoked"
|
||||
|
||||
name_string = (name + name_record['sender'] + value_hash).encode('utf8')
|
||||
name_string = (name + name_record['sender'] + profile_hash + revoked_string).encode('utf8')
|
||||
|
||||
return name_string
|
||||
|
||||
|
||||
@@ -97,8 +119,6 @@ class BlockstoreDBIterator(object):
|
||||
try:
|
||||
namespace_string = (namespace_id + rules_string + sender).encode('utf8')
|
||||
except Exception, e:
|
||||
|
||||
print "\n%s\n" % namespace_record
|
||||
raise e
|
||||
|
||||
return namespace_string
|
||||
@@ -158,6 +178,8 @@ class BlockstoreDBIterator(object):
|
||||
self.next_name += 1
|
||||
|
||||
serialized_name_record = self.serialize_name_record( name, self.db.get_name( name ) )
|
||||
|
||||
log.debug(" Serialized name record: '%s' (%s)" % (serialized_name_record, name) )
|
||||
return serialized_name_record
|
||||
|
||||
# out of names
|
||||
@@ -182,6 +204,8 @@ class BlockstoreDBIterator(object):
|
||||
self.next_namespace += 1
|
||||
|
||||
serialized_namespace_record = self.serialize_namespace_record( namespace_id, self.db.get_namespace( namespace_id ) )
|
||||
|
||||
log.debug(" Serialized namespace record: '%s' (%s)" % (serialized_namespace_record, namespace_id) )
|
||||
return serialized_namespace_record
|
||||
|
||||
# out of namespaces
|
||||
@@ -206,6 +230,8 @@ class BlockstoreDBIterator(object):
|
||||
self.next_import_namespace += 1
|
||||
|
||||
serialized_importing_namespace = self.serialize_importing_namespace( namespace_id_hash, self.db.get_importing_namespace_raw( namespace_id_hash ) )
|
||||
|
||||
log.debug(" Serialized import record: '%s' (%s)" % (serialized_importing_namespace, namespace_id_hash) )
|
||||
return serialized_importing_namespace
|
||||
|
||||
# out of importing namespaces
|
||||
@@ -264,17 +290,20 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
# "first_registered": block when registered,
|
||||
# "last_renewed": block when last renewed,
|
||||
# "address": bitcoin public key of the sender
|
||||
# "value_hash": hex string of hash of profile JSON }
|
||||
# "value_hash": hex string of hash of profile JSON
|
||||
# "revoked": True if this name was revoked; False if not}
|
||||
|
||||
self.owner_names = defaultdict(list) # map sender_script_pubkey hex string to list of names owned by the principal it represents
|
||||
self.hash_names = {} # map hex_hash160(name) to name
|
||||
self.preorders = {} # map preorder name.ns_id+script_pubkey hash (as a hex string) to its first "preorder" nameop
|
||||
self.namespaces = {} # map namespace ID to first instance of NAMESPACE_DEFINE op (a dict) combined with the namespace name and sender script_pubkey
|
||||
self.namespace_preorders = {} # map hash(ns_id+script_pubkey) hex string to NAMESPACE_PREORDER op
|
||||
self.pending_imports = {} # map an in-progress namespace import (as the hex string of ns_id+script_pubkey hash) to a list of nameops.
|
||||
# The first element is always the NAMESPACE_PREORDER nameop.
|
||||
# The second element is always the NAMESPACE_DEFINE nameop.
|
||||
|
||||
self.block_name_registers = defaultdict(list) # map a block ID to the list of names that were registered at that block. Used to find expired names.
|
||||
self.block_name_renewals = defaultdict(list) # map a block ID to the list of names that were renewed at that block. Used to find expired names.
|
||||
|
||||
self.name_consensus_hash_name = {} # temporary table for mapping the hash(name + consensus_hash) in an update to its name
|
||||
|
||||
# default namespace (empty string)
|
||||
self.namespaces[""] = NAMESPACE_DEFAULT
|
||||
@@ -292,8 +321,10 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
if 'namespaces' in db_dict:
|
||||
self.namespaces = db_dict['namespaces']
|
||||
|
||||
if 'namespace_preorders' in db_dict:
|
||||
self.namespace_preorders = db_dict['namespace_preorders']
|
||||
# translate empty namesapce ID from json-ized format
|
||||
if "null" in self.namespaces.keys():
|
||||
self.namespaces[None] = self.namespaces["null"]
|
||||
del self.namespaces["null"]
|
||||
|
||||
if 'pending_imports' in db_dict:
|
||||
self.pending_imports = db_dict['pending_imports']
|
||||
@@ -304,6 +335,15 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
# build up our reverse indexes
|
||||
for name, name_record in self.name_records.items():
|
||||
self.block_name_renewals[ name_record['last_renewed'] ] = name
|
||||
self.owner_names[ name_record['sender'] ].append( name )
|
||||
self.hash_names[ hash256_trunc128( name ) ] = name
|
||||
|
||||
# load up consensus hash for this block
|
||||
self.snapshot( self.lastblock )
|
||||
|
||||
|
||||
def save_db(self, filename):
|
||||
"""
|
||||
@@ -319,8 +359,7 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
'registrations': self.name_records,
|
||||
'preorders': self.preorders,
|
||||
'namespaces': self.namespaces,
|
||||
'namespace_preorders': self.namespace_preorders,
|
||||
'pending_imports': self.pending_imports
|
||||
'pending_imports': self.pending_imports,
|
||||
}
|
||||
|
||||
f.write(json.dumps(db_dict))
|
||||
@@ -397,6 +436,7 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
|
||||
names = self.owner_names.get( sender, None )
|
||||
if names is None:
|
||||
|
||||
# invalid name owner
|
||||
return None
|
||||
|
||||
@@ -404,7 +444,8 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
|
||||
for i in xrange( block_id - virtualchain.config.BLOCKS_CONSENSUS_HASH_IS_VALID, block_id ):
|
||||
consensus_hash = self.get_consensus_at( i )
|
||||
possible_consensus_hashes.append( consensus_hash )
|
||||
if consensus_hash is not None:
|
||||
possible_consensus_hashes.append( consensus_hash )
|
||||
|
||||
for name in names:
|
||||
for consensus_hash in possible_consensus_hashes:
|
||||
@@ -492,14 +533,13 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
return self.pending_imports[ namespace_id_hash ]
|
||||
|
||||
|
||||
def find_expires_at( self, block_id ):
|
||||
def find_renewed_at( self, block_id ):
|
||||
"""
|
||||
Given a block ID, find all names that will have expired exactly
|
||||
EXPIRATION_PERIOD blocks ago.
|
||||
Find all names registered at a particular block.
|
||||
|
||||
Returns a list of names on success (which can be empty)
|
||||
"""
|
||||
return self.block_name_registers.get( block_id, [] )
|
||||
return self.block_name_renewals.get( block_id, [] )
|
||||
|
||||
|
||||
def is_name_registered(self, name):
|
||||
@@ -528,10 +568,10 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
Return False if not.
|
||||
"""
|
||||
|
||||
if namespace_id_hash not in self.namespace_preorders.keys():
|
||||
namespace_preorder = self.get_importing_namespace_preorder( namespace_id_hash )
|
||||
if namespace_preorder is None:
|
||||
return False
|
||||
|
||||
namespace_preorder = self.get_importing_namespace_preorder( namespace_id_hash )
|
||||
if namespace_preorder['sender'] != sender_script_pubkey:
|
||||
return False
|
||||
|
||||
@@ -658,13 +698,14 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
Return True if so.
|
||||
Return False if not.
|
||||
"""
|
||||
return (namespace_id_hash not in self.namespace_preorders.keys())
|
||||
return (self.get_importing_namespace_preorder(namespace_id_hash) is None)
|
||||
|
||||
|
||||
def is_name_imported( self, name, sender_script_pubkey ):
|
||||
"""
|
||||
Given a name and a sender script_pubkey hex string, determine if the given name is part of a namespace import.
|
||||
The name must have been sent by the same sender who sent the NAMESPACE_DEFINE
|
||||
|
||||
Return True if so
|
||||
Return False if not.
|
||||
"""
|
||||
@@ -678,6 +719,22 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
|
||||
return self.is_namespace_importing_hash( namespace_id_hash )
|
||||
|
||||
|
||||
def is_name_revoked( self, name ):
|
||||
"""
|
||||
Given a name, determine whether or not it was revoked.
|
||||
If the name was not registered in the first place, then it was not revoked.
|
||||
|
||||
Return True if so
|
||||
Return False if not
|
||||
"""
|
||||
|
||||
if name not in self.name_records.keys():
|
||||
# doesn't exist, so not revoked
|
||||
return False
|
||||
|
||||
return self.name_records[name]['revoked']
|
||||
|
||||
|
||||
def is_name_expired_at( self, name, block_id ):
|
||||
"""
|
||||
@@ -689,7 +746,7 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
"""
|
||||
|
||||
expiring_block_number = block_id - EXPIRATION_PERIOD
|
||||
names_expiring = self.find_expires_at( expiring_block_number )
|
||||
names_expiring = self.find_renewed_at( expiring_block_number )
|
||||
return (name in names_expiring)
|
||||
|
||||
|
||||
@@ -698,7 +755,8 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
Remove a name that has expired.
|
||||
"""
|
||||
|
||||
name_hash128 = hash256_trunc128( name )
|
||||
name_hash = hash256_trunc128( name )
|
||||
|
||||
owner = None
|
||||
|
||||
if not self.name_records.has_key( name ):
|
||||
@@ -711,6 +769,9 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
if self.owner_names.has_key( owner ):
|
||||
del self.owner_names[ owner ]
|
||||
|
||||
if self.hash_names.has_key( name_hash ):
|
||||
del self.hash_names[ name_hash ]
|
||||
|
||||
|
||||
def commit_name_expire_all( self, block_id ):
|
||||
"""
|
||||
@@ -718,23 +779,14 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
exactly EXPIRATION_PERIOD blocks ago.
|
||||
"""
|
||||
|
||||
expired_names = self.find_expires_at( block_id )
|
||||
expiring_block_number = block_id - EXPIRATION_PERIOD
|
||||
expired_names = self.find_renewed_at( expiring_block_number )
|
||||
for name in expired_names:
|
||||
|
||||
self.commit_name_expire( name )
|
||||
|
||||
|
||||
def commit_remove_namespace_preorder( self, namespace_id, script_pubkey ):
|
||||
"""
|
||||
Given the namespace ID and a script_pubkey hex string,
|
||||
remove the namespace preorder.
|
||||
"""
|
||||
try:
|
||||
namespace_id_hash = hash_name(namespace_id, script_pubkey)
|
||||
except ValueError:
|
||||
return None
|
||||
else:
|
||||
del self.namespace_preorders[namespace_id_hash]
|
||||
if expiring_block_number in self.block_name_renewals.keys():
|
||||
del self.block_name_renewals[ expiring_block_number ]
|
||||
|
||||
|
||||
def commit_remove_preorder( self, name, script_pubkey ):
|
||||
@@ -794,20 +846,30 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
self.commit_namespace_import( nameop, current_block_number )
|
||||
|
||||
else:
|
||||
# registered!
|
||||
self.commit_remove_preorder( name, sender )
|
||||
|
||||
name_record = {
|
||||
'value_hash': None, # i.e. the hex hash of profile data in immutable storage.
|
||||
'sender': str(sender),
|
||||
'first_registered': current_block_number,
|
||||
'last_renewed': current_block_number,
|
||||
'address': address
|
||||
}
|
||||
|
||||
self.name_records[ name ] = name_record
|
||||
self.block_expirations[ current_block_number ].append( name )
|
||||
self.owner_names[ sender ].append( str(sender) )
|
||||
# is this a renewal?
|
||||
if self.is_name_registered( name ):
|
||||
|
||||
self.commit_renewal( nameop, current_block_number )
|
||||
|
||||
else:
|
||||
|
||||
# registered!
|
||||
self.commit_remove_preorder( name, sender )
|
||||
|
||||
name_record = {
|
||||
'value_hash': None, # i.e. the hex hash of profile data in immutable storage.
|
||||
'sender': str(sender),
|
||||
'first_registered': current_block_number,
|
||||
'last_renewed': current_block_number,
|
||||
'address': address,
|
||||
'revoked': False
|
||||
}
|
||||
|
||||
self.name_records[ name ] = name_record
|
||||
self.owner_names[ sender ].append( str(name) )
|
||||
self.hash_names[ hash256_trunc128( name ) ] = name
|
||||
self.block_name_renewals[ current_block_number ].append( name )
|
||||
|
||||
|
||||
def commit_renewal( self, nameop, current_block_number ):
|
||||
@@ -819,8 +881,8 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
block_last_renewed = self.name_records[name]['last_renewed']
|
||||
|
||||
# name no longer expires at last renewal time...
|
||||
self.block_expirations[ block_last_renewed ].remove( name )
|
||||
self.block_expirations[ current_block_number ].append( name )
|
||||
self.block_name_renewals[ block_last_renewed ].remove( name )
|
||||
self.block_name_renewals[ current_block_number ].append( name )
|
||||
|
||||
self.name_records[name]['last_renewed'] = current_block_number
|
||||
|
||||
@@ -832,6 +894,14 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
"""
|
||||
|
||||
sender = nameop['sender']
|
||||
name_consensus_hash = nameop['name_hash']
|
||||
|
||||
try:
|
||||
name = nameop['name']
|
||||
except:
|
||||
print "\n\nnameop: %s\n\n" % nameop
|
||||
name = self.name_consensus_hash_name[ name_consensus_hash ]
|
||||
del self.name_consensus_hash_name[ name_consensus_hash ]
|
||||
|
||||
if self.is_name_imported( name, sender ):
|
||||
# this is part of a namespace import
|
||||
@@ -839,7 +909,6 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
|
||||
else:
|
||||
|
||||
name = nameop['name']
|
||||
self.name_records[name]['value_hash'] = nameop['update_hash']
|
||||
|
||||
|
||||
@@ -847,19 +916,30 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
"""
|
||||
Commit a transfer--update the name record to indicate the recipient of the
|
||||
transaction as the new owner.
|
||||
|
||||
TODO: blow away previous owner's data, if requested
|
||||
"""
|
||||
|
||||
name = nameop['name']
|
||||
owner = nameop['sender']
|
||||
recipient = nameop['recipient']
|
||||
keep_data = nameop['keep_data']
|
||||
|
||||
self.name_records[name]['sender'] = recipient
|
||||
|
||||
self.owner_names[owner].remove( name )
|
||||
self.owner_names[recipient].append( name )
|
||||
|
||||
if not keep_data:
|
||||
self.name_records[name]['value_hash'] = None
|
||||
|
||||
|
||||
def commit_revoke( self, nameop, current_block_number ):
|
||||
"""
|
||||
Commit a revocation--update the name record.
|
||||
"""
|
||||
|
||||
name = nameop['name']
|
||||
self.name_records[name]['revoked'] = True
|
||||
|
||||
|
||||
def commit_namespace_preorder( self, nameop, block_number ):
|
||||
"""
|
||||
@@ -873,8 +953,6 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
namespace_id_hash = nameop['namespace_id_hash']
|
||||
sender = nameop['sender']
|
||||
|
||||
self.commit_remove_namespace_preorder( namespace_id_hash, sender )
|
||||
|
||||
# this namespace is preordered, but not yet defined
|
||||
self.pending_imports[ namespace_id_hash ] = [nameop]
|
||||
|
||||
@@ -970,6 +1048,10 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
preorder_name_hash = nameop['preorder_name_hash']
|
||||
consensus_hash = nameop['consensus_hash']
|
||||
|
||||
for pending_preorders in pending_nameops[ NAME_PREORDER ]:
|
||||
if pending_preorders['preorder_name_hash'] == preorder_name_hash:
|
||||
return False
|
||||
|
||||
if self.is_new_preorder(preorder_name_hash) and self.is_consensus_hash_valid( block_id, consensus_hash ):
|
||||
# new hash and right consensus
|
||||
return True
|
||||
@@ -994,7 +1076,7 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
sender = nameop['sender']
|
||||
namespace_id = get_namespace_from_name( name )
|
||||
|
||||
if self.log_namespace_import( nameop, block_id ):
|
||||
if self.log_namespace_import( pending_nameops, nameop, block_id ):
|
||||
# this registration is part of a namespace import
|
||||
# will add to the namespace's list of imports.
|
||||
return True
|
||||
@@ -1007,11 +1089,11 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
return False
|
||||
|
||||
# sender exceeded maximum number of names?
|
||||
if len( self.owner_names.get( name, [] ) ) >= config.MAX_NAMES_PER_SENDER:
|
||||
if len( self.owner_names.get( name, [] ) ) >= MAX_NAMES_PER_SENDER:
|
||||
return False
|
||||
|
||||
namespace_base_price = nameop['cost']
|
||||
namespace_price_decay = nameop['price_decay']
|
||||
namespace_base_price = namespace['cost']
|
||||
namespace_price_decay = namespace['price_decay']
|
||||
|
||||
# is this registration valid?
|
||||
if not self.is_name_registered( name ) and self.has_preordered_name( name, sender ) and is_mining_fee_sufficient( name, nameop['fee'], namespace_base_price, namespace_price_decay ):
|
||||
@@ -1049,16 +1131,25 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
# nothing to do--write is stale or on a fork
|
||||
return False
|
||||
|
||||
# remember the name, so we don't have to re-calculate it
|
||||
# remember the name, so we don't have to re-calculate it (either in log_namespace_import, or in commit_update)
|
||||
self.name_consensus_hash_name[ name_consensus_hash ] = name
|
||||
nameop['name'] = name
|
||||
|
||||
if self.log_namespace_import( nameop, block_id ):
|
||||
if self.log_namespace_import( pending_nameops, nameop, block_id ):
|
||||
# this update is part of a namespace import
|
||||
# will add to the namespace's list of imports.
|
||||
return True
|
||||
|
||||
else:
|
||||
|
||||
if not self.is_name_registered( name ):
|
||||
# doesn't exist
|
||||
return False
|
||||
|
||||
if self.is_name_revoked( name ):
|
||||
# revoked
|
||||
return False
|
||||
|
||||
if self.is_name_owner( name, sender ):
|
||||
|
||||
# update is sent by the owner of the name, so accept
|
||||
@@ -1071,7 +1162,7 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
def log_transfer( self, pending_nameops, nameop, block_id ):
|
||||
"""
|
||||
Log a name's transferrance to another private key.
|
||||
The name must exist and be owned by the sender.
|
||||
The name must exist, not be revoked, and be owned by the sender.
|
||||
The recipient must not exceed the maximum allowed number of names per keypair,
|
||||
and the recipient cannot own an equivalent name.
|
||||
|
||||
@@ -1079,10 +1170,21 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
Return False if not
|
||||
"""
|
||||
|
||||
name = nameop['name']
|
||||
name_hash = nameop['name_hash']
|
||||
name = self.hash_names.get( name_hash )
|
||||
|
||||
if name is None:
|
||||
# invalid
|
||||
return False
|
||||
|
||||
consensus_hash = nameop['consensus_hash']
|
||||
sender = nameop['sender']
|
||||
recipient = nameop['recipient']
|
||||
|
||||
if not self.is_consensus_hash_valid( consensus_hash, block_id ):
|
||||
# nope
|
||||
return False
|
||||
|
||||
if sender == recipient:
|
||||
# nonsensical
|
||||
return False
|
||||
@@ -1093,6 +1195,10 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
if not self.is_name_owner( name, sender ):
|
||||
return False
|
||||
|
||||
if self.is_name_revoked( name ):
|
||||
# name exists and was revoked
|
||||
return False
|
||||
|
||||
if recipient in self.owner_names.keys():
|
||||
|
||||
# recipient already has names...
|
||||
@@ -1108,6 +1214,38 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
return True
|
||||
|
||||
|
||||
def log_revoke( self, pending_nameops, nameop, block_id ):
|
||||
"""
|
||||
Revoke a name. It will still exist, but no future
|
||||
updates or transfers on it will be accepted.
|
||||
The sender must own the name, and the name must be registered.
|
||||
|
||||
Return True if accepted
|
||||
Return False if not
|
||||
"""
|
||||
|
||||
name = nameop['name']
|
||||
sender = nameop['sender']
|
||||
|
||||
if self.log_namespace_import( pending_nameops, nameop, block_id ):
|
||||
# this update is part of a namespace import
|
||||
# will add to the namespace's list of imports.
|
||||
return True
|
||||
|
||||
if not self.is_name_registered( name ):
|
||||
return False
|
||||
|
||||
if not self.is_name_owner( name, sender ):
|
||||
return False
|
||||
|
||||
if self.is_name_revoked( name ):
|
||||
# name was already revoked
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def log_namespace_preorder( self, pending_nameops, nameop, block_id ):
|
||||
"""
|
||||
Given a NAMESPACE_PREORDER nameop, see if we can preorder it.
|
||||
@@ -1120,7 +1258,12 @@ class BlockstoreDB( virtualchain.StateEngine ):
|
||||
namespace_id_hash = nameop['namespace_id_hash']
|
||||
consensus_hash = nameop['consensus_hash']
|
||||
|
||||
if self.is_new_namespace_preorder(preorder_name_hash) and self.is_consensus_hash_valid( block_id, consensus_hash ):
|
||||
# block duplicate preorders
|
||||
for pending_namespace_preorder in pending_nameops[ NAMESPACE_PREORDER ]:
|
||||
if pending_namespace_preorder['namespace_id_hash'] == namespace_id_hash:
|
||||
return False
|
||||
|
||||
if self.is_new_namespace_preorder(namespace_id_hash) and self.is_consensus_hash_valid( block_id, consensus_hash ):
|
||||
# new hash and right consensus
|
||||
return True
|
||||
|
||||
@@ -1240,13 +1383,13 @@ def price_name( name, namespace_base_price, namespace_decay ):
|
||||
price = float(namespace_base_price)
|
||||
|
||||
# adjust the price by a factor X for every character beyond the first
|
||||
price = ceil( price / (namespace_decay**(len(name)-1)) )
|
||||
price = math.ceil( price / (namespace_decay**(len(name)-1)) )
|
||||
|
||||
# price cannot be lower than 1 satoshi
|
||||
if price < 1:
|
||||
price = 1
|
||||
|
||||
return price
|
||||
return int(price)
|
||||
|
||||
|
||||
def is_mining_fee_sufficient( name, mining_fee, namespace_base_price, namespace_decay ):
|
||||
@@ -1258,5 +1401,5 @@ def is_mining_fee_sufficient( name, mining_fee, namespace_base_price, namespace_
|
||||
Return False if not.
|
||||
"""
|
||||
|
||||
name_price = calculate_name_price(name, namespace_base_price, namespace_decay)
|
||||
name_price = price_name(name, namespace_base_price, namespace_decay)
|
||||
return (mining_fee >= name_price)
|
||||
|
||||
Reference in New Issue
Block a user