diff --git a/electrumx/lib/coins.py b/electrumx/lib/coins.py index 9cbc98e..9721759 100644 --- a/electrumx/lib/coins.py +++ b/electrumx/lib/coins.py @@ -427,6 +427,58 @@ class NameMixin(object): return named_values, address_script +class NameIndexMixin(NameMixin): + """Shared definitions for coins that have a name index + + This class defines common functions and logic for coins that have + a name index in addition to the index by address / script.""" + + BLOCK_PROCESSOR = block_proc.NameIndexBlockProcessor + + @classmethod + def build_name_index_script(cls, name): + """Returns the script by which names are indexed""" + + from electrumx.lib.script import Script + + res = bytearray() + res.append(cls.OP_NAME_UPDATE) + res.extend(Script.push_data(name)) + res.extend(Script.push_data(bytes([]))) + res.append(OpCodes.OP_2DROP) + res.append(OpCodes.OP_DROP) + res.append(OpCodes.OP_RETURN) + + return bytes(res) + + @classmethod + def split_name_script(cls, script): + named_values, address_script = cls.interpret_name_prefix(script, cls.NAME_OPERATIONS) + if named_values is None or "name" not in named_values: + return None, address_script + + name_index_script = cls.build_name_index_script(named_values["name"][1]) + return name_index_script, address_script + + @classmethod + def hashX_from_script(cls, script): + _, address_script = cls.split_name_script(script) + return super().hashX_from_script(address_script) + + @classmethod + def address_from_script(cls, script): + _, address_script = cls.split_name_script(script) + return super().address_from_script(address_script) + + @classmethod + def name_hashX_from_script(cls, script): + name_index_script, _ = cls.split_name_script(script) + if name_index_script is None: + return None + + return super().hashX_from_script(name_index_script) + + class HOdlcoin(Coin): NAME = "HOdlcoin" SHORTNAME = "HODLC" @@ -959,7 +1011,7 @@ class Unitus(Coin): # Source: namecoin.org -class Namecoin(NameMixin, AuxPowMixin, Coin): +class Namecoin(NameIndexMixin, AuxPowMixin, Coin): NAME = "Namecoin" SHORTNAME = "NMC" NET = "mainnet" @@ -979,74 +1031,24 @@ class Namecoin(NameMixin, AuxPowMixin, Coin): 'luggscoqbymhvnkp.onion t82', 'ulrichard.ch s50006 t50005', ] - BLOCK_PROCESSOR = block_proc.NamecoinBlockProcessor + BLOCK_PROCESSOR = block_proc.NameIndexBlockProcessor # Name opcodes OP_NAME_NEW = OpCodes.OP_1 OP_NAME_FIRSTUPDATE = OpCodes.OP_2 OP_NAME_UPDATE = OpCodes.OP_3 - @classmethod - def build_name_index_script(cls, name): - """Returns the normalised script by which names are indexed""" - - from electrumx.lib.script import Script - - normalized_name_op_script = bytearray() - normalized_name_op_script.append(cls.OP_NAME_UPDATE) - normalized_name_op_script.extend(Script.push_data(name)) - normalized_name_op_script.extend(Script.push_data(bytes([]))) - normalized_name_op_script.append(OpCodes.OP_2DROP) - normalized_name_op_script.append(OpCodes.OP_DROP) - normalized_name_op_script.append(OpCodes.OP_RETURN) - - return bytes(normalized_name_op_script) - - @classmethod - def split_name_script(cls, script): - from electrumx.lib.script import Script - - # Opcode sequences for name operations - NAME_NEW_OPS = [cls.OP_NAME_NEW, -1, OpCodes.OP_2DROP] - NAME_FIRSTUPDATE_OPS = [cls.OP_NAME_FIRSTUPDATE, "name", -1, -1, - OpCodes.OP_2DROP, OpCodes.OP_2DROP] - NAME_UPDATE_OPS = [cls.OP_NAME_UPDATE, "name", -1, OpCodes.OP_2DROP, - OpCodes.OP_DROP] - - ops = [ - NAME_NEW_OPS, - NAME_FIRSTUPDATE_OPS, - NAME_UPDATE_OPS, - ] - - named_values, address_script = cls.interpret_name_prefix(script, ops) - - if named_values is None or "name" not in named_values: - return None, address_script - - normalized_name_op_script = cls.build_name_index_script(named_values["name"][1]) - return bytes(normalized_name_op_script), address_script - - @classmethod - def hashX_from_script(cls, script): - _name_op_script, address_script = cls.split_name_script(script) - - return super().hashX_from_script(address_script) - - @classmethod - def address_from_script(cls, script): - _name_op_script, address_script = cls.split_name_script(script) - - return super().address_from_script(address_script) - - @classmethod - def name_hashX_from_script(cls, script): - name_op_script, _address_script = cls.split_name_script(script) - - if name_op_script is None: - return None - - return super().hashX_from_script(name_op_script) + # Valid name prefixes. + NAME_NEW_OPS = [OP_NAME_NEW, -1, OpCodes.OP_2DROP] + NAME_FIRSTUPDATE_OPS = [OP_NAME_FIRSTUPDATE, "name", -1, -1, + OpCodes.OP_2DROP, OpCodes.OP_2DROP] + NAME_UPDATE_OPS = [OP_NAME_UPDATE, "name", -1, OpCodes.OP_2DROP, + OpCodes.OP_DROP] + NAME_OPERATIONS = [ + NAME_NEW_OPS, + NAME_FIRSTUPDATE_OPS, + NAME_UPDATE_OPS, + ] class NamecoinTestnet(Namecoin): @@ -3181,7 +3183,7 @@ class CPUchain(Coin): return cpupower.getPoWHash(header) -class Xaya(AuxPowMixin, Coin): +class Xaya(NameIndexMixin, AuxPowMixin, Coin): NAME = "Xaya" SHORTNAME = "CHI" NET = "mainnet" @@ -3203,6 +3205,20 @@ class Xaya(AuxPowMixin, Coin): 'xaya.domob.eu s50002', ] + # Op-codes for name operations + OP_NAME_REGISTER = OpCodes.OP_1 + OP_NAME_UPDATE = OpCodes.OP_2 + + # Valid name prefixes. + NAME_REGISTER_OPS = [OP_NAME_REGISTER, "name", -1, OpCodes.OP_2DROP, + OpCodes.OP_DROP] + NAME_UPDATE_OPS = [OP_NAME_UPDATE, "name", -1, OpCodes.OP_2DROP, + OpCodes.OP_DROP] + NAME_OPERATIONS = [ + NAME_REGISTER_OPS, + NAME_UPDATE_OPS, + ] + @classmethod def genesis_block(cls, block): super().genesis_block(block) diff --git a/electrumx/server/block_processor.py b/electrumx/server/block_processor.py index 883fc5f..fc98400 100644 --- a/electrumx/server/block_processor.py +++ b/electrumx/server/block_processor.py @@ -690,7 +690,7 @@ class DecredBlockProcessor(BlockProcessor): return start, count -class NamecoinBlockProcessor(BlockProcessor): +class NameIndexBlockProcessor(BlockProcessor): def advance_txs(self, txs): result = super().advance_txs(txs) diff --git a/tests/transactions/xaya_mainnet_namereg_a32f38.json b/tests/transactions/xaya_mainnet_namereg_a32f38.json new file mode 100644 index 0000000..22842bc --- /dev/null +++ b/tests/transactions/xaya_mainnet_namereg_a32f38.json @@ -0,0 +1,60 @@ +{ + "txid": "a32f38a463b75f2cb9955f5660063e7888f9120b40f27312b65e53fad6a226fd", + "hash": "a32f38a463b75f2cb9955f5660063e7888f9120b40f27312b65e53fad6a226fd", + "version": 2, + "size": 240, + "vsize": 240, + "weight": 960, + "locktime": 0, + "vin": [ + { + "txid": "c87eb7b9c71146a18f8ebaea93b74bfeb4795b265f151ba5a1e62ef32017bc34", + "vout": 0, + "scriptSig": { + "asm": "3045022100df2c9fdfa19e145a3d1f3b995e2925e6270f02dd13a9d5e79edc0bf7841517d40220722d8c694a21890bb24b82530f7e553371b9123d1e0e8c1ad818fe87c53e3cbb[ALL] 03a2bfae3cc2b43c7ac5e8ae402e1552b9edca7a2ff73ac1950ca52dae73791e95", + "hex": "483045022100df2c9fdfa19e145a3d1f3b995e2925e6270f02dd13a9d5e79edc0bf7841517d40220722d8c694a21890bb24b82530f7e553371b9123d1e0e8c1ad818fe87c53e3cbb012103a2bfae3cc2b43c7ac5e8ae402e1552b9edca7a2ff73ac1950ca52dae73791e95" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 1996928100, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 5026b54aec9036aaf02473481356acb3fe45846a OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9145026b54aec9036aaf02473481356acb3fe45846a88ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "CPmgzsvaWeSNvXd5CNfzSLnX2ymjJ7jwtw" + ] + } + }, + { + "value": 1000000, + "n": 1, + "scriptPubKey": { + "nameOp": { + "op": "name_register", + "name": "p/domob", + "name_encoding": "utf8", + "value": "{}", + "value_encoding": "ascii" + }, + "asm": "OP_NAME_REGISTER 702f646f6d6f62 32123 OP_2DROP OP_DROP OP_DUP OP_HASH160 eed2f5ecba300e6137c3a966d60cab012b490e01 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "5107702f646f6d6f62027b7d6d7576a914eed2f5ecba300e6137c3a966d60cab012b490e0188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "CeEg7VvAJ6rtz7MQ9sbkmEEb4zxRbSU4JT" + ] + } + } + ], + "hex": "020000000134bc1720f32ee6a1a51b155f265b79b4fe4bb793eaba8e8fa14611c7b9b77ec8000000006b483045022100df2c9fdfa19e145a3d1f3b995e2925e6270f02dd13a9d5e79edc0bf7841517d40220722d8c694a21890bb24b82530f7e553371b9123d1e0e8c1ad818fe87c53e3cbb012103a2bfae3cc2b43c7ac5e8ae402e1552b9edca7a2ff73ac1950ca52dae73791e95feffffff0264b40677000000001976a9145026b54aec9036aaf02473481356acb3fe45846a88ac40420f0000000000275107702f646f6d6f62027b7d6d7576a914eed2f5ecba300e6137c3a966d60cab012b490e0188ac00000000", + "blockhash": "1efbbbe72b0198a68bd3a9f5d349f4bcb5d87c660262a6c6731c37b1cb61a73e", + "confirmations": 1032707, + "time": 1531484387, + "blocktime": 1531484387 +} diff --git a/tests/transactions/xaya_mainnet_nameupd_83747d.json b/tests/transactions/xaya_mainnet_nameupd_83747d.json new file mode 100644 index 0000000..a0b5a99 --- /dev/null +++ b/tests/transactions/xaya_mainnet_nameupd_83747d.json @@ -0,0 +1,69 @@ +{ + "txid": "83747d1e69e264644f425bc2dae3bedca6d72274a0f2f82b00d9a0a70714c2be", + "hash": "83747d1e69e264644f425bc2dae3bedca6d72274a0f2f82b00d9a0a70714c2be", + "version": 2, + "size": 413, + "vsize": 413, + "weight": 1652, + "locktime": 244772, + "vin": [ + { + "txid": "59d8a63955615b49b550ca9207ae9c5853898370a37efe8fcb4cfbff7eba989e", + "vout": 0, + "scriptSig": { + "asm": "304402202f16982264f61a1bdd08cf5f5aa620fd761419416aceaf65226ba74a932e8ea50220520d2a8755da0f85c257afeb841fab9692807d177fd4693e0697308f658940ed[ALL] 02d9ce309aa25d552cc1e6e2557e4b91b8ad9d055ff74fc4241e6b5b1039792eae", + "hex": "47304402202f16982264f61a1bdd08cf5f5aa620fd761419416aceaf65226ba74a932e8ea50220520d2a8755da0f85c257afeb841fab9692807d177fd4693e0697308f658940ed012102d9ce309aa25d552cc1e6e2557e4b91b8ad9d055ff74fc4241e6b5b1039792eae" + }, + "sequence": 4294967294 + }, + { + "txid": "a32f38a463b75f2cb9955f5660063e7888f9120b40f27312b65e53fad6a226fd", + "vout": 1, + "scriptSig": { + "asm": "3044022030710158479236b1e8da22cbe5710f0b1b1210fdfa3c68dcb955af8137340db8022064f8f2d2c4047f51f0e62ebe2ee2aac7d3eb574f57f497ad828fb2381234d81e[ALL] 03611ff32dd36a49b75873dc3770c1e5f6a83ea8a4f56fa1fd08400b7686eb4c21", + "hex": "473044022030710158479236b1e8da22cbe5710f0b1b1210fdfa3c68dcb955af8137340db8022064f8f2d2c4047f51f0e62ebe2ee2aac7d3eb574f57f497ad828fb2381234d81e012103611ff32dd36a49b75873dc3770c1e5f6a83ea8a4f56fa1fd08400b7686eb4c21" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 473277800, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 13f261c11e7471063893a4821331a1bd4496f5fb OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a91413f261c11e7471063893a4821331a1bd4496f5fb88ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "CJHMmfxKEypZd9oF5Ui9cSgWD7eaUC6cGT" + ] + } + }, + { + "value": 1000000, + "n": 1, + "scriptPubKey": { + "nameOp": { + "op": "name_update", + "name": "p/domob", + "name_encoding": "utf8", + "value": "{\"g\":{\"mv\":{\"d\":\"u\",\"n\":10}}}", + "value_encoding": "ascii" + }, + "asm": "OP_NAME_UPDATE 702f646f6d6f62 7b2267223a7b226d76223a7b2264223a2275222c226e223a31307d7d7d OP_2DROP OP_DROP OP_DUP OP_HASH160 9375d04e6c8a332e0dd06dff3e9c037ac80d31a0 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "5207702f646f6d6f621d7b2267223a7b226d76223a7b2264223a2275222c226e223a31307d7d7d6d7576a9149375d04e6c8a332e0dd06dff3e9c037ac80d31a088ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "CVub35ZeaqJajwUxr7ib3sYBfQg19AhKRs" + ] + } + } + ], + "hex": "02000000029e98ba7efffb4ccb8ffe7ea370838953589cae0792ca50b5495b615539a6d859000000006a47304402202f16982264f61a1bdd08cf5f5aa620fd761419416aceaf65226ba74a932e8ea50220520d2a8755da0f85c257afeb841fab9692807d177fd4693e0697308f658940ed012102d9ce309aa25d552cc1e6e2557e4b91b8ad9d055ff74fc4241e6b5b1039792eaefefffffffd26a2d6fa535eb61273f2400b12f988783e0660565f95b92c5fb763a4382fa3010000006a473044022030710158479236b1e8da22cbe5710f0b1b1210fdfa3c68dcb955af8137340db8022064f8f2d2c4047f51f0e62ebe2ee2aac7d3eb574f57f497ad828fb2381234d81e012103611ff32dd36a49b75873dc3770c1e5f6a83ea8a4f56fa1fd08400b7686eb4c21feffffff0268a5351c000000001976a91413f261c11e7471063893a4821331a1bd4496f5fb88ac40420f0000000000425207702f646f6d6f621d7b2267223a7b226d76223a7b2264223a2275222c226e223a31307d7d7d6d7576a9149375d04e6c8a332e0dd06dff3e9c037ac80d31a088ac24bc0300", + "blockhash": "6d8071aa2e91e13004d9cc185e3a51a1975f33f190b171ce3d638ae17fdb1154", + "confirmations": 787951, + "time": 1539182355, + "blocktime": 1539182355 +}