diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..615aafb03 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "/usr/bin/python3" +} \ No newline at end of file diff --git a/docs/HOWTO.rst b/docs/HOWTO.rst index 404493e20..a76f7c237 100644 --- a/docs/HOWTO.rst +++ b/docs/HOWTO.rst @@ -33,10 +33,10 @@ You **must** to be running a non-pruning bitcoin daemon with:: txindex=1 set in its configuration file. If you have an existing installation -of bitcoind and have not previously set this you will need to reindex +of dnotesd and have not previously set this you will need to reindex the blockchain with:: - bitcoind -reindex + dnotesd -reindex which can take some time. @@ -260,11 +260,11 @@ from heights 363,000 to 378,000 is the most sluggish:: *Machine A*: a low-spec 2011 1.6GHz AMD E-350 dual-core fanless CPU, 8GB RAM and a DragonFlyBSD UFS fileystem on an SSD. It requests -blocks over the LAN from a bitcoind on machine B. :envvar:`DB_CACHE` +blocks over the LAN from a dnotesd on machine B. :envvar:`DB_CACHE` the default of 1,200. LevelDB. *Machine B*: a late 2012 iMac running Sierra 10.12.2, 2.9GHz quad-core -Intel i5 CPU with an HDD and 24GB RAM. Running bitcoind on the same +Intel i5 CPU with an HDD and 24GB RAM. Running dnotesd on the same machine. :envvar:`DB_CACHE` set to 1,800. LevelDB. For chains other than bitcoin-mainnet sychronization should be much diff --git a/docs/architecture.rst b/docs/architecture.rst index 6ac192d91..9b4d54448 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -31,13 +31,13 @@ Handles JSON Electrum client connections over TCP or SSL. One instance per client session. Should be the only component concerned with the details of the Electrum wire protocol. -Not started until the Block Processor has caught up with bitcoind. +Not started until the Block Processor has caught up with dnotesd. Daemon ------ -Encapsulates the RPC wire protocol with bitcoind for the whole server. -Transparently handles temporary bitcoind connection errors, and fails +Encapsulates the RPC wire protocol with dnotesd for the whole server. +Transparently handles temporary dnotesd connection errors, and fails over if necessary. Notifies the Mempool when the list of mempool transaction hashes is @@ -62,14 +62,14 @@ Prefetcher ---------- Cooperates with the Block Processor to asynchronously prefetch blocks -from bitcoind. Once it has caught up it additionally asks the Daemon -to refresh its view of bitcoind's mempool transaction hashes. Serves +from dnotesd. Once it has caught up it additionally asks the Daemon +to refresh its view of dnotesd's mempool transaction hashes. Serves blocks to the Block Processor via a queue. Mempool ------- -Handles all the details of maintaining a representation of bitcoind's +Handles all the details of maintaining a representation of dnotesd's mempool state. Obtains the list of current mempool transaction hashes from the Daemon when notified by the Prefetcher. diff --git a/lib/coins.py b/lib/coins.py index 4a44afb32..9b6791ba2 100644 --- a/lib/coins.py +++ b/lib/coins.py @@ -1613,3 +1613,52 @@ def header_hash(cls, header): ''' import x11_hash return x11_hash.getPoWHash(header) + +class DNotes(Coin): + STATIC_BLOCK_HEADERS = False + NAME = "DNotes" + SHORTNAME = "NOTE" + NET = "mainnet" + TX_COUNT = 121000 + TX_COUNT_HEIGHT = 61218 + TX_PER_BLOCK = 2 + DAEMON = daemon.DNotesDaemon + P2PKH_VERBYTE = bytes.fromhex("3F") + P2SH_VERBYTES = [bytes.fromhex("7D")] + GENESIS_HASH = ('00001123368370feb0997f471423e444' + '5be205b9947e7053c762886317274d2a') + DESERIALIZER = lib_tx.DeserializerDNotes + PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'} + PEERS = [ + ] + ESTIMATE_FEE = 0.005 + RELAY_FEE = 0.005 + + @classmethod + def block_header(cls, block, height): + '''Return the block header bytes''' + deserializer = cls.DESERIALIZER(block) + return deserializer.read_header(height, cls.BASIC_HEADER_SIZE) + + @classmethod + def header_hash(cls, header): + version, = struct.unpack(' 6: + return double_sha256(header[:80]) + else: + import x13_hash + return x13_hash.getPoWHash(header[:80]) + +class DNotesTestnet(DNotes): + NAME = "DNotes" + SHORTNAME = "NOTE" + NET = "testnet" + TX_COUNT = 11684 + TX_COUNT_HEIGHT = 5819 + TX_PER_BLOCK = 2 + P2PKH_VERBYTE = bytes.fromhex("41") + P2SH_VERBYTES = [bytes.fromhex("C4")] + GENESIS_HASH = ('00000089c09ef97712b7bde5994e6eb1' + 'c6f237cc119a86b77b92c28ef411e2f2') + PEERS = [ + ] diff --git a/lib/tx.py b/lib/tx.py index c4be13961..9abdd0635 100644 --- a/lib/tx.py +++ b/lib/tx.py @@ -503,3 +503,52 @@ def read_tx(self): expiry, witness ), DeserializerDecred.blake256(no_witness_tx) + + +class TxOutputDNotes(namedtuple("TxOutput", "value invoice pk_script")): + '''Class representing a transaction output.''' + pass + +class TxDNotes(namedtuple("Tx", "version time inputs outputs locktime")): + '''Class representing transaction that has a time field.''' + + @cachedproperty + def is_coinbase(self): + return self.inputs[0].is_coinbase + + +class DeserializerDNotes(Deserializer): + def read_tx(self): + + return TxDNotes( + self._read_le_int32(), + self._read_le_uint32(), + self._read_inputs(), + self._read_outputs(), + self._read_le_uint32() + ) + + def _read_outputs(self): + read_output = self._read_output + return [read_output() for i in range(self._read_varint())] + + def _read_output(self): + return TxOutputDNotes( + self._read_le_int64(), # value + self._read_varbytes(), # invoice + self._read_varbytes(), # pk_script + ) + + def read_header(self, height, static_header_size): + '''Return the block header bytes''' + start = self.cursor + self.cursor = start + self.cursor += static_header_size # Block normal header + numAddresses = self._read_varint() + for i in range(numAddresses): + self._read_varint() #variant type + self._read_nbytes(20) #address + self._read_le_uint64() #balance + header_end = self.cursor + self.cursor = start + return self._read_nbytes(header_end) \ No newline at end of file diff --git a/server/daemon.py b/server/daemon.py index 70ccf549c..8a1432562 100644 --- a/server/daemon.py +++ b/server/daemon.py @@ -381,3 +381,24 @@ def timestamp_safe(self, t): if isinstance(t, int): return t return timegm(strptime(t, "%Y-%m-%d %H:%M:%S %Z")) + + +class DNotesDaemon(FakeEstimateFeeDaemon): + '''Handles connections to a daemon at the given URL. + + This class is for the DNotes daemon that implements a separate RPC call called + getrawblock that gets raw blocks''' + async def raw_blocks(self, hex_hashes): + '''Return the raw binary blocks with the given hex hashes.''' + params_iterable = ((h, False) for h in hex_hashes) + blocks = await self._send_vector('getrawblock', params_iterable) + #Convert hex string to bytes + return [hex_to_bytes(block) for block in blocks] + + async def deserialised_block(self, hex_hash): + '''Return the deserialised block with the given hex hash.'''\ + #return the block in new bitcoin RPC format, for now only tx list is updated + block = await self._send_single('getblock', (hex_hash, True)) + tx = list(map(lambda r: r['txid'], block['tx'])) + block['tx'] = tx + return block \ No newline at end of file diff --git a/setup.py b/setup.py old mode 100644 new mode 100755