From bff20889c13c035020faca2d10dd338de8cf22ac Mon Sep 17 00:00:00 2001 From: ThomasV Date: Fri, 9 Dec 2011 22:55:04 +0300 Subject: [PATCH 1/8] fix manifest --- client/MANIFEST.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/MANIFEST.in b/client/MANIFEST.in index 37e11229..1ba82587 100644 --- a/client/MANIFEST.in +++ b/client/MANIFEST.in @@ -1,2 +1,5 @@ include README LICENCE RELEASE-NOTES -recursive-include *.py +include *.py +exclude setup.py +recursive-include ecdsa *.py +recursive-include aes *.py From 882c9753bdae97d2790b352870ae60f78edc46ba Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sat, 10 Dec 2011 09:46:20 +0300 Subject: [PATCH 2/8] better logs --- server/server.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/server.py b/server/server.py index ddc4993c..e4deceed 100755 --- a/server/server.py +++ b/server/server.py @@ -367,9 +367,9 @@ def client_thread(ipaddr,conn): conn.close() return - print time.asctime(), "new session", version, ipaddr, session_id, addresses[0] if addresses else addresses, len(addresses) + print time.strftime("[%d/%m/%Y-%H:%M:%S]"), "new session", ipaddr, addresses[0] if addresses else addresses, len(addresses), "v"+version - sessions[session_id] = { 'addresses':{}, 'version':version } + sessions[session_id] = { 'addresses':{}, 'version':version, 'ip':ipaddr } for a in addresses: sessions[session_id]['addresses'][a] = '' out = repr( (session_id, config.get('server','banner').replace('\\n','\n') ) ) @@ -383,7 +383,7 @@ def client_thread(ipaddr,conn): conn.close() return - print time.asctime(), "update session", ipaddr, session_id, addresses[0] if addresses else addresses, len(addresses) + print time.strftime("[%d/%m/%Y-%H:%M:%S]"), "update session", ipaddr, addresses[0] if addresses else addresses, len(addresses) sessions[session_id]['addresses'] = {} for a in addresses: @@ -525,7 +525,7 @@ def clean_session_thread(): for k,s in sessions.items(): t0 = s['last_time'] if t - t0 > 5*60: - print time.asctime(), "lost session",k + print time.strftime("[%d/%m/%Y-%H:%M:%S]"), "end session", s['ip'] sessions.pop(k) From dedb15e2bce128db88289e73f3f7f5e3a488acaf Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sat, 10 Dec 2011 22:34:35 +0300 Subject: [PATCH 3/8] maintain a list of mempool keys; the database might contain rejected transactions --- server/server.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/server/server.py b/server/server.py index e4deceed..732a8f90 100755 --- a/server/server.py +++ b/server/server.py @@ -249,6 +249,8 @@ class MyStore(Datastore_class): tx_hash = self.hashout_hex(tx_hash) if tx_hash in known_tx: continue + if tx_hash not in self.mempool_keys: + continue address_has_mempool = True #print "mempool", tx_hash @@ -362,12 +364,13 @@ def client_thread(ipaddr,conn): version = "old" else: version, addresses = ast.literal_eval(data) + version = "v"+version except: - print "error" + print "error", data conn.close() return - print time.strftime("[%d/%m/%Y-%H:%M:%S]"), "new session", ipaddr, addresses[0] if addresses else addresses, len(addresses), "v"+version + print time.strftime("[%d/%m/%Y-%H:%M:%S]"), "new session", ipaddr, addresses[0] if addresses else addresses, len(addresses), version sessions[session_id] = { 'addresses':{}, 'version':version, 'ip':ipaddr } for a in addresses: @@ -439,7 +442,7 @@ def client_thread(ipaddr,conn): else: out = 'wrong password' - elif cmd =='tx': + elif cmd =='tx': out = send_tx(data) print "sent tx:", out @@ -495,6 +498,7 @@ ds = BCDataStream.BCDataStream() def memorypool_update(store): + store.mempool_keys = [] conn = bitcoinrpc.connect_to_local() try: v = conn.getmemorypool() @@ -507,17 +511,16 @@ def memorypool_update(store): ds.write(hextx.decode('hex')) tx = deserialize.parse_Transaction(ds) tx['hash'] = util.double_sha256(tx['tx']) + store.mempool_keys.append(tx['hash'][::-1].encode('hex')) if store.tx_find_id_and_value(tx): pass - else: - #print "new tx", tx['hash'][::-1].encode('hex') + else: store.import_tx(tx, False) store.commit() - def clean_session_thread(): while not stopping: time.sleep(30) @@ -621,6 +624,7 @@ if __name__ == '__main__': store = MyStore(args) store.tx_cache = {} store.ismempool = False + store.mempool_keys = {} thread.start_new_thread(listen_thread, (store,)) thread.start_new_thread(clean_session_thread, ()) From 56014643a1b8b0e67af7100460414f2e4b79d88a Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sat, 10 Dec 2011 22:44:28 +0300 Subject: [PATCH 4/8] another patch for bitcoind --- server/patches/main.cpp.diff | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 server/patches/main.cpp.diff diff --git a/server/patches/main.cpp.diff b/server/patches/main.cpp.diff new file mode 100644 index 00000000..29b767f0 --- /dev/null +++ b/server/patches/main.cpp.diff @@ -0,0 +1,20 @@ +diff --git a/src/main.cpp b/src/main.cpp +index 45de76a..6cd304f 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -414,6 +414,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi + return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); + } + ++ /* + // Don't accept it if it can't get into a block + if (nFees < GetMinFee(1000, true, true)) + return error("AcceptToMemoryPool() : not enough fees"); +@@ -442,6 +443,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi + dFreeCount += nSize; + } + } ++ */ + } + + // Store transaction in memory From df689325a6c2760589434b740d4a16c8f527c1da Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sat, 10 Dec 2011 23:31:20 +0300 Subject: [PATCH 5/8] remove ismempool flag --- server/server.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/server/server.py b/server/server.py index 732a8f90..41738283 100755 --- a/server/server.py +++ b/server/server.py @@ -20,6 +20,8 @@ Todo: * server should check and return bitcoind status.. * improve txpoint sorting * command to check cache + + mempool transactions do not need to be added to the database; it slows it down """ @@ -73,14 +75,14 @@ class MyStore(Datastore_class): _hash = store.binout(row[6]) address = hash_to_address(chr(0), _hash) if self.tx_cache.has_key(address): - print "cache: invalidating", address, self.ismempool + #print "cache: invalidating", address self.tx_cache.pop(address) outrows = self.get_tx_outputs(txid, False) for row in outrows: _hash = store.binout(row[6]) address = hash_to_address(chr(0), _hash) if self.tx_cache.has_key(address): - print "cache: invalidating", address, self.ismempool + #print "cache: invalidating", address self.tx_cache.pop(address) def safe_sql(self,sql, params=(), lock=True): @@ -623,7 +625,6 @@ if __name__ == '__main__': args.connect_args = { 'database' : config.get('database','database') } store = MyStore(args) store.tx_cache = {} - store.ismempool = False store.mempool_keys = {} thread.start_new_thread(listen_thread, (store,)) @@ -635,9 +636,7 @@ if __name__ == '__main__': try: dblock.acquire() store.catch_up() - store.ismempool = True memorypool_update(store) - store.ismempool = False block_number = store.get_block_number(1) dblock.release() except: From b08f98524c2bd6260793ffe2252ad323604fef22 Mon Sep 17 00:00:00 2001 From: thomasv Date: Sun, 11 Dec 2011 11:37:59 +0100 Subject: [PATCH 6/8] wrong length --- client/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gui.py b/client/gui.py index 4239374b..29af6fa3 100644 --- a/client/gui.py +++ b/client/gui.py @@ -32,7 +32,7 @@ def format_satoshis(x): s = str( Decimal(x) /100000000 ) if not '.' in s: s += '.' p = s.find('.') - s += " "*( 8 - ( len(s) - p )) + s += " "*( 9 - ( len(s) - p )) return s def numbify(entry, is_int = False): From 05eeef4d949c581e9cfa19af2a7702eb36805c15 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 12 Dec 2011 13:52:15 +0300 Subject: [PATCH 7/8] patch for bitcoind --- server/patches/main.cpp.diff | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/server/patches/main.cpp.diff b/server/patches/main.cpp.diff index 29b767f0..e9a6f062 100644 --- a/server/patches/main.cpp.diff +++ b/server/patches/main.cpp.diff @@ -1,20 +1,28 @@ diff --git a/src/main.cpp b/src/main.cpp -index 45de76a..6cd304f 100644 +index 45de76a..8a9002f 100644 --- a/src/main.cpp +++ b/src/main.cpp -@@ -414,6 +414,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi - return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); - } +@@ -2787,16 +2787,19 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) -+ /* - // Don't accept it if it can't get into a block - if (nFees < GetMinFee(1000, true, true)) - return error("AcceptToMemoryPool() : not enough fees"); -@@ -442,6 +443,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi - dFreeCount += nSize; - } - } -+ */ - } + // Size limits + unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); +- if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN) +- continue; ++ //if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN) ++ // continue; + int nTxSigOps = tx.GetSigOpCount(); +- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) +- continue; ++ //if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) ++ // continue; - // Store transaction in memory + // Transaction fee required depends on block size + bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority)); + int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, true); + ++ // electrum server: do not check fees ++ nMinFee = 0; ++ + // Connecting shouldn't fail due to dependency on other memory pool transactions + // because we're already processing them in order of dependency + map mapTestPoolTmp(mapTestPool); From aded1e35f1bc4cd472ad41be42e928cfdaa34370 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 12 Dec 2011 13:56:36 +0300 Subject: [PATCH 8/8] getmemorypool != database; use db to set address_has_mempool --- server/server.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/server/server.py b/server/server.py index 41738283..2e8f000d 100755 --- a/server/server.py +++ b/server/server.py @@ -75,14 +75,14 @@ class MyStore(Datastore_class): _hash = store.binout(row[6]) address = hash_to_address(chr(0), _hash) if self.tx_cache.has_key(address): - #print "cache: invalidating", address + print "cache: invalidating", address self.tx_cache.pop(address) outrows = self.get_tx_outputs(txid, False) for row in outrows: _hash = store.binout(row[6]) address = hash_to_address(chr(0), _hash) if self.tx_cache.has_key(address): - #print "cache: invalidating", address + print "cache: invalidating", address self.tx_cache.pop(address) def safe_sql(self,sql, params=(), lock=True): @@ -251,10 +251,14 @@ class MyStore(Datastore_class): tx_hash = self.hashout_hex(tx_hash) if tx_hash in known_tx: continue + + # this means that pending transactions were added to the db, even if they are not returned by getmemorypool + address_has_mempool = True + + # this means pending transactions are returned by getmemorypool if tx_hash not in self.mempool_keys: continue - address_has_mempool = True #print "mempool", tx_hash txpoint = { "nTime": 0, @@ -351,7 +355,7 @@ def client_thread(ipaddr,conn): try: cmd, data = ast.literal_eval(msg[:-1]) except: - print "syntax error", repr(msg) + print "syntax error", repr(msg), ipaddr conn.close() return @@ -450,7 +454,7 @@ def client_thread(ipaddr,conn): elif cmd =='clear_cache': if config.get('server','password') == data: - self.tx_cache = {} + store.tx_cache = {} out = 'ok' else: out = 'wrong password' @@ -513,10 +517,11 @@ def memorypool_update(store): ds.write(hextx.decode('hex')) tx = deserialize.parse_Transaction(ds) tx['hash'] = util.double_sha256(tx['tx']) - store.mempool_keys.append(tx['hash'][::-1].encode('hex')) + tx_hash = tx['hash'][::-1].encode('hex') + store.mempool_keys.append(tx_hash) if store.tx_find_id_and_value(tx): pass - else: + else: store.import_tx(tx, False) store.commit()