diff --git a/blockstore/blockstore_cli.py b/blockstore/blockstore_cli.py index 58df15ac2..3bac5d433 100644 --- a/blockstore/blockstore_cli.py +++ b/blockstore/blockstore_cli.py @@ -330,7 +330,7 @@ def run_cli(): name = args.name value = args.data - key = coinit.hex_hash160(value) + key = coinkit.hex_hash160(value) logger.debug("Signing hash '%s' by '%s'", key, name) client = proxy.callRemote('signdata', name, key, value, args.privatekey) diff --git a/blockstore/blockstored.py b/blockstore/blockstored.py index d52e16310..d89b092f7 100644 --- a/blockstore/blockstored.py +++ b/blockstore/blockstored.py @@ -49,8 +49,7 @@ CHAIN_COM_API_ID = None CHAIN_COM_API_SECRET = None from lib import preorder_name, register_name, update_name, \ - transfer_name - + transfer_name, namespace_define, namespace_begin, putdata_storage, rmdata_storage def signal_handler(signal, frame): """ Handle Ctrl+C for dht node @@ -216,7 +215,14 @@ class BlockstoredRPC(jsonrpc.JSONRPC): reply['error'] = "hash(value) doesn't match, not storing" return reply - return self.dht_server.set(key, value) + result = self.dht_server.set(key, value) + if result: + reply['key'] = hash + reply['result'] = True + else: + reply['result'] = False + + return reply def jsonrpc_signdata(self, name, key, value, privatekey): diff --git a/blockstore/lib/config.py b/blockstore/lib/config.py index 5f4a63b4b..bb9612204 100644 --- a/blockstore/lib/config.py +++ b/blockstore/lib/config.py @@ -11,7 +11,7 @@ from ConfigParser import SafeConfigParser import schemas DEBUG = True -TESTNET = True +TESTNET = False TESTSET = True """ constants @@ -187,7 +187,7 @@ def default_bitcoind_opts( config_file=None ): REINDEX_FREQUENCY = 10 # in seconds -FIRST_BLOCK_MAINNET = 343883 +FIRST_BLOCK_MAINNET = 367090 # 343883 FIRST_BLOCK_MAINNET_TESTSET = FIRST_BLOCK_MAINNET # FIRST_BLOCK_TESTNET = 343883 FIRST_BLOCK_TESTNET = 508800 @@ -264,9 +264,9 @@ MIN_OP_LENGTHS = { 'transfer': LENGTHS['namelen'] + LENGTHS['name_min'], 'data_put': LENGTHS['name_hash'] + LENGTHS['data_hash'], 'data_remove': LENGTHS['name_hash'] + LENGTHS['data_hash'], - 'namespace_define': LENGTHS['blockchain_id_namespace_id'] + LENGTHS['blockchain_id_namespace_id_len'], - 'namespace_begin': LENGTHS['blockchain_id_namespace_life'] + LENGTHS['blockchain_id_namespace_cost'] + \ - LENGTHS['blockchain_id_namespace_price_decay'] + LENGTHS['blockchain_id_namespace_id_len'] + LENGTHS['blockchain_id_namespace_id'] + 'namespace_begin': LENGTHS['blockchain_id_namespace_id_len'] + 1, + 'namespace_define': LENGTHS['blockchain_id_namespace_life'] + LENGTHS['blockchain_id_namespace_cost'] + \ + LENGTHS['blockchain_id_namespace_price_decay'] + LENGTHS['blockchain_id_namespace_id_len'] } OP_RETURN_MAX_SIZE = 40 diff --git a/blockstore/lib/hashing.py b/blockstore/lib/hashing.py index 84edb12c9..38be8062c 100644 --- a/blockstore/lib/hashing.py +++ b/blockstore/lib/hashing.py @@ -8,6 +8,7 @@ from .config import LENGTHS def hash_name(name, script_pubkey): + print "hash_name %s %s" % (name, script_pubkey) bin_name = b40_to_bin(name) name_and_pubkey = bin_name + unhexlify(script_pubkey) return hex_hash160(name_and_pubkey) diff --git a/blockstore/lib/nameset/build.py b/blockstore/lib/nameset/build.py index ad810b529..5ea250f96 100644 --- a/blockstore/lib/nameset/build.py +++ b/blockstore/lib/nameset/build.py @@ -5,7 +5,7 @@ from binascii import hexlify, unhexlify from .check import * from .commit import commit_registration, commit_update, commit_transfer, \ commit_renewal, commit_namespace, commit_putdata, commit_deletedata -from .log import log_preorder, log_registration, log_update, log_transfer, log_namespace_define, log_namespace_begin +from .log import log_preorder, log_registration, log_update, log_transfer, log_namespace_define, log_namespace_begin, log_putdata, log_deletedata from ..fees import is_mining_fee_sufficient from ..parsing import parse_blockstore_op @@ -105,10 +105,10 @@ def log_blockstore_op(db, blockstore_op, block_number): log_namespace_begin(db, blockstore_op, block_number) elif opcode == DATA_PUT: - log_data_put( db, blockstore_op, block_number ) + log_putdata( db, blockstore_op, block_number ) elif opcode == DATA_DELETE: - log_data_delete( db, blockstore_op, block_number ) + log_deletedata( db, blockstore_op, block_number ) def name_record_to_string(name, name_record): diff --git a/blockstore/lib/nameset/check.py b/blockstore/lib/nameset/check.py index b57fccd8b..b1bb4040b 100644 --- a/blockstore/lib/nameset/check.py +++ b/blockstore/lib/nameset/check.py @@ -1,6 +1,6 @@ from ..hashing import hash_name, hash256_trunc128 from ..config import BLOCKS_CONSENSUS_HASH_IS_VALID - +from .namedb import get_name_from_hash128 def name_registered(db, name): if name in db.name_records: @@ -21,21 +21,29 @@ def namespace_registered( db, namespace ): else: return False -def namespace_importing( db, namespace ): + +def namespace_importing_hash( db, namespace_id_hash ): """ Is a namespace in the process of being defined? """ - try: - namespace_id_hash = hash_name(namespace_id, sender_script_pubkey) - except ValueError: - return False - if namespace_id_hash in db.imports.keys(): return True else: return False +def namespace_importing( db, namespace, sender_script_pubkey ): + """ + Is a namespace in the process of being defined? + """ + try: + namespace_id_hash = hash_name(namespace, sender_script_pubkey) + except ValueError: + return False + + return namespace_importing_hash( db, namespace_id_hash ) + + def has_defined_namespace( db, namespace_id, sender_script_pubkey ): """ Has the given user (identified by the sender_script_pubkey) defined this namespace? @@ -63,11 +71,19 @@ def has_preordered_name(db, name, sender_script_pubkey): try: name_hash = hash_name(name, sender_script_pubkey) except ValueError: + raise return False if name_hash in db.preorders: + print "%s: %s" % (name_hash, db.preorders[name_hash]) if sender_script_pubkey == db.preorders[name_hash]['sender']: return True + else: + print "requester: %s; preorderer: %s" % (sender_script_pubkey, db.preorders[name_hash]['sender']) + return False + else: + print "%s not found" % name_hash + return False @@ -125,4 +141,6 @@ def is_storageop_from_registered_name( db, storageop ): if name_owner != storageop['sender']: return False - \ No newline at end of file + else: + return True + diff --git a/blockstore/lib/nameset/commit.py b/blockstore/lib/nameset/commit.py index 8fc578711..b30c88ca3 100644 --- a/blockstore/lib/nameset/commit.py +++ b/blockstore/lib/nameset/commit.py @@ -1,5 +1,5 @@ from ..hashing import hash_name, hash256_trunc128 -from .namedb import get_name_from_hash128 +from .namedb import get_name_from_hash128, put_signed_data def remove_preorder(db, name, script_pubkey): try: @@ -95,7 +95,7 @@ def commit_putdata( db, storageop ): name_hash = storageop['name_hash'] data_hash = storageop['data_hash'] - name = get_name_from_hash128( name_hash ) + name = get_name_from_hash128( name_hash, db ) put_signed_data( name, data_hash, db ) @@ -107,6 +107,6 @@ def commit_deletedata( db, storageop): name_hash = storageop['name_hash'] data_hash = storageop['data_hash'] - name = get_name_from_hash128( name_hash ) + name = get_name_from_hash128( name_hash, db ) remove_signed_data( name, data_hash, db ) diff --git a/blockstore/lib/nameset/log.py b/blockstore/lib/nameset/log.py index 3e1516c96..1342a42f7 100644 --- a/blockstore/lib/nameset/log.py +++ b/blockstore/lib/nameset/log.py @@ -1,11 +1,11 @@ from .check import name_not_registered, has_preordered_name, \ is_name_owner, is_preorder_hash_unique, name_registered, \ is_consensus_hash_valid, is_storageop_from_registered_name, \ - namespace_importing + namespace_importing, namespace_importing_hash, namespace_registered from ..fees import is_mining_fee_sufficient from .namedb import get_name_from_hash128, put_signed_data, get_namespace_from_name from ..hashing import hash256_trunc128, hash_name - +from collections import defaultdict def log_import( db, nameop, block_number ): """ @@ -28,21 +28,26 @@ def log_registration(db, nameop, block_number): namespace_id = get_namespace_from_name( name ) # part of an import? - if namespace_importing( db, namespace_id ): + if namespace_importing( db, namespace_id, nameop['sender'] ): # yup--remember which block, to avoid conflicts log_import( db, nameop, block_number ) else: - namespace = get_namespace( db, namespace_id ) + # TODO: look up namespace, and make sure the registration fee is sufficient + # namespace = get_namespace( db, namespace_id ) + + print "" + print "name: %s, available? %s, preordered by %s? %s, fee? %s" % (name, name_not_registered(db, name), nameop['sender'], has_preordered_name(db, name, nameop['sender']), is_mining_fee_sufficient(name, nameop['fee'], 0, 0)) + print "" # check if this registration is a valid one - if (name_not_registered(db, name) and has_preordered_name(db, name, nameop['sender']) and is_mining_fee_sufficient(name, nameop['fee'])): + if (name_not_registered(db, name) and has_preordered_name(db, name, nameop['sender']) and is_mining_fee_sufficient(name, nameop['fee'], 0, 0)): # we're good - log the registration! db.pending_registrations[name].append(nameop) # check if this registration is actually a valid renewal - if (name_registered(db, name) and is_name_owner(db, name, nameop['sender']) and is_mining_fee_sufficient(name, nameop['fee'])): + if (name_registered(db, name) and is_name_owner(db, name, nameop['sender']) and is_mining_fee_sufficient(name, nameop['fee'], 0, 0)): # we're good - log the renewal! db.pending_renewals[name].append(nameop) @@ -62,7 +67,7 @@ def log_update(db, nameop, block_number): namespace_id = get_namespace_from_name( name ) # part of an import? - if namespace_importing( db, namespace_id ): + if namespace_importing( db, namespace_id, nameop['sender'] ): # yup--remember which block, to avoid conflicts log_import( db, nameop, block_number ) @@ -80,7 +85,7 @@ def log_transfer(db, nameop, block_number): namespace_id = get_namespace_from_name( name ) # part of an import? - if namespace_importing( db, namespace_id ): + if namespace_importing( db, namespace_id, nameop['sender'] ): # yup--remember which block, to avoid conflicts log_import( db, nameop, block_number ) @@ -116,9 +121,11 @@ def log_namespace_define(db, nameop, block_number): namespace_id_hash = nameop['namespace_id_hash'] - if not namespace_registered( db, namespace_id_hash ) and not namespace_importing( db, namespace_id_hash ): + if not namespace_registered( db, namespace_id_hash ) and not namespace_importing_hash( db, namespace_id_hash ): # can begin the import - db.imports[ namespace_id_hash ] = defaultdict(list) + if not db.imports.has_key( namespace_id_hash ): + db.imports[ namespace_id_hash ] = [] + db.imports[ namespace_id_hash ].append( nameop ) @@ -130,7 +137,7 @@ def log_namespace_begin(db, nameop, block_number): namespace_id = nameop['namespace_id'] - if not namespace_registered( db, namespace_id ) and namespace_importing( db, namespace_id ) and has_defined_namespace( db, namespace_id, nameop['sender'] ): + if not namespace_registered( db, namespace_id ) and namespace_importing( db, namespace_id, nameop['sender'] ) and has_defined_namespace( db, namespace_id, nameop['sender'] ): # can merge on next commit. this namespace is no longer importing. db.pending_imports[ namespace_id ] = db.imports[ namespace_id_hash ] del db.imports[ namespace_id_hash ] @@ -144,13 +151,17 @@ def log_putdata( db, storageop, block_number ): data_hash = storageop['data_hash'] - if is_storageop_from_registered_name( storageop ): + if is_storageop_from_registered_name( db, storageop ): name_hash = storageop['name_hash'] - name = get_name_from_hash128( name_hash ) + name = get_name_from_hash128( name_hash, db ) if name is not None: - db.pending_data_puts[name].append( data_hash ) + db.pending_data_puts[name].append( storageop ) + else: + print "Unrecognized name_hash '%s'" % name_hash + else: + print "Not from registered name: %s" % storageop def log_deletedata( db, storageop, block_number ): @@ -161,7 +172,7 @@ def log_deletedata( db, storageop, block_number ): data_hash = storageop['data_hash'] - if is_storageop_from_registered_name( storageop ): + if is_storageop_from_registered_name( db, storageop ): name_hash = storageop['name_hash'] name = get_name_from_hash128( name_hash ) @@ -170,4 +181,4 @@ def log_deletedata( db, storageop, block_number ): # user owns this data db.pending_data_deletes[name].append( data_hash ) - \ No newline at end of file + diff --git a/blockstore/lib/nameset/namedb.py b/blockstore/lib/nameset/namedb.py index 915ed8b73..1d207d55b 100644 --- a/blockstore/lib/nameset/namedb.py +++ b/blockstore/lib/nameset/namedb.py @@ -168,6 +168,8 @@ def put_signed_data( owner_name, data_hash, db ): NOTE: this doesn't verify that the name is valid; the caller must do so. """ + print "user %s owns %s" % (owner_name, data_hash) + if db.signed_data.has_key( owner_name ): db.signed_data[owner_name].update( set([data_hash]) ) @@ -181,12 +183,15 @@ def verify_signed_data( owner_name, data_hash, db ): Return True if so; False if not """ - + + debug_str = "" if not db.signed_data.has_key( owner_name ): # user has written nothing - return False + debug_str = "user %s does not own anything" % owner_name + return {"debug": debug_str, "result": False} - return data_hash in db.signed_data[ owner_name ] + debug_str = "user %s owns %s? %s" % (owner_name, data_hash, data_hash in db.signed_data[owner_name]) + return {"debug": debug_str, "result": data_hash in db.signed_data[ owner_name ] } def delete_signed_data( owner_name, data_hash, db ): diff --git a/blockstore/lib/operations/namespacebegin.py b/blockstore/lib/operations/namespacebegin.py index 721254c4b..b3a694ea5 100644 --- a/blockstore/lib/operations/namespacebegin.py +++ b/blockstore/lib/operations/namespacebegin.py @@ -15,9 +15,9 @@ def build( namespace_id, testset=False ): Format: - 0 2 3 4 23 - |-----|--|--|-------------| - magic op len ns_id + 0 2 3 4 5 24 + |-----|--|--|--|-----------| + magic op len . ns_id """ # sanity check @@ -27,7 +27,7 @@ def build( namespace_id, testset=False ): if len(namespace_id) == 0 or len(namespace_id) > LENGTHS['blockchain_id_namespace_id']: raise Exception("Invalid namespace ID '%s (expected length between 1 and %s)" % (namespace_id, LENGTHS['blockchain_id_namespace_id'])) - readable_script = "NAMESPACE_BEGIN %i %s" % (len(namespace_id), namespace_id) + readable_script = "NAMESPACE_BEGIN %i %s" % (len(namespace_id), hexlify("." + namespace_id)) hex_script = blockstore_script_to_hex(readable_script) packaged_script = add_magic_bytes(hex_script, testset=testset) @@ -49,9 +49,9 @@ def parse( bin_payload ): """ namespace_id_len = ord( bin_payload[0:LENGTHS['blockchain_id_namespace_id_len']] ) - namespace_id = bin_payload[ LENGTHS['blockchain_id_namespace_id_len']:LENGTHS['blockchain_id_namespace_id_len'] + namespace_id_len ] - + namespace_id = bin_payload[ LENGTHS['blockchain_id_namespace_id_len'] + 1:LENGTHS['blockchain_id_namespace_id_len'] + namespace_id_len + 1 ] # skip the '.' + return { 'opcode': 'NAMESPACE_BEGIN', 'namespace_id': namespace_id - } \ No newline at end of file + } diff --git a/blockstore/lib/operations/namespacedefine.py b/blockstore/lib/operations/namespacedefine.py index 7d906f543..40e426125 100644 --- a/blockstore/lib/operations/namespacedefine.py +++ b/blockstore/lib/operations/namespacedefine.py @@ -5,7 +5,7 @@ from binascii import hexlify, unhexlify from ..b40 import b40_to_hex, bin_to_b40, is_b40 from ..config import * from ..scripts import blockstore_script_to_hex, add_magic_bytes, get_script_pubkey - +from ..hashing import hash_name def namespace_decay_to_float( namespace_decay_fixedpoint ): """ @@ -128,19 +128,19 @@ def parse( bin_payload ): namespace_id_len = None namespace_id = None - life = ord( bin_payload[off:off+LENGTHS['blockchain_id_namespace_life']] ) + life = int( hexlify(bin_payload[off:off+LENGTHS['blockchain_id_namespace_life']]), 16 ) off += LENGTHS['blockchain_id_namespace_life'] - cost = ord( bin_payload[off:off+LENGTHS['blockchain_id_namespace_cost']] ) + cost = int( hexlify(bin_payload[off:off+LENGTHS['blockchain_id_namespace_cost']]), 16 ) off += LENGTHS['blockchain_id_namespace_cost'] - decay_fixedpoint = ord( bin_payload[off:off+LENGTHS['blockchain_id_namespace_price_decay']] ) + decay_fixedpoint = int( hexlify(bin_payload[off:off+LENGTHS['blockchain_id_namespace_price_decay']]), 16 ) off += LENGTHS['blockchain_id_namespace_price_decay'] - namespace_id_len = ord( bin_payload[off:off+LENGTHS['blockchain_id_namespace_id_len']] ) + namespace_id_len = int( hexlify(bin_payload[off:off+LENGTHS['blockchain_id_namespace_id_len']]), 16 ) off += LENGTHS['blockchain_id_namespace_id_len'] @@ -151,6 +151,6 @@ def parse( bin_payload ): 'lifetime': life, 'cost': cost, 'price_decay': namespace_decay_to_float( decay_fixedpoint ), - 'namespace_id_hash': namespace_id_hash + 'namespace_id_hash': hexlify( namespace_id_hash ) } diff --git a/blockstore/lib/operations/preorder.py b/blockstore/lib/operations/preorder.py index e12fce2b7..be9e65779 100644 --- a/blockstore/lib/operations/preorder.py +++ b/blockstore/lib/operations/preorder.py @@ -67,6 +67,6 @@ def parse(bin_payload): return { 'opcode': 'NAME_PREORDER', - 'preorder_name_hash': hexlify(name_hash), - 'consensus_hash': hexlify(consensus_hash) + 'preorder_name_hash': name_hash, + 'consensus_hash': consensus_hash } diff --git a/blockstore/lib/operations/register.py b/blockstore/lib/operations/register.py index 4081f40df..707ce8bdf 100644 --- a/blockstore/lib/operations/register.py +++ b/blockstore/lib/operations/register.py @@ -49,14 +49,14 @@ def parse(bin_payload): will not be present in bin_payload. """ - fqn = unhexlify( bin_payload ) - scheme = fqn[0:(len(NAME_SCHEME) - 3)] # excludes 'id://' - - if scheme != NAME_SCHEME[3:]: + fqn = bin_payload + scheme = fqn[0:len(NAME_SCHEME)] # exclude scheme + + if scheme != NAME_SCHEME: raise Exception("Invalid bin payload: does not start with '%s'" % NAME_SCHEME) return { 'opcode': 'NAME_REGISTRATION', - 'name': fqn[(len(NAME_SCHEME) - 3):] # skip the '//', since that's what bin_payload will always start with + 'name': fqn[len(NAME_SCHEME):] # skip the scheme } diff --git a/blockstore/lib/parsing.py b/blockstore/lib/parsing.py index 89b1c824e..53bb4bcdd 100644 --- a/blockstore/lib/parsing.py +++ b/blockstore/lib/parsing.py @@ -60,31 +60,40 @@ def parse_blockstore_op_data(data): else: # this is a name registration opcode = NAME_REGISTRATION + payload = bin_data op = None if opcode == NAME_PREORDER and len(payload) >= MIN_OP_LENGTHS['preorder']: + print "Parse NAME_PREORDER: %s" % data op = parse_preorder(payload) elif (opcode == NAME_REGISTRATION and len(payload) >= MIN_OP_LENGTHS['registration']): + print "Parse NAME_REGISTRATION: %s" % data op = parse_registration(payload) elif opcode == NAME_UPDATE and len(payload) >= MIN_OP_LENGTHS['update']: + print "Parse NAME_UPDATE: %s" % data op = parse_update(payload) elif (opcode == NAME_TRANSFER and len(payload) >= MIN_OP_LENGTHS['transfer']): + print "Parse NAME_TRANSFER: %s" % data op = parse_transfer(payload) elif opcode == NAMESPACE_DEFINE and len(payload) >= MIN_OP_LENGTHS['namespace_define']: + print "Parse NAMESPACE_DEFINE: %s" % data op = parse_namespacedefine( payload ) elif opcode == NAMESPACE_BEGIN and len(payload) >= MIN_OP_LENGTHS['namespace_begin']: + print "Parse NAMESPACE_BEGIN: %s" % data op = parse_namespacebegin( payload ) elif opcode == DATA_PUT and len(payload) >= MIN_OP_LENGTHS['data_put']: + print "Parse DATA_PUT: %s" % data op = parse_putdata( payload ) elif opcode == DATA_REMOVE and len(payload) >= MIN_OP_LENGTHS['data_remove']: + print "Parse DATA_REMOVE: %s" % data op = parse_rmdata( payload ) return op diff --git a/blockstore/lib/scripts.py b/blockstore/lib/scripts.py index eca112846..128d8fe37 100644 --- a/blockstore/lib/scripts.py +++ b/blockstore/lib/scripts.py @@ -50,6 +50,7 @@ def data_script_to_hex(script): # generate a pay-to-pubkeyhash script from a private key. def get_script_pubkey( private_key ): - hash160 = BitcoinPrivateKey(private_key).public_key().hash160() + hash160 = BitcoinPrivateKey(private_key).public_key(compressed=True).hash160() script_pubkey = script_to_hex( 'OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG' % hash160) - return script_pubkey \ No newline at end of file + print "script_pubkey of %s is %s" % (private_key, script_pubkey) + return script_pubkey