mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-23 19:31:00 +08:00
remove salt from the name registration process
This commit is contained in:
@@ -20,8 +20,6 @@ __Table of Contents__
|
||||
- [Constraints](<#constraints>)
|
||||
|
||||
|
||||
|
||||
|
||||
## Intro
|
||||
<a name="intro"/>
|
||||
|
||||
@@ -56,7 +54,7 @@ Install libzmq-dev
|
||||
+ validated sequence of operations + rules to interpret them = global consensus / agreed upon view of the system
|
||||
+ data is simply stored in the blockchain in a defined sequence, and nodes read the blockchain and interpret the sequence of events with a set of defined rules. From this, they build a view of the system that should be in sync.
|
||||
register names by being the first to include the name in a “registration” operation
|
||||
+ to prevent people from stealing your name, first secretly “preorder” the name, but include a salted hash of the name in the blockchain
|
||||
+ to prevent people from stealing your name, first secretly “preorder” the name, but include a hash of the name in the blockchain
|
||||
+ to associate data with the name, issue an “update” operation by including a hash of the data and storing the data itself in the DHT
|
||||
+ to lookup the data associated with a name, issue a request to an opennamed node, which will lookup the name’s entry in the nameset, find the hash associated with the name, then go into the DHT with the hash and get the data associated with it
|
||||
+ there are many, many possible namespaces
|
||||
@@ -84,8 +82,7 @@ register names by being the first to include the name in a “registration” op
|
||||
|
||||
- `nameset`: all the names ever registered on all possible namespaces
|
||||
- `hash160`: a 20-byte ripemd160 hash
|
||||
- `salt`: a random value appended to data in order to prevent reverse-lookups of the hashed data
|
||||
- `preorder hash`: a hash160 of a given name to preorder, a random salt, and the scriptPubKey of the registrant
|
||||
- `preorder hash`: a hash160 of a given name to preorder and the scriptPubKey of the registrant
|
||||
- `name encoding`: a given name converted from base 40 to base 256
|
||||
- `consensus hash`: a hash of a data string generated from a representation of the nameset (also known as the historical record hash or merkle snapshot)
|
||||
- `update hash`: a hash of the data to be associated with a given name
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
__version__ = '0.1.0'
|
||||
|
||||
from .opennamed import run_opennamed
|
||||
from .openname_cli import run_cli
|
||||
from .openname_cli import run_cli
|
||||
|
||||
@@ -7,6 +7,8 @@ from opennamed import bitcoind
|
||||
|
||||
|
||||
def refresh_index(first_block, last_block):
|
||||
"""
|
||||
"""
|
||||
|
||||
start = datetime.datetime.now()
|
||||
|
||||
@@ -30,7 +32,7 @@ def refresh_index(first_block, last_block):
|
||||
print "merkle snapshot: %s\n" % merkle_snapshot
|
||||
pprint(db.name_records)
|
||||
|
||||
fout = open('lastblock.txt','w') #to overwrite
|
||||
fout = open('lastblock.txt', 'w') # to overwrite
|
||||
fout.write(str(last_block))
|
||||
fout.close()
|
||||
|
||||
|
||||
@@ -133,18 +133,18 @@ LENGTHS = {
|
||||
'opcode': 1,
|
||||
'name_hash': 20,
|
||||
'consensus_hash': 16,
|
||||
'namelen': 1,
|
||||
'name_min': 1,
|
||||
'name_max': 16,
|
||||
'unencoded_name': 24,
|
||||
'salt': 16,
|
||||
'update_hash': 20,
|
||||
}
|
||||
|
||||
MIN_OP_LENGTHS = {
|
||||
'preorder': LENGTHS['name_hash'],
|
||||
'registration': LENGTHS['name_min'] + LENGTHS['salt'],
|
||||
'update': LENGTHS['name_min'] + LENGTHS['update_hash'],
|
||||
'transfer': LENGTHS['name_min']
|
||||
'registration': LENGTHS['namelen'] + LENGTHS['name_min'],
|
||||
'update': LENGTHS['namelen'] + LENGTHS['name_min'] + LENGTHS['update_hash'],
|
||||
'transfer': LENGTHS['namelen'] + LENGTHS['name_min']
|
||||
}
|
||||
|
||||
OP_RETURN_MAX_SIZE = 40
|
||||
|
||||
@@ -7,23 +7,10 @@ from .b40 import b40_to_bin
|
||||
from .config import LENGTHS
|
||||
|
||||
|
||||
def gen_name_salt(hex_format=False):
|
||||
bin_salt = dev_urandom_entropy(LENGTHS['salt'])
|
||||
return bin_salt
|
||||
|
||||
|
||||
def is_hex_salt(s):
|
||||
if is_hex(s) and len(unhexlify(s)) == LENGTHS['salt']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def hash_name(name, salt, script_pubkey, hex_format=True):
|
||||
if hex_format and not (is_hex_salt(salt) and is_hex(script_pubkey)):
|
||||
raise ValueError('Salt must be a %i byte hex string' % LENGTHS['salt'])
|
||||
def hash_name(name, script_pubkey):
|
||||
bin_name = b40_to_bin(name)
|
||||
salted_name = bin_name + unhexlify(salt) + unhexlify(script_pubkey)
|
||||
return hex_hash160(salted_name)
|
||||
name_and_pubkey = bin_name + unhexlify(script_pubkey)
|
||||
return hex_hash160(name_and_pubkey)
|
||||
|
||||
|
||||
def calculate_consensus_hash128(consensus_hash):
|
||||
|
||||
@@ -19,9 +19,9 @@ def no_pending_higher_priority_registration(db, name, mining_fee):
|
||||
return True
|
||||
|
||||
|
||||
def has_preordered_name(db, name, salt, sender_script_pubkey):
|
||||
def has_preordered_name(db, name, sender_script_pubkey):
|
||||
try:
|
||||
name_hash = hash_name(name, salt, sender_script_pubkey)
|
||||
name_hash = hash_name(name, sender_script_pubkey)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from ..hashing import hash_name
|
||||
|
||||
|
||||
def remove_preorder(db, name, salt, script_pubkey):
|
||||
def remove_preorder(db, name, script_pubkey):
|
||||
try:
|
||||
name_hash = hash_name(name, salt, script_pubkey)
|
||||
name_hash = hash_name(name, script_pubkey)
|
||||
except ValueError:
|
||||
return False
|
||||
else:
|
||||
@@ -17,7 +17,7 @@ def commit_preorder(db, nameop):
|
||||
|
||||
def commit_registration(db, nameop, current_block_number):
|
||||
name = nameop['name']
|
||||
remove_preorder(db, name, nameop['salt'], nameop['sender'])
|
||||
remove_preorder(db, name, nameop['sender'])
|
||||
db.name_records[name] = {
|
||||
'value_hash': None,
|
||||
'owner': str(nameop['sender']),
|
||||
|
||||
@@ -9,7 +9,7 @@ def log_registration(db, nameop):
|
||||
name = nameop['name']
|
||||
# check if this registration is a valid one
|
||||
if (name_not_registered(db, name)
|
||||
and has_preordered_name(db, name, nameop['salt'], nameop['sender'])
|
||||
and has_preordered_name(db, name, nameop['sender'])
|
||||
and is_mining_fee_sufficient(name, nameop['fee'])):
|
||||
# we're good - log the registration!
|
||||
db.pending_registrations[name].append(nameop)
|
||||
|
||||
@@ -6,41 +6,35 @@ from binascii import hexlify, unhexlify
|
||||
from ..b40 import b40_to_hex
|
||||
from ..config import *
|
||||
from ..scripts import name_script_to_hex, add_magic_bytes
|
||||
from ..hashing import hash_name, calculate_consensus_hash128, gen_name_salt
|
||||
from ..hashing import hash_name, calculate_consensus_hash128
|
||||
|
||||
|
||||
def build(name, script_pubkey, consensus_hash, salt=None, testset=False):
|
||||
""" Takes in an ascii string as a name and an optional hex salt.
|
||||
def build(name, script_pubkey, consensus_hash, testset=False):
|
||||
""" Takes in an ascii string as a name.
|
||||
"""
|
||||
if salt:
|
||||
if not is_hex(salt) and len(unhexlify(salt)) == LENGTHS['salt']:
|
||||
raise ValueError('Invalid salt')
|
||||
else:
|
||||
salt = hexlify(gen_name_salt())
|
||||
|
||||
name_hash = hash_name(name, salt, script_pubkey)
|
||||
name_hash = hash_name(name, script_pubkey)
|
||||
|
||||
script = 'NAME_PREORDER %s %s' % (name_hash, consensus_hash)
|
||||
hex_script = name_script_to_hex(script)
|
||||
packaged_script = add_magic_bytes(hex_script, testset=testset)
|
||||
|
||||
return packaged_script, salt
|
||||
return packaged_script
|
||||
|
||||
|
||||
def broadcast(name, consensus_hash, private_key, salt=None,
|
||||
def broadcast(name, consensus_hash, private_key,
|
||||
blockchain_client=BlockchainInfoClient(), testset=False):
|
||||
""" Builds and broadcasts a preorder transaction.
|
||||
"""
|
||||
hash160 = BitcoinPrivateKey(private_key).public_key().hash160()
|
||||
script_pubkey = script_to_hex(
|
||||
'OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG' % hash160)
|
||||
nulldata, salt = build(
|
||||
name, script_pubkey, consensus_hash, testset=testset, salt=salt)
|
||||
nulldata = build(
|
||||
name, script_pubkey, consensus_hash, testset=testset)
|
||||
response = embed_data_in_blockchain(
|
||||
nulldata, private_key, blockchain_client, format='hex')
|
||||
# response = {'success': True }
|
||||
response.update(
|
||||
{'data': nulldata, 'salt': salt, 'consensus_hash': consensus_hash})
|
||||
{'data': nulldata, 'consensus_hash': consensus_hash})
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@@ -7,24 +7,22 @@ from ..config import *
|
||||
from ..scripts import name_script_to_hex, add_magic_bytes
|
||||
|
||||
|
||||
def build(name, salt, testset=False):
|
||||
""" Takes in the name that was preordered, along with the salt used.
|
||||
def build(name, testset=False):
|
||||
""" Takes in the name that was preordered.
|
||||
"""
|
||||
hex_name = b40_to_hex(name)
|
||||
name_len = len(hex_name)/2
|
||||
if not is_hex(salt):
|
||||
salt = hexlify(salt)
|
||||
|
||||
readable_script = 'NAME_REGISTRATION %i %s %s' % (name_len, hex_name, salt)
|
||||
readable_script = 'NAME_REGISTRATION %i %s' % (name_len, hex_name)
|
||||
hex_script = name_script_to_hex(readable_script)
|
||||
packaged_script = add_magic_bytes(hex_script, testset=testset)
|
||||
|
||||
return packaged_script
|
||||
|
||||
|
||||
def broadcast(name, salt, private_key,
|
||||
def broadcast(name, private_key,
|
||||
blockchain_client=BlockchainInfoClient(), testset=False):
|
||||
nulldata = build(name, salt, testset=testset)
|
||||
nulldata = build(name, testset=testset)
|
||||
# response = {'success': True }
|
||||
response = embed_data_in_blockchain(
|
||||
nulldata, private_key, blockchain_client, format='hex')
|
||||
@@ -35,9 +33,7 @@ def broadcast(name, salt, private_key,
|
||||
def parse(bin_payload):
|
||||
name_len = ord(bin_payload[0:1])
|
||||
name = bin_payload[1:1+name_len]
|
||||
salt = bin_payload[1+name_len:1+name_len+LENGTHS['salt']]
|
||||
return {
|
||||
'opcode': 'NAME_REGISTRATION',
|
||||
'name': bin_to_b40(name),
|
||||
'salt': hexlify(salt)
|
||||
'name': bin_to_b40(name)
|
||||
}
|
||||
|
||||
@@ -107,30 +107,24 @@ def run_cli():
|
||||
# ------------------------------------
|
||||
subparser = subparsers.add_parser(
|
||||
'preorder',
|
||||
help='<name> <consensushash> <privatekey> | preorder a name')
|
||||
help='<name> <privatekey> | preorder a name')
|
||||
subparser.add_argument(
|
||||
'name', type=str,
|
||||
help='the name that you want to preorder')
|
||||
subparser.add_argument(
|
||||
'consensushash', type=str,
|
||||
help='the current consensus hash of the nameset')
|
||||
subparser.add_argument(
|
||||
'privatekey', type=str,
|
||||
help='the privatekey of the Bitcoin address that will own the name')
|
||||
help='the private key of the Bitcoin address that will own the name')
|
||||
|
||||
# ------------------------------------
|
||||
subparser = subparsers.add_parser(
|
||||
'register',
|
||||
help='<name> <salt> <privatekey> | register/claim a name')
|
||||
help='<name> <privatekey> | register/claim a name')
|
||||
subparser.add_argument(
|
||||
'name', type=str,
|
||||
help='the name that you want to register/claim')
|
||||
subparser.add_argument(
|
||||
'salt', type=str,
|
||||
help='the salt')
|
||||
subparser.add_argument(
|
||||
'privatekey', type=str,
|
||||
help='the privatekey of the Bitcoin address that will own the name')
|
||||
help='the private key of the Bitcoin address that will own the name')
|
||||
|
||||
# ------------------------------------
|
||||
subparser = subparsers.add_parser(
|
||||
@@ -198,19 +192,16 @@ def run_cli():
|
||||
client = proxy.callRemote('getinfo')
|
||||
|
||||
elif args.action == 'ping':
|
||||
|
||||
client = proxy.callRemote('ping')
|
||||
|
||||
elif args.action == 'preorder':
|
||||
logger.debug('Preordering %s', args.name)
|
||||
|
||||
client = proxy.callRemote('preorder', args.name, args.consensushash,
|
||||
args.privatekey)
|
||||
client = proxy.callRemote('preorder', args.name, args.privatekey)
|
||||
|
||||
elif args.action == 'register':
|
||||
logger.debug('Registering %s', args.name)
|
||||
client = proxy.callRemote('register', args.name, args.salt,
|
||||
args.privatekey)
|
||||
client = proxy.callRemote('register', args.name, args.privatekey)
|
||||
|
||||
elif args.action == 'update':
|
||||
logger.debug('Updating %s', args.name)
|
||||
|
||||
@@ -84,6 +84,8 @@ class OpennamedRPC(jsonrpc.JSONRPC):
|
||||
return self.dht_server.get(key)
|
||||
|
||||
def jsonrpc_set(self, key, value):
|
||||
"""
|
||||
"""
|
||||
|
||||
reply = {}
|
||||
|
||||
@@ -104,6 +106,8 @@ class OpennamedRPC(jsonrpc.JSONRPC):
|
||||
return self.dht_server.set(key, value)
|
||||
|
||||
def jsonrpc_getinfo(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
info = bitcoind.getinfo()
|
||||
reply = {}
|
||||
@@ -111,29 +115,32 @@ class OpennamedRPC(jsonrpc.JSONRPC):
|
||||
reply['test'] = "hello"
|
||||
return reply
|
||||
|
||||
def jsonrpc_preorder(self, name, consensushash, privatekey):
|
||||
def jsonrpc_preorder(self, name, privatekey):
|
||||
""" Preorder a name
|
||||
"""
|
||||
|
||||
print str(privatekey)
|
||||
working_dir = get_working_dir()
|
||||
namespace_file = os.path.join(
|
||||
working_dir, config.OPENNAMED_NAMESPACE_FILE)
|
||||
db = NameDb(namespace_file)
|
||||
consensus_hash = db.consensus_hashes.get('current')
|
||||
|
||||
resp = preorder_name(
|
||||
name, consensushash, str(privatekey),
|
||||
blockchain_client=bitcoind_client,
|
||||
testset=True)
|
||||
name, consensus_hash, str(privatekey),
|
||||
blockchain_client=bitcoind_client, testset=True)
|
||||
|
||||
log.debug('preorder <%s, %s>' % (name, privatekey))
|
||||
|
||||
return resp
|
||||
|
||||
def jsonrpc_register(self, name, salt, privatekey):
|
||||
def jsonrpc_register(self, name, privatekey):
|
||||
""" Register a name
|
||||
"""
|
||||
|
||||
resp = register_name(name, salt, privatekey,
|
||||
resp = register_name(name, privatekey,
|
||||
blockchain_client=bitcoind_client, testset=True)
|
||||
|
||||
log.debug('register <%s, %s, %s>' % (name, salt, privatekey))
|
||||
log.debug('register <%s, %s, %s>' % (name, privatekey))
|
||||
|
||||
return resp
|
||||
|
||||
@@ -169,6 +176,8 @@ class OpennamedRPC(jsonrpc.JSONRPC):
|
||||
|
||||
|
||||
def refresh_index(first_block, last_block, initial_index=False):
|
||||
"""
|
||||
"""
|
||||
|
||||
from twisted.python import log as twisted_log
|
||||
|
||||
@@ -222,6 +231,8 @@ index_initialized = False
|
||||
|
||||
|
||||
def reindex_blockchain():
|
||||
"""
|
||||
"""
|
||||
|
||||
from twisted.python import log
|
||||
global old_block
|
||||
@@ -252,6 +263,8 @@ def reindex_blockchain():
|
||||
|
||||
|
||||
def get_working_dir():
|
||||
"""
|
||||
"""
|
||||
|
||||
from os.path import expanduser
|
||||
home = expanduser("~")
|
||||
@@ -266,6 +279,8 @@ def get_working_dir():
|
||||
|
||||
|
||||
def get_index_range(start_block=0):
|
||||
"""
|
||||
"""
|
||||
|
||||
from lib.config import START_BLOCK
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ blockchain_client = ChainComClient(
|
||||
|
||||
registration_example_1 = {
|
||||
'name': 'ryanshea',
|
||||
'salt': '83675d4f5c112b74e86af99b7ec83cec',
|
||||
'data': """{ }""",
|
||||
'recipient': '1DuckDmHTXVxSHC7UafaBiUZB81qYhKprF'
|
||||
}
|
||||
@@ -34,7 +33,7 @@ class NamePreorderTest(unittest.TestCase):
|
||||
consensus_hash128 = str(self.namedb.consensus_hashes['current'])
|
||||
resp = preorder_name(
|
||||
self.data['name'], consensus_hash128, SECRETS['private_keys'][0],
|
||||
salt=self.data['salt'], blockchain_client=blockchain_client,
|
||||
blockchain_client=blockchain_client,
|
||||
testset=True)
|
||||
print resp
|
||||
self.assertTrue('success' in resp)
|
||||
@@ -49,7 +48,7 @@ class NameRegistrationTest(unittest.TestCase):
|
||||
|
||||
def test_name_registration(self):
|
||||
resp = register_name(
|
||||
self.data['name'], self.data['salt'], SECRETS['private_keys'][0],
|
||||
self.data['name'], SECRETS['private_keys'][0],
|
||||
blockchain_client=blockchain_client, testset=True)
|
||||
print resp
|
||||
self.assertTrue('success' in resp)
|
||||
@@ -108,36 +107,6 @@ class MerkleRootTest(unittest.TestCase):
|
||||
self.assertEqual(merkle_root, self.merkle_root)
|
||||
|
||||
|
||||
"""class NameOperationSequenceTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
blockchain_client = ChainComClient(
|
||||
api_key_id=SECRETS['chain_api_id'],
|
||||
api_key_secret=SECRETS['chain_api_secret'])
|
||||
self.private_keys = SECRETS['private_keys']
|
||||
self.data = registration_example_1
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_name_preorder(self):
|
||||
resp = preorder_name(self.name, self.private_keys[0],
|
||||
blockchain_client=blockchain_client, testspace=True)
|
||||
self.salt = resp['salt']
|
||||
self.assertTrue('success' in resp)
|
||||
|
||||
resp = register_name(self.name, self.salt, self.private_keys[1],
|
||||
blockchain_client=blockchain_client, testspace=True)
|
||||
self.assertTrue('success' in resp)
|
||||
|
||||
resp = update_name(self.name, self.data, self.private_keys[2],
|
||||
blockchain_client=blockchain_client, testspace=True)
|
||||
self.assertTrue('success' in resp)
|
||||
|
||||
resp = transfer_name(self.name, self.recipient, self.private_keys[3],
|
||||
blockchain_client=blockchain_client, testspace=True)
|
||||
self.assertTrue('success' in resp)"""
|
||||
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(
|
||||
MerkleRootTest,
|
||||
|
||||
Reference in New Issue
Block a user