code: function readDefinitionChashByAddress(conn, address, max_mci, handle){
  	if (max_mci == null || max_mci == undefined)
  		max_mci = MAX_INT32;
  	// try to find last definition change, otherwise definition_chash=address
  	conn.query(
  		"SELECT definition_chash FROM address_definition_changes CROSS JOIN units USING(unit) \n\
  		WHERE address=? AND is_stable=1 AND sequence='good' AND main_chain_index<=? ORDER BY main_chain_index DESC LIMIT 1", 
  		[address, max_mci], 
  		function(rows){
  			var definition_chash = (rows.length > 0) ? rows[0].definition_chash : address;
  			handle(definition_chash);
  	});
  }
docs: /*
  function readWitnessesOnMcUnit(conn, main_chain_index, handleWitnesses){
  conn.query( // we read witnesses from MC unit (users can cheat with side-chains)
  "SELECT address \n\
  FROM units \n\
  JOIN unit_witnesses ON(units.unit=unit_witnesses.unit OR units.witness_list_unit=unit_witnesses.unit) \n\
  WHERE main_chain_index=? AND is_on_main_chain=1",
  [main_chain_index],
  function(witness_rows){
  if (witness_rows.length === 0)
  throw "no witness list on MC unit "+main_chain_index;
  if (witness_rows.length !== constants.COUNT_WITNESSES)
  throw "wrong number of witnesses on MC unit "+main_chain_index;
  var arrWitnesses = witness_rows.map(function(witness_row){ return witness_row.address; });
  handleWitnesses(arrWitnesses);
  }
  );
  }