From 06c93bcf389e84ca1c93dc181436434e686a52dd Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sun, 27 Oct 2013 16:12:06 -0200 Subject: [PATCH 01/29] update port in help text --- src/init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index dccbda3b..6307a288 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -177,7 +177,7 @@ std::string HelpMessage() strUsage += " -socks= " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n"; strUsage += " -tor= " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"; strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n"; - strUsage += " -port= " + _("Listen for connections on (default: 8333 or testnet: 18333)") + "\n"; + strUsage += " -port= " + _("Listen for connections on (default: 28333 or testnet: 18333)") + "\n"; strUsage += " -maxconnections= " + _("Maintain at most connections to peers (default: 125)") + "\n"; strUsage += " -addnode= " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; strUsage += " -connect= " + _("Connect only to the specified node(s)") + "\n"; @@ -220,7 +220,7 @@ std::string HelpMessage() #endif strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; - strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 8332 or testnet: 18332)") + "\n"; + strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 28332 or testnet: 18332)") + "\n"; strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address") + "\n"; if (!fHaveGUI) strUsage += " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n"; From d93da9efd5057e4e9adc5436fa7dc16afd5c4e2d Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sun, 27 Oct 2013 22:54:47 -0200 Subject: [PATCH 02/29] 2 months to expire posts from dht --- src/twister.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/twister.h b/src/twister.h index 38233776..ef3daaba 100644 --- a/src/twister.h +++ b/src/twister.h @@ -11,7 +11,7 @@ #define USERPOST_FLAG_DM 0x02 #define BLOCK_AGE_TO_EXPIRE_DHT_ENTRY (2016) // about 2 weeks -#define BLOCK_AGE_TO_EXPIRE_DHT_POSTS (4320*6) // about 6 months +#define BLOCK_AGE_TO_EXPIRE_DHT_POSTS (4320*2) // about 2 months class twister From dea07606642b99d1416f581749b4c61f589bc66f Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 09:00:23 -0200 Subject: [PATCH 03/29] just todo items --- TODO | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/TODO b/TODO index 2a912581..c67e215a 100644 --- a/TODO +++ b/TODO @@ -66,3 +66,9 @@ of his own torrent) - Estimate number of online followers by quering the "tracker" resource (implement a value within this resource to report the number of torrent peers) +- Properly implement spam signing and checking to prevent it from been used to impersonate users. +"nobody" might be an exception so default client could still send unauthenticated/anonymous spam +messages. + +- Define and enforce html directory to serve from. Do installation scripts. + From ac76c967ae323596bc4c776c8ff7553a9bc84818 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 18:05:13 -0200 Subject: [PATCH 04/29] do not add peers with high failcount to the local dht tracker --- libtorrent/src/torrent.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index dde7b2aa..2ef492f4 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2057,25 +2057,25 @@ namespace libtorrent { TORRENT_ASSERT(m_ses.is_network_thread()); if (!m_ses.m_dht) return; - if (!m_name) return; + if (!m_name) return; if (!should_announce_dht()) return; TORRENT_ASSERT(m_allow_peers); - // [MF] use m_dht->announce with myself=false to update dht tracker with other peers + // [MF] use m_dht->announce with myself=false to update dht tracker with peers we know { - policy::const_iterator i = get_policy().begin_peer(); - policy::const_iterator end = get_policy().end_peer(); - for (; i != end; ++i) - { - policy::peer const* p = *i; + policy::const_iterator i = get_policy().begin_peer(); + policy::const_iterator end = get_policy().end_peer(); + for (; i != end; ++i) { + policy::peer const* p = *i; - if( p->connectable && !p->banned ) { + if( p->connectable && !p->banned && + int(p->failcount) < settings().max_failcount ) { m_ses.m_dht->announce(name(), m_torrent_file->info_hash() , p->address(), p->port, p->seed, false , boost::bind(&nop)); + } } - } } #ifdef TORRENT_USE_OPENSSL From 40803b910c23741e8684db62e8b700f724570200 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 18:58:29 -0200 Subject: [PATCH 05/29] improve last commit: only announce to local dht tracker if we ever connected to peer. --- libtorrent/src/torrent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 2ef492f4..784fc626 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2069,7 +2069,7 @@ namespace libtorrent for (; i != end; ++i) { policy::peer const* p = *i; - if( p->connectable && !p->banned && + if( p->connectable && !p->banned && p->last_connected && int(p->failcount) < settings().max_failcount ) { m_ses.m_dht->announce(name(), m_torrent_file->info_hash() , p->address(), p->port, p->seed, false From d363d2f788b502b209d017f32d4d2298d27767ab Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:01:13 -0200 Subject: [PATCH 06/29] remove unneeded optimization: m_data_callback is called multiple times (for every reply) so asking ourselves doesn't hurt. this might fix the assertion which is failing on observer destructor. --- libtorrent/src/kademlia/find_data.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libtorrent/src/kademlia/find_data.cpp b/libtorrent/src/kademlia/find_data.cpp index 2bcc08d1..1ef1f05b 100644 --- a/libtorrent/src/kademlia/find_data.cpp +++ b/libtorrent/src/kademlia/find_data.cpp @@ -206,10 +206,6 @@ bool find_data::invoke(observer_ptr o) return false; } - // im not going to ask trackers from myself - if( o->id() == m_node.nid() ) - return false; - entry e; e["z"] = "q"; e["q"] = "getData"; // "getPeers" From 624b5f8b490735dff856e5d2d6955c4a06fc3810 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:03:10 -0200 Subject: [PATCH 07/29] improved debugging of get/put dht keys --- libtorrent/src/kademlia/node.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 4675c92f..5883dffe 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -1179,13 +1179,11 @@ void node_impl::incoming_request(msg const& m, entry& e) sha1_hash target = hasher(targetbuf.first,targetbuf.second).final(); //#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::string target_str(targetbuf.first,targetbuf.second); - printf("PUT target: %s = {%s,%s,%s} = '%s'\n" - , to_hex(target.to_string()).c_str() + printf("PUT target={%s,%s,%s} from=%s:%d\n" , msg_keys[mk_n]->string_value().c_str() , msg_keys[mk_r]->string_value().c_str() , msg_keys[mk_t]->string_value().c_str() - , target_str.c_str()); + , m.addr.address().to_string().c_str(), m.addr.port()); //#endif // verify the write-token. tokens are only valid to write to @@ -1359,13 +1357,11 @@ void node_impl::incoming_request(msg const& m, entry& e) if (msg_keys[mk_justtoken] && msg_keys[mk_justtoken]->int_value() != 0) justtoken = true; //#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::string target_str(targetbuf.first,targetbuf.second); - printf("GET target: %s = {%s,%s,%s} = '%s'\n" - , to_hex(target.to_string()).c_str() + printf("GET target={%s,%s,%s} from=%s:%d\n" , msg_keys[mk_n]->string_value().c_str() , msg_keys[mk_r]->string_value().c_str() , msg_keys[mk_t]->string_value().c_str() - , target_str.c_str()); + , m.addr.address().to_string().c_str(), m.addr.port()); //#endif reply["token"] = generate_token(m.addr, target.to_string().c_str()); From c7141bcb2e4eb33f9ea4392bc04d21c95c7bfb63 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:17:50 -0200 Subject: [PATCH 08/29] prevent bencoding uninitialized entries (which causes assertion fail) --- src/twister_utils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/twister_utils.cpp b/src/twister_utils.cpp index 9e066b71..cfd72fe7 100644 --- a/src/twister_utils.cpp +++ b/src/twister_utils.cpp @@ -137,8 +137,8 @@ int saveUserData(std::string const& filename, std::map con for (i = users.begin(); i != users.end(); ++i) { UserData const &udata = i->second; - entry &userData = userDict[i->first]; if( udata.m_following.size() ) { + entry &userData = userDict[i->first]; entry &followingList = userData["following"]; BOOST_FOREACH( std::string const &n, udata.m_following) { followingList.list().push_back(n); @@ -146,6 +146,7 @@ int saveUserData(std::string const& filename, std::map con } if( udata.m_directmsg.size() ) { + entry &userData = userDict[i->first]; entry &dmDict = userData["dm"]; std::map >::const_iterator j; From 5dd9116627af37e7612e3b046472358d65515065 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:28:15 -0200 Subject: [PATCH 09/29] less debug noise --- src/netbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 8708316c..10405627 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -382,7 +382,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe } if (nRet != 0) { - printf("connect() failed after select(): %s\n",strerror(nRet)); + //printf("connect() failed after select(): %s\n",strerror(nRet)); closesocket(hSocket); return false; } From c9e2b88920d7ca4658288660ebfb3c4e5ae37d5e Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:42:36 -0200 Subject: [PATCH 10/29] try another improvement to local dht tracker updating: currently connected nodes or recently connected (4 hours) --- libtorrent/src/torrent.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 784fc626..475b7ce9 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2069,8 +2069,9 @@ namespace libtorrent for (; i != end; ++i) { policy::peer const* p = *i; - if( p->connectable && !p->banned && p->last_connected && - int(p->failcount) < settings().max_failcount ) { + bool connect_recently = !p->banned && int(p->failcount) < settings().max_failcount && + p->last_connected && (m_ses.session_time() - p->last_connected) < (4*3600); + if( p->connectable && ( p->connection || connect_recently) ) { m_ses.m_dht->announce(name(), m_torrent_file->info_hash() , p->address(), p->port, p->seed, false , boost::bind(&nop)); From d9c64c2076206b5ada7db2941f08047a45128fee Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 19:45:01 -0200 Subject: [PATCH 11/29] another try at ThreadMaintainDHTNodes to fix the problem of adding useless dht nodes and forcing announcements all the time. --- src/twister.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/twister.cpp b/src/twister.cpp index e7742069..964bb707 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -249,14 +249,16 @@ void ThreadMaintainDHTNodes() while(1) { MilliSleep(5000); + session_status ss = ses->status(); + int dht_nodes = ss.dht_nodes; bool nodesAdded = false; + if( ses ) { LOCK(cs_vNodes); vector vAddr = addrman.GetAddr(); - session_status ss = ses->status(); int totalNodesCandidates = (int)(vNodes.size() + vAddr.size()); - if( (!ss.dht_nodes && totalNodesCandidates) || - ss.dht_nodes < totalNodesCandidates / 2 ) { + if( (!dht_nodes && totalNodesCandidates) || + dht_nodes < totalNodesCandidates / 2 ) { printf("ThreadMaintainDHTNodes: too few dht_nodes, trying to add some...\n"); BOOST_FOREACH(const CAddress &a, vAddr) { std::string addr = a.ToStringIP(); @@ -269,7 +271,7 @@ void ThreadMaintainDHTNodes() // if !fInbound we created this connection so ip is reachable. // we can't use port number of inbound connection, so try standard port. // only use inbound as last resort (if dht_nodes empty) - if( !pnode->fInbound || !ss.dht_nodes ) { + if( !pnode->fInbound || !dht_nodes ) { std::string addr = pnode->addr.ToStringIP(); int port = (!pnode->fInbound) ? pnode->addr.GetPort() : Params().GetDefaultPort(); port += LIBTORRENT_PORT_OFFSET; @@ -283,9 +285,18 @@ void ThreadMaintainDHTNodes() } } if( nodesAdded ) { - LOCK(cs_twister); - BOOST_FOREACH(const PAIRTYPE(std::string, torrent_handle)& item, m_userTorrent) { - item.second.force_dht_announce(); + MilliSleep(5000); + ss = ses->status(); + if( ss.dht_nodes > dht_nodes ) { + // new nodes were added to dht: force updating peers from dht so torrents may start faster + LOCK(cs_twister); + BOOST_FOREACH(const PAIRTYPE(std::string, torrent_handle)& item, m_userTorrent) { + item.second.force_dht_announce(); + } + } else { + // nodes added but dht ignored them, so they are probably duplicated. + // we sleep a bit as a punishment :-) + MilliSleep(30000); } } } From 2cd0b0a88127d5418eed16989f525d0a01ab13f0 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 22:59:43 -0200 Subject: [PATCH 12/29] rescandirectmsgs: rescan all streams of users we follow for new and old directmessages --- libtorrent/include/libtorrent/torrent.hpp | 2 ++ .../include/libtorrent/torrent_handle.hpp | 1 + libtorrent/src/torrent.cpp | 24 +++++++++++++ libtorrent/src/torrent_handle.cpp | 6 ++++ src/bitcoinrpc.cpp | 1 + src/bitcoinrpc.h | 1 + src/twister.cpp | 36 +++++++++++++++++-- 7 files changed, 68 insertions(+), 3 deletions(-) diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 57bb0a83..35390111 100644 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -523,6 +523,8 @@ namespace libtorrent return m_picker->have_piece(index); } + void recheck_pieces(uint32_t piece_flags); + // called when we learn that we have a piece // only once per piece void we_have(int index, boost::uint32_t post_flags); diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp index 586311a6..29f0ec80 100644 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ b/libtorrent/include/libtorrent/torrent_handle.hpp @@ -170,6 +170,7 @@ namespace libtorrent void read_piece(int piece) const; void get_pieces(std::vector &pieces, int count, int max_id, int since_id, uint32_t filter_flags) const; bool have_piece(int piece) const; + void recheck_pieces(uint32_t piece_flags) const; void get_full_peer_list(std::vector& v) const; void get_peer_info(std::vector& v) const; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 475b7ce9..71597a6c 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -3073,6 +3073,30 @@ namespace libtorrent m_picker->set_piece_priority(i, 6); } + void on_disk_read_recheck_piece_complete(int ret, disk_io_job const& j, peer_request r) + { + // [MF] FIXME: implement cond_wakeup here so that recheck_pieces would wait + } + + void torrent::recheck_pieces(uint32_t piece_flags) + { + TORRENT_ASSERT(m_ses.is_network_thread()); + TORRENT_ASSERT(m_picker); + + for( int i = 0; i <= last_have(); i++) { + if( m_picker->have_piece(i) && m_picker->post_flags(i) == piece_flags ) { + peer_request r; + r.piece = i; + r.start = 0; + r.length = torrent_file().piece_size(i); + + filesystem().async_read_and_hash(r, + boost::bind(&on_disk_read_recheck_piece_complete + , _1, _2, r), 1); + } + } + } + void torrent::we_have(int index, boost::uint32_t post_flags) { TORRENT_ASSERT(m_ses.is_network_thread()); diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index ab216e93..590bd4e6 100644 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -846,6 +846,12 @@ namespace libtorrent return r; } + void torrent_handle::recheck_pieces(uint32_t piece_flags) const + { + INVARIANT_CHECK; + TORRENT_SYNC_CALL1(recheck_pieces, piece_flags); + } + storage_interface* torrent_handle::get_storage_impl() const { INVARIANT_CHECK; diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 0e19356c..36cf0171 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -256,6 +256,7 @@ static const CRPCCommand vRPCCommands[] = { "listusernamespartial", &listusernamespartial, false, true }, { "getdefaultuser", &getdefaultuser, false, true }, { "setdefaultuser", &setdefaultuser, false, true }, + { "rescandirectmsgs", &rescandirectmsgs, false, true }, }; CRPCTable::CRPCTable() diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 2b080685..5dc0d06e 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -208,5 +208,6 @@ extern json_spirit::Value getlasthave(const json_spirit::Array& params, bool fHe extern json_spirit::Value listusernamespartial(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getdefaultuser(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value setdefaultuser(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value rescandirectmsgs(const json_spirit::Array& params, bool fHelp); #endif diff --git a/src/twister.cpp b/src/twister.cpp index 964bb707..6bda7edd 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -653,11 +653,10 @@ bool processReceivedDM(lazy_entry const* post) } else { std::string textOut; if( key.Decrypt(sec, textOut) ) { - /* this printf is good for debug, but bad for security. + // this printf is good for debug, but bad for security. printf("Received DM for user '%s' text = '%s'\n", item.second.username.c_str(), textOut.c_str()); - */ std::string n = post->dict_find_string_value("n"); @@ -958,7 +957,8 @@ bool shouldDhtResourceExpire(std::string resource, bool multi, int height) if( m_noExpireResources[resourceBasic] == PostNoExpireRecent && (height + BLOCK_AGE_TO_EXPIRE_DHT_POSTS) < getBestHeight() ) { #ifdef DEBUG_EXPIRE_DHT_ITEM - printf("shouldDhtResourceExpire: expiring old post resource '%s'\n", resource.c_str()); + printf("shouldDhtResourceExpire: expiring old post resource '%s' (height %d cur %d)\n", + resource.c_str(), height, getBestHeight()); #endif return true; } @@ -1594,3 +1594,33 @@ Value listusernamespartial(const Array& params, bool fHelp) return ret; } +Value rescandirectmsgs(const Array& params, bool fHelp) +{ + if (fHelp || (params.size() != 1)) + throw runtime_error( + "rescandirectmsgs \n" + "rescan all streams of users we follow for new and old directmessages"); + + string localUser = params[0].get_str(); + + std::set following; + { + LOCK(cs_twister); + following = m_users[localUser].m_following; + } + + BOOST_FOREACH(string username, following) { + torrent_handle torrent; + + { + LOCK(cs_twister); + if( username.size() && m_userTorrent.count(username) ) + torrent = m_userTorrent[username]; + } + if( torrent.is_valid() ){ + torrent.recheck_pieces(USERPOST_FLAG_DM); + } + } + + return Value(); +} From d16d50313aaa00dc7a08f700f0acf7303dc52cac Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 23:15:19 -0200 Subject: [PATCH 13/29] insert directmsgs into vector ordered by time --- src/twister.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/twister.cpp b/src/twister.cpp index 6bda7edd..89126023 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -653,10 +653,11 @@ bool processReceivedDM(lazy_entry const* post) } else { std::string textOut; if( key.Decrypt(sec, textOut) ) { - // this printf is good for debug, but bad for security. + /* this printf is good for debug, but bad for security. printf("Received DM for user '%s' text = '%s'\n", item.second.username.c_str(), textOut.c_str()); + */ std::string n = post->dict_find_string_value("n"); @@ -668,12 +669,16 @@ bool processReceivedDM(lazy_entry const* post) LOCK(cs_twister); // store this dm in memory list, but prevent duplicates std::vector &dmsFromToUser = m_users[item.second.username].m_directmsg[n]; - std::vector::const_iterator it; + std::vector::iterator it; for( it = dmsFromToUser.begin(); it != dmsFromToUser.end(); ++it ) { if( stoDM.m_utcTime == (*it).m_utcTime && stoDM.m_text == (*it).m_text ) { break; } + if( stoDM.m_utcTime < (*it).m_utcTime ) { + dmsFromToUser.insert(it, stoDM); + break; + } } if( it == dmsFromToUser.end() ) { dmsFromToUser.push_back(stoDM); From dbc640faaac2b389fe6ee27e4ce6f20a7e98c0ac Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 23:30:18 -0200 Subject: [PATCH 14/29] implement exact match on username search --- src/bitcoinrpc.cpp | 1 + src/twister.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 36cf0171..a93ff3ca 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1258,6 +1258,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "unfollow" && n > 1) ConvertTo(params[1]); if (strMethod == "listusernamespartial" && n > 1) ConvertTo(params[1]); + if (strMethod == "listusernamespartial" && n > 2) ConvertTo(params[2]); return params; } diff --git a/src/twister.cpp b/src/twister.cpp index 89126023..1fd4d421 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1548,13 +1548,16 @@ Value getlasthave(const Array& params, bool fHelp) Value listusernamespartial(const Array& params, bool fHelp) { - if (fHelp || (params.size() != 2)) + if (fHelp || (params.size() < 2 || params.size() > 3)) throw runtime_error( - "listusernamespartial \n" + "listusernamespartial [exact_match]\n" "get list of usernames starting with"); string userStartsWith = params[0].get_str(); size_t count = params[1].get_int(); + bool exact_match = false; + if( params.size() > 2 ) + exact_match = params[2].get_bool(); set retStrings; @@ -1564,6 +1567,8 @@ Value listusernamespartial(const Array& params, bool fHelp) BOOST_FOREACH(const PAIRTYPE(CKeyID, CKeyMetadata)& item, pwalletMain->mapKeyMetadata) { LOCK(cs_twister); BOOST_FOREACH(const string &user, m_users[item.second.username].m_following) { + if( exact_match && userStartsWith.size() != user.size() ) + break; int toCompare = std::min( userStartsWith.size(), user.size() ); if( memcmp( user.data(), userStartsWith.data(), toCompare ) == 0 ) retStrings.insert( user ); @@ -1582,6 +1587,8 @@ Value listusernamespartial(const Array& params, bool fHelp) BOOST_FOREACH(const CTransaction&tx, block.vtx) { if( !tx.IsSpamMessage() ) { string txUsername = tx.userName.ExtractSmallString(); + if( exact_match && userStartsWith.size() != txUsername.size() ) + break; int toCompare = std::min( userStartsWith.size(), txUsername.size() ); if( memcmp( txUsername.data(), userStartsWith.data(), toCompare ) == 0 ) retStrings.insert( txUsername ); From 3c90b0a94c64aa279a5e8ff420cb5e338e6a6319 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 23:51:11 -0200 Subject: [PATCH 15/29] rt also updates status --- src/twister.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/twister.cpp b/src/twister.cpp index 1fd4d421..e02cfc94 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1278,6 +1278,8 @@ Value newrtmsg(const Array& params, bool fHelp) // post to dht as well ses->dht_putData(strUsername, string("post")+strK, false, v, strUsername, GetAdjustedTime(), 1); + ses->dht_putData(strUsername, string("status"), false, + v, strUsername, GetAdjustedTime(), k); // notification to keep track of RTs of the original post if( rt ) { From 68f3e97e65dae6a504aca6880627c7a4ba4f25f2 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 28 Oct 2013 23:54:30 -0200 Subject: [PATCH 16/29] another todo --- TODO | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TODO b/TODO index c67e215a..bd6640a7 100644 --- a/TODO +++ b/TODO @@ -72,3 +72,6 @@ messages. - Define and enforce html directory to serve from. Do installation scripts. +- Don't accept dht "post"+k if k violates the validatePostNumberForUser() rule. + + From 549ba353dd2ff88e739a184e4ca18e4d06c346d7 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Tue, 29 Oct 2013 10:48:06 -0200 Subject: [PATCH 17/29] yet another ThreadMaintainDHTNodes heuristic improvement --- libtorrent/src/session.cpp | 2 +- src/twister.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 8b4d5544..5382ff4a 100644 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -1235,7 +1235,7 @@ namespace libtorrent , coalesce_writes(false) , outgoing_ports(0,0) , peer_tos(0) - , active_downloads(3) + , active_downloads(6) , active_seeds(5) , active_dht_limit(88) // don't announce more than once every 40 seconds , active_tracker_limit(1600) // don't announce to trackers more than once every 1.125 seconds diff --git a/src/twister.cpp b/src/twister.cpp index e02cfc94..57c21521 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -258,7 +258,7 @@ void ThreadMaintainDHTNodes() vector vAddr = addrman.GetAddr(); int totalNodesCandidates = (int)(vNodes.size() + vAddr.size()); if( (!dht_nodes && totalNodesCandidates) || - dht_nodes < totalNodesCandidates / 2 ) { + (dht_nodes < 5 && totalNodesCandidates > 10) ) { printf("ThreadMaintainDHTNodes: too few dht_nodes, trying to add some...\n"); BOOST_FOREACH(const CAddress &a, vAddr) { std::string addr = a.ToStringIP(); From 6ade53ce530fba62fbc9bf340cd0121f6f1ff758 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Tue, 29 Oct 2013 17:54:23 -0200 Subject: [PATCH 18/29] implement new rpc dumppubkey. importprivkey now verifies if username exists in txdb --- src/bitcoinrpc.cpp | 2 ++ src/bitcoinrpc.h | 1 + src/rpcdump.cpp | 37 +++++++++++++++++++++++++++++++++++-- src/twister.cpp | 2 +- src/twister.h | 1 + 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index a93ff3ca..b3c79f67 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -230,6 +230,7 @@ static const CRPCCommand vRPCCommands[] = { "submitblock", &submitblock, false, false }, { "listsinceblock", &listsinceblock, false, false }, { "dumpprivkey", &dumpprivkey, true, false }, + { "dumppubkey", &dumppubkey, false, false }, { "dumpwallet", &dumpwallet, true, false }, { "importprivkey", &importprivkey, false, false }, { "importwallet", &importwallet, false, false }, @@ -1241,6 +1242,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); if (strMethod == "lockunspent" && n > 1) ConvertTo(params[1]); if (strMethod == "importprivkey" && n > 2) ConvertTo(params[2]); + if (strMethod == "importprivkey" && n > 3) ConvertTo(params[3]); if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); if (strMethod == "dhtput" && n > 3) ConvertToValue(params[3]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 5dc0d06e..071c6a72 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -146,6 +146,7 @@ extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp +extern json_spirit::Value dumppubkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 6c139d6d..f76d5591 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -9,6 +9,7 @@ #include "bitcoinrpc.h" #include "ui_interface.h" #include "base58.h" +#include "twister.h" #include #include @@ -67,9 +68,9 @@ std::string DecodeDumpString(const std::string &str) { Value importprivkey(const Array& params, bool fHelp) { - if (fHelp || params.size() < 2 || params.size() > 3) + if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( - "importprivkey [rescan=true]\n" + "importprivkey [rescan=true] [allow_new_user=false]\n" "Adds a private key (as returned by dumpprivkey) to your wallet."); string strSecret = params[0].get_str(); @@ -80,11 +81,24 @@ Value importprivkey(const Array& params, bool fHelp) if (params.size() > 2) fRescan = params[2].get_bool(); + bool fAllowNewUser = false; + if (params.size() > 3) + fAllowNewUser = params[3].get_bool(); + CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(strSecret); if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + if( !fAllowNewUser ) { + CTransaction txOut; + uint256 hashBlock; + uint256 userhash = SerializeHash(strUsername); + if( !GetTransaction(userhash, txOut, hashBlock) ) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "User must exist (or allow_new_user flag must be set)"); + } + } + CKey key = vchSecret.GetKey(); CPubKey pubkey = key.GetPubKey(); CKeyID vchAddress = pubkey.GetID(); @@ -211,6 +225,25 @@ Value dumpprivkey(const Array& params, bool fHelp) return CBitcoinSecret(vchSecret).ToString(); } +Value dumppubkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "dumppubkey \n" + "Returns the public key corresponding to ."); + + string strUsername = params[0].get_str(); + + CPubKey pubkey; + bool gotKey = getUserPubKey(strUsername, pubkey); + + if( !gotKey ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Username not found"); + + string strPubkey = string( reinterpret_cast(pubkey.begin()), pubkey.size()); + return strPubkey; +} + Value dumpwallet(const Array& params, bool fHelp) { diff --git a/src/twister.cpp b/src/twister.cpp index 57c21521..428d204c 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1552,7 +1552,7 @@ Value listusernamespartial(const Array& params, bool fHelp) { if (fHelp || (params.size() < 2 || params.size() > 3)) throw runtime_error( - "listusernamespartial [exact_match]\n" + "listusernamespartial [exact_match=false]\n" "get list of usernames starting with"); string userStartsWith = params[0].get_str(); diff --git a/src/twister.h b/src/twister.h index ef3daaba..913b985d 100644 --- a/src/twister.h +++ b/src/twister.h @@ -23,6 +23,7 @@ public: void startSessionTorrent(boost::thread_group& threadGroup); void stopSessionTorrent(); +bool getUserPubKey(std::string const &strUsername, CPubKey &pubkey); std::string createSignature(std::string const &strMessage, CKeyID &keyID); std::string createSignature(std::string const &strMessage, std::string const &strUsername); bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign); From 8d793b371dd6fe8b7722b5bed2acddc199579f75 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Tue, 29 Oct 2013 18:02:33 -0200 Subject: [PATCH 19/29] return "" in dumppubkey for nonexistent user --- src/rpcdump.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index f76d5591..9116dc29 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -230,15 +230,16 @@ Value dumppubkey(const Array& params, bool fHelp) if (fHelp || params.size() != 1) throw runtime_error( "dumppubkey \n" - "Returns the public key corresponding to ."); + "Returns the public key corresponding to (empty if user doesn't exist)"); string strUsername = params[0].get_str(); CPubKey pubkey; bool gotKey = getUserPubKey(strUsername, pubkey); - if( !gotKey ) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Username not found"); + if( !gotKey ) { + return ""; + } string strPubkey = string( reinterpret_cast(pubkey.begin()), pubkey.size()); return strPubkey; From 432535bd6d6ee11831bda45f759ed8e631ef11e1 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Wed, 30 Oct 2013 17:31:30 -0200 Subject: [PATCH 20/29] fix listusernamespartial: search string must be shorter than username being compared (or equal). not longer. --- src/twister.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/twister.cpp b/src/twister.cpp index 428d204c..3491391b 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1569,9 +1569,11 @@ Value listusernamespartial(const Array& params, bool fHelp) BOOST_FOREACH(const PAIRTYPE(CKeyID, CKeyMetadata)& item, pwalletMain->mapKeyMetadata) { LOCK(cs_twister); BOOST_FOREACH(const string &user, m_users[item.second.username].m_following) { - if( exact_match && userStartsWith.size() != user.size() ) - break; - int toCompare = std::min( userStartsWith.size(), user.size() ); + if( (exact_match && userStartsWith.size() != user.size()) || + userStartsWith.size() > user.size() ) { + continue; + } + int toCompare = userStartsWith.size(); if( memcmp( user.data(), userStartsWith.data(), toCompare ) == 0 ) retStrings.insert( user ); if( retStrings.size() >= count ) @@ -1589,9 +1591,11 @@ Value listusernamespartial(const Array& params, bool fHelp) BOOST_FOREACH(const CTransaction&tx, block.vtx) { if( !tx.IsSpamMessage() ) { string txUsername = tx.userName.ExtractSmallString(); - if( exact_match && userStartsWith.size() != txUsername.size() ) - break; - int toCompare = std::min( userStartsWith.size(), txUsername.size() ); + if( (exact_match && userStartsWith.size() != txUsername.size()) || + userStartsWith.size() > txUsername.size() ) { + continue; + } + int toCompare = userStartsWith.size(); if( memcmp( txUsername.data(), userStartsWith.data(), toCompare ) == 0 ) retStrings.insert( txUsername ); if( retStrings.size() >= count ) From defb9a13a374fce696977beb38118fee0db1eb82 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Wed, 30 Oct 2013 18:55:13 -0200 Subject: [PATCH 21/29] increase POW difficulty for user registrations --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 4add2bdc..0a03e37d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -33,7 +33,7 @@ public: nDefaultPort = 28333; nRPCPort = 28332; bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); - nTxBits = 0x1e03ffff; + nTxBits = 0x1e00ffff; nSubsidyHalvingInterval = 210000; // Build the genesis block. Note that the output of the genesis coinbase cannot From 3ac54ffbe960f3501b3aa33eca7267b4bd911bd4 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Wed, 30 Oct 2013 20:57:49 -0200 Subject: [PATCH 22/29] don't start torrent for nonexistent users. (we will need something different for #hashtags) --- src/twister.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/twister.cpp b/src/twister.cpp index 3491391b..2305372a 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -70,7 +70,7 @@ sha1_hash dhtTargetHash(std::string const &username, std::string const &resource torrent_handle startTorrentUser(std::string const &username) { LOCK(cs_twister); - if( !m_userTorrent.count(username) ) { + if( !m_userTorrent.count(username) && usernameExists(username) ) { sha1_hash ih = dhtTargetHash(username, "tracker", "m"); printf("adding torrent for [%s,tracker]\n", username.c_str()); From 2df6ff2420f7b55b24f6566d20419b7eeed8ac89 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Wed, 30 Oct 2013 21:19:14 -0200 Subject: [PATCH 23/29] persist spammsg to send and generate status --- src/twister.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/twister.cpp b/src/twister.cpp index 2305372a..810a3846 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -111,6 +111,12 @@ int saveGlobalData(std::string const& filename) globalDict["receivedSpamMsg"] = m_receivedSpamMsgStr; globalDict["receivedSpamUser"] = m_receivedSpamUserStr; globalDict["lastSpamTime"] = m_lastSpamTime; + globalDict["sendSpamMsg"] = strSpamMessage; + globalDict["sendSpamUser"] = strSpamUser; + globalDict["generate"] = GetBoolArg("-gen", false); + int genproclimit = GetArg("-genproclimit", -1); + if( genproclimit > 0 ) + globalDict["genproclimit"] = genproclimit; std::vector buf; bencode(std::back_inserter(buf), globalDict); @@ -131,6 +137,20 @@ int loadGlobalData(std::string const& filename) m_receivedSpamMsgStr = userDict.dict_find_string_value("receivedSpamMsg"); m_receivedSpamUserStr = userDict.dict_find_string_value("receivedSpamUser"); m_lastSpamTime = userDict.dict_find_int_value("lastSpamTime"); + string sendSpamMsg = userDict.dict_find_string_value("sendSpamMsg"); + if( sendSpamMsg.size() ) strSpamMessage = sendSpamMsg; + string sendSpamUser = userDict.dict_find_string_value("sendSpamUser"); + if( sendSpamUser.size() ) strSpamUser = sendSpamUser; + bool generate = userDict.dict_find_int_value("generate"); + int genproclimit = userDict.dict_find_int_value("genproclimit"); + + if( generate ) { + Array params; + params.push_back( generate ); + if( genproclimit > 0 ) + params.push_back( genproclimit ); + setgenerate(params, false); + } return 0; } From 277c917b5376be63dc7502691e29499eae0656f0 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 31 Oct 2013 13:48:31 -0200 Subject: [PATCH 24/29] no use for setting/getting defaultuser, it just adds confusion. --- INSTALL | 1 + src/bitcoinrpc.cpp | 2 -- src/bitcoinrpc.h | 2 -- src/rpcwallet.cpp | 6 +++++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index 7430335f..ccb1c4ae 100644 --- a/INSTALL +++ b/INSTALL @@ -14,6 +14,7 @@ libtorrent's. 1) Start with libtorrent: $ cd libtorrent +$ ./bootstrap.sh $ ./configure --enable-logging --enable-debug --enable-dht Note1: 64-bit systems may need "--with-boost-libdir=/usr/lib64" diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index b3c79f67..87690826 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -255,8 +255,6 @@ static const CRPCCommand vRPCCommands[] = { "getfollowing", &getfollowing, false, true }, { "getlasthave", &getlasthave, false, true }, { "listusernamespartial", &listusernamespartial, false, true }, - { "getdefaultuser", &getdefaultuser, false, true }, - { "setdefaultuser", &setdefaultuser, false, true }, { "rescandirectmsgs", &rescandirectmsgs, false, true }, }; diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 071c6a72..28266de7 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -207,8 +207,6 @@ extern json_spirit::Value unfollow(const json_spirit::Array& params, bool fHelp) extern json_spirit::Value getfollowing(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getlasthave(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value listusernamespartial(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getdefaultuser(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value setdefaultuser(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value rescandirectmsgs(const json_spirit::Array& params, bool fHelp); #endif diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 7cde6dab..c611ba02 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -153,6 +153,10 @@ Value listwalletusers(const Array& params, bool fHelp) return ret; } +/* [mf] no use for setting/getting defaultuser, it just adds confusion. + all commands should receive user as parameter (including the user for spammsg). +*/ +#if 0 Value setdefaultuser(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -199,7 +203,7 @@ Value getdefaultuser(const Array& params, bool fHelp) return username; } - +#endif Value signmessage(const Array& params, bool fHelp) { From 2c48386b4e4ccf2f01e59236a180fe0941b2cf54 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 31 Oct 2013 14:02:29 -0200 Subject: [PATCH 25/29] Properly implement spam signing and checking to prevent it from been used to impersonate users. "nobody" is an exception so default client could still send unauthenticated/anonymous spam messages. --- TODO | 4 ---- src/bitcoind.cpp | 59 ------------------------------------------------ src/main.cpp | 58 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 73 deletions(-) diff --git a/TODO b/TODO index bd6640a7..90a2d733 100644 --- a/TODO +++ b/TODO @@ -66,10 +66,6 @@ of his own torrent) - Estimate number of online followers by quering the "tracker" resource (implement a value within this resource to report the number of torrent peers) -- Properly implement spam signing and checking to prevent it from been used to impersonate users. -"nobody" might be an exception so default client could still send unauthenticated/anonymous spam -messages. - - Define and enforce html directory to serve from. Do installation scripts. - Don't accept dht "post"+k if k violates the validatePostNumberForUser() rule. diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index f9715a88..905e980a 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -124,64 +124,6 @@ bool AppInit(int argc, char* argv[]) } -static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"); - -static bool TestCreateSpamMsgTx() -{ - CTransaction txNew; - - txNew.message = CScript() << strSpamMessage; - - CBitcoinSecret bsecret1; - bsecret1.SetString (strSecret1C); - - CKey key; - key.MakeNewKey(true); - //CKey key = bsecret1.GetKey(); - CPubKey pubkey( key.GetPubKey() ); - - printf("key valid: %d compressed: %d\n", key.IsValid(), key.IsCompressed()); - printf("pubkey: %s\n", EncodeBase64(&pubkey[0], pubkey.size()).c_str() ); - - // compute message hash and sign it - CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); - ss << txNew.message; - uint256 hashMsg = ss.GetHash(); - - // vchSig is sig(hash(message)) - vector vchSig; - if (!key.Sign(hashMsg, vchSig)) { - printf("CreateNewBlock: Failed to sign SpamMessage\n"); - return false; - } - - /* - vector vchSigCompact; - if (!key.SignCompact(hashMsg, vchSigCompact)) { - printf("CreateNewBlock: Failed to sign SpamMessage2\n"); - return false; - } - printf("sign size: %zu signCompact size: %zu\n", vchSig.size(), vchSigCompact.size()); - printf("signCompact: %s\n", EncodeBase64(&vchSigCompact[0], vchSigCompact.size()).c_str()); - */ - - printf("CreateSpamMsgTx: msg = %s user = %s hash = %s signedhash = %s\n", txNew.message.ToString().c_str(), strSpamUser.c_str(), - hashMsg.ToString().c_str(), EncodeBase64(&vchSig[0], vchSig.size()).c_str() ); - - // add username and signature - txNew.userName = CScript() << strSpamUser; - txNew.userName += CScript() << vchSig; - txNew.pubKey.clear(); // pubKey will be updated to include extranonce - txNew.nNonce = 0; // no update needed for spamMessage's nonce. - - std::vector< std::vector > vData; - txNew.userName.ExtractPushData(vData); - - printf("Verify: %d\n", pubkey.Verify(hashMsg,vData[1])); - - exit(1); -} - extern void GenesisMiner(); extern void noui_connect(); int main(int argc, char* argv[]) @@ -190,7 +132,6 @@ int main(int argc, char* argv[]) fHaveGUI = false; //GenesisMiner(); - //TestCreateSpamMsgTx(); // Connect bitcoind signal handlers noui_connect(); diff --git a/src/main.cpp b/src/main.cpp index 965353eb..1cc24acd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -425,10 +425,45 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) { // Basic checks that don't depend on any context if (tx.IsSpamMessage()) { - if (tx.message.size() > MAX_SPAM_MSG_SIZE) - return state.DoS(100, error("CheckTransaction() : spam message too big")); - // [MF] TODO: check message signature - // [MF] Problem: registration of this user may be in the block itself, better check later. + string spamMsg = tx.message.ExtractPushDataString(0); + if (!spamMsg.size()) + return state.DoS(100, error("CheckTransaction() : invalid or empty spam message")); + if (spamMsg.size() > MAX_SPAM_MSG_SIZE) + return state.DoS(100, error("CheckTransaction() : spam message too big")); + + string spamUser = tx.userName.ExtractPushDataString(0); + if( spamUser != "nobody" ) { + string strSign = tx.userName.ExtractPushDataString(1); + if (!strSign.size()) + return state.DoS(100, error("CheckTransaction() : spam signature missing")); + vector vchSig((const unsigned char*)strSign.data(), + (const unsigned char*)strSign.data() + strSign.size()); + + CPubKey pubkey; + CTransaction txPubKey; + uint256 hashBlock; + uint256 userhash = SerializeHash(spamUser); + if( !GetTransaction(userhash, txPubKey, hashBlock) ) + return state.DoS(100, error("CheckTransaction() : spam signed by unknown user")); + + std::vector< std::vector > vData; + if( !txPubKey.pubKey.ExtractPushData(vData) || vData.size() < 1 ) + return state.DoS(100, error("CheckTransaction() : spam signed with broken pubkey")); + + pubkey = CPubKey(vData[0]); + + // compute message hash for signature checking + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + ss << strMessageMagic; + ss << tx.message; + + CPubKey pubkeyRec; + if (!pubkeyRec.RecoverCompact(ss.GetHash(), vchSig)) + return state.DoS(100, error("CheckTransaction() : RecoverCompact failed for spammsg")); + + if (pubkeyRec.GetID() != pubkey.GetID()) + return state.DoS(100, error("CheckTransaction() : spam signature verification failed")); + } } else { if (tx.userName.empty()) return state.DoS(10, error("CheckTransaction() : username empty")); @@ -1713,11 +1748,10 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl if( pblock->vtx[0].IsSpamMessage() ) { string msg = pblock->vtx[0].message.ExtractPushDataString(0); string user = pblock->vtx[0].userName.ExtractPushDataString(0); - // [MF] FIXME: validate user properly - if( msg.length() <= 140 ) { - printf("ProcessBlock: msg='%s' user='%s'\n", msg.c_str(), user.c_str()); - receivedSpamMessage(msg, user); - } + + // SpamMessage was already validated in CheckBlock => CheckTransation + printf("ProcessBlock: msg='%s' user='%s'\n", msg.c_str(), user.c_str()); + receivedSpamMessage(msg, user); } return true; } @@ -3492,7 +3526,7 @@ static bool CreateSpamMsgTx(CTransaction &txNew, std::vector &sal std::string strUsername = strSpamUser; CKeyID keyID; - if( !pwalletMain->GetKeyIdFromUsername(strSpamUser, keyID) ) { + if( strSpamUser != "nobody" && !pwalletMain->GetKeyIdFromUsername(strSpamUser, keyID) ) { if( pwalletMain->vchDefaultKey.IsValid() ) { keyID = pwalletMain->vchDefaultKey.GetID(); strUsername = pwalletMain->mapKeyMetadata[keyID].username; @@ -3534,6 +3568,10 @@ static bool CreateSpamMsgTx(CTransaction &txNew, std::vector &sal txNew.pubKey.clear(); // pubKey will be updated to include extranonce txNew.nNonce = 0; // no update needed for spamMessage's nonce. + CValidationState state; + bool ret = CheckTransaction(txNew, state); + printf("CheckTransaction returned %d\n", ret ); + return true; } From 0678ae169b7de8d1784e2c946c03dba287f6a80f Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 31 Oct 2013 14:04:13 -0200 Subject: [PATCH 26/29] CreateSpamMsgTx fallback to "nobody" --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 1cc24acd..34993fe2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3530,6 +3530,8 @@ static bool CreateSpamMsgTx(CTransaction &txNew, std::vector &sal if( pwalletMain->vchDefaultKey.IsValid() ) { keyID = pwalletMain->vchDefaultKey.GetID(); strUsername = pwalletMain->mapKeyMetadata[keyID].username; + } else { + strUsername = "nobody"; } } printf("CreateSpamMsgTx: keyId = %s\n", keyID.ToString().c_str() ); From 8286e4c78de34c20fa3ae28e7bcbcf055c666088 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 31 Oct 2013 14:24:04 -0200 Subject: [PATCH 27/29] old debug printf --- src/twister.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/twister.cpp b/src/twister.cpp index 810a3846..71feab05 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -520,7 +520,6 @@ void stopSessionTorrent() // save_resume_data will generate an alert when it's done st.handle.save_resume_data(); ++num_outstanding_resume_data; - printf("\r%d ", num_outstanding_resume_data); } printf("\nwaiting for resume data [%d]\n", num_outstanding_resume_data); while (num_outstanding_resume_data > 0) From 6594b01e6f8b256a5266cf2bd23030c8312f5a44 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 31 Oct 2013 23:52:44 -0200 Subject: [PATCH 28/29] less logging when pooling for network status --- src/bitcoinrpc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 87690826..23eaa422 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -913,7 +913,8 @@ void JSONRequest::parse(const Value& valRequest) throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); strMethod = valMethod.get_str(); if (strMethod != "getwork" && strMethod != "getblocktemplate" && - strMethod != "getlasthave") + strMethod != "getlasthave" && + strMethod != "getinfo" && strMethod != "getbestblockhash" && strMethod != "getblock") printf("ThreadRPCServer method=%s\n", strMethod.c_str()); // Parse params From 22161a71ed6cfc01ef486f8b39a5c9cc4a1779ca Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Fri, 1 Nov 2013 15:13:37 -0200 Subject: [PATCH 29/29] fix deadlock --- src/twister.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/twister.cpp b/src/twister.cpp index 71feab05..9f427524 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -69,8 +69,10 @@ sha1_hash dhtTargetHash(std::string const &username, std::string const &resource torrent_handle startTorrentUser(std::string const &username) { + bool userInTxDb = usernameExists(username); // keep this outside cs_twister to avoid deadlock + LOCK(cs_twister); - if( !m_userTorrent.count(username) && usernameExists(username) ) { + if( !m_userTorrent.count(username) && userInTxDb ) { sha1_hash ih = dhtTargetHash(username, "tracker", "m"); printf("adding torrent for [%s,tracker]\n", username.c_str());