code: function requestNextHashTree(ws) {
  	db.query("SELECT COUNT(1) AS count_left FROM catchup_chain_balls", function (rows) {
  		if (rows.length > 0) {
  			if (catchup_balls_at_start == -1) { // first time to get all catchup ball number
  				catchup_balls_at_start = rows[0].count_left;
  			}
  			catchup_balls_left = rows[0].count_left;
  		}
  	});
  	db.query("SELECT ball FROM catchup_chain_balls ORDER BY member_index LIMIT 2", function (rows) {
  		if (rows.length === 0)
  			return comeOnline();
  		if (rows.length === 1) {
  			db.query("DELETE FROM catchup_chain_balls WHERE ball=?", [rows[0].ball], function () {
  				comeOnline();
  			});
  			return;
  		}
  
  		let from_ball = rows[0].ball;
  		let to_ball = rows[1].ball;
  
  		// don't send duplicate requests
  		for (let tag in ws.assocPendingRequests) {
  			if (ws.assocPendingRequests[tag].request.command === 'get_hash_tree') {
  				console.log("already requested hash tree from this peer");
  				return;
  			}
  		}
  
  		//	...
  		sendRequest(ws, 'get_hash_tree', {from_ball: from_ball, to_ball: to_ball}, true, handleHashTree);
  	});
  }
docs: ////////////////////////////////////////////////////////////////////////////// hash tree //////////////////////////////////////////////////////////////////////////////