aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2015-12-13 22:14:50 +0200
committerRiccardo Spagni <ric@spagni.net>2015-12-13 22:14:56 +0200
commitbdf738bc7ff996f95276fceb78c66c1aee19de08 (patch)
tree63f63c88aa91688ad9f9d394154471c038174d3a /src
parentMerge pull request #530 (diff)
parentcore_tests: fix ring_signature_1 tests (diff)
downloadmonero-bdf738bc7ff996f95276fceb78c66c1aee19de08.tar.xz
Merge pull request #531
cbded43 core_tests: fix ring_signature_1 tests (moneromooo-monero) c3d208f core_tests: bump default test fee to 0.02 monero (moneromooo-monero) 10da0a0 add a --fakechain argument for tests (moneromooo-monero) eee44e6 unit_tests: fix block reward test using post hard fork settings (moneromooo-monero) 595893f blockchain: log block (not chain) height in "BLOCK SUCCESFULLY ADDED" (moneromooo-monero) 2369968 blockchain: fix off by one in get_blocks (moneromooo-monero) 8af913a db_lmdb: implement BlockchainLMDB::reset (moneromooo-monero) 4833f4f db_bdb: implement BlockchainBDB::reset (moneromooo-monero) 18bf06e tx_pool: fix "minumim" typo in message (moneromooo-monero) 44f1267 tests: fix a typo in test name (moneromooo-monero) 1494557 db_lmdb: create all needed directories, not just the leaf one (moneromooo-monero) 015b68a db_bdb: create all needed directories, not just the leaf one (moneromooo-monero) f141869 tests: remove data-dir argument registration (moneromooo-monero)
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp43
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp30
-rw-r--r--src/common/command_line.cpp5
-rw-r--r--src/common/command_line.h1
-rw-r--r--src/cryptonote_core/blockchain.cpp15
-rw-r--r--src/cryptonote_core/blockchain.h2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp11
-rw-r--r--src/cryptonote_core/cryptonote_core.h1
-rw-r--r--src/cryptonote_core/tx_pool.cpp2
9 files changed, 95 insertions, 15 deletions
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index ce355ccde..07cb622a7 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -759,7 +759,7 @@ void BlockchainBDB::open(const std::string& filename, const int db_flags)
}
else
{
- if (!boost::filesystem::create_directory(direc))
+ if (!boost::filesystem::create_directories(direc))
throw0(DB_OPEN_FAILURE(std::string("Failed to create directory ").append(filename).c_str()));
}
@@ -1042,7 +1042,46 @@ void BlockchainBDB::sync()
void BlockchainBDB::reset()
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
- // TODO: this
+ check_open();
+
+ bdb_txn_safe txn;
+ if (m_env->txn_begin(NULL, txn, 0))
+ throw0(DB_ERROR("Failed to create a transaction for the db"));
+ m_write_txn = &txn;
+ try
+ {
+ uint32_t count;
+
+ m_blocks->truncate(*m_write_txn, &count, 0);
+ m_block_heights->truncate(*m_write_txn, &count, 0);
+ m_block_hashes->truncate(*m_write_txn, &count, 0);
+ m_block_timestamps->truncate(*m_write_txn, &count, 0);
+ m_block_sizes->truncate(*m_write_txn, &count, 0);
+ m_block_diffs->truncate(*m_write_txn, &count, 0);
+ m_block_coins->truncate(*m_write_txn, &count, 0);
+
+ m_txs->truncate(*m_write_txn, &count, 0);
+ m_tx_unlocks->truncate(*m_write_txn, &count, 0);
+ m_tx_heights->truncate(*m_write_txn, &count, 0);
+ m_tx_outputs->truncate(*m_write_txn, &count, 0);
+
+ m_output_txs->truncate(*m_write_txn, &count, 0);
+ m_output_indices->truncate(*m_write_txn, &count, 0);
+ m_output_amounts->truncate(*m_write_txn, &count, 0);
+ m_output_keys->truncate(*m_write_txn, &count, 0);
+
+ m_spent_keys->truncate(*m_write_txn, &count, 0);
+
+ m_hf_starting_heights->truncate(*m_write_txn, &count, 0);
+ m_hf_versions->truncate(*m_write_txn, &count, 0);
+
+ m_properties->truncate(*m_write_txn, &count, 0);
+ }
+ catch (const std::exception& e)
+ {
+ throw0(DB_ERROR(std::string("Failed to reset database: ").append(e.what()).c_str()));
+ }
+ m_write_txn = NULL;
}
std::vector<std::string> BlockchainBDB::get_filenames() const
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index fabe01d7f..9be21b039 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -943,7 +943,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
}
else
{
- if (!boost::filesystem::create_directory(direc))
+ if (!boost::filesystem::create_directories(direc))
throw0(DB_OPEN_FAILURE(std::string("Failed to create directory ").append(filename).c_str()));
}
@@ -1159,7 +1159,33 @@ void BlockchainLMDB::sync()
void BlockchainLMDB::reset()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- // TODO: this
+ check_open();
+
+ mdb_txn_safe txn;
+ if (mdb_txn_begin(m_env, NULL, 0, txn))
+ throw0(DB_ERROR("Failed to create a transaction for the db"));
+ mdb_drop(txn, m_blocks, 0);
+ mdb_drop(txn, m_block_timestamps, 0);
+ mdb_drop(txn, m_block_heights, 0);
+ mdb_drop(txn, m_block_hashes, 0);
+ mdb_drop(txn, m_block_sizes, 0);
+ mdb_drop(txn, m_block_diffs, 0);
+ mdb_drop(txn, m_block_coins, 0);
+ mdb_drop(txn, m_txs, 0);
+ mdb_drop(txn, m_tx_unlocks, 0);
+ mdb_drop(txn, m_tx_heights, 0);
+ mdb_drop(txn, m_tx_outputs, 0);
+ mdb_drop(txn, m_output_txs, 0);
+ mdb_drop(txn, m_output_indices, 0);
+ mdb_drop(txn, m_output_amounts, 0);
+ mdb_drop(txn, m_output_keys, 0);
+ mdb_drop(txn, m_spent_keys, 0);
+ mdb_drop(txn, m_hf_starting_heights, 0);
+ mdb_drop(txn, m_hf_versions, 0);
+ mdb_drop(txn, m_properties, 0);
+ txn.commit();
+ m_height = 0;
+ m_num_outputs = 0;
}
std::vector<std::string> BlockchainLMDB::get_filenames() const
diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp
index 925b62a54..5e5a9ff44 100644
--- a/src/common/command_line.cpp
+++ b/src/common/command_line.cpp
@@ -91,4 +91,9 @@ namespace command_line
, "Show time-stats when processing blocks/txs and disk synchronization."
, 0
};
+ const command_line::arg_descriptor<bool> arg_fakechain = {
+ "fakechain"
+ , "Use a fake chain for testing purposes."
+ , false
+ };
}
diff --git a/src/common/command_line.h b/src/common/command_line.h
index ffac71704..8955b826e 100644
--- a/src/common/command_line.h
+++ b/src/common/command_line.h
@@ -215,4 +215,5 @@ namespace command_line
extern const arg_descriptor<uint64_t> arg_prep_blocks_threads;
extern const arg_descriptor<uint64_t> arg_db_auto_remove_logs;
extern const arg_descriptor<uint64_t> arg_show_time_stats;
+ extern const arg_descriptor<bool> arg_fakechain;
}
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 2d71b61a1..5823c86f7 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -236,7 +236,7 @@ uint64_t Blockchain::get_current_blockchain_height() const
//------------------------------------------------------------------
//FIXME: possibly move this into the constructor, to avoid accidentally
// dereferencing a null BlockchainDB pointer
-bool Blockchain::init(BlockchainDB* db, const bool testnet)
+bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain)
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
@@ -293,8 +293,11 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet)
{
}
- // ensure we fixup anything we found and fix in the future
- m_db->fixup();
+ if (!fakechain)
+ {
+ // ensure we fixup anything we found and fix in the future
+ m_db->fixup();
+ }
// check how far behind we are
uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
@@ -311,7 +314,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet)
m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
#if defined(PER_BLOCK_CHECKPOINT)
- if (m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
+ if (!fakechain && m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
{
if (get_blocks_dat_size(testnet) > 4)
{
@@ -1361,7 +1364,7 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list<block
if(start_offset > m_db->height())
return false;
- for(size_t i = start_offset; i < start_offset + count && i <= m_db->height();i++)
+ for(size_t i = start_offset; i < start_offset + count && i < m_db->height();i++)
{
blocks.push_back(m_db->get_block_from_height(i));
}
@@ -2631,7 +2634,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
// do this after updating the hard fork state since the size limit may change due to fork
update_next_cumulative_size_limit();
- LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
+ LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
if(m_show_time_stats)
{
LOG_PRINT_L0("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: "
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index c83314634..f0b03ab0a 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -91,7 +91,7 @@ namespace cryptonote
Blockchain(tx_memory_pool& tx_pool);
- bool init(BlockchainDB* db, const bool testnet = false);
+ bool init(BlockchainDB* db, const bool testnet = false, const bool fakechain = false);
bool deinit();
void set_checkpoints(checkpoints&& chk_pts) { m_checkpoints = chk_pts; }
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 2f21bd4f1..960c8eff8 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -97,7 +97,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::update_checkpoints()
{
- if (m_testnet) return true;
+ if (m_testnet || m_fakechain) return true;
if (m_checkpoints_updating.test_and_set()) return true;
@@ -145,18 +145,20 @@ namespace cryptonote
command_line::add_arg(desc, command_line::arg_db_sync_mode);
command_line::add_arg(desc, command_line::arg_show_time_stats);
command_line::add_arg(desc, command_line::arg_db_auto_remove_logs);
+ command_line::add_arg(desc, command_line::arg_fakechain);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_command_line(const boost::program_options::variables_map& vm)
{
m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ m_fakechain = command_line::get_arg(vm, command_line::arg_fakechain);
auto data_dir_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
m_config_folder = command_line::get_arg(vm, data_dir_arg);
auto data_dir = boost::filesystem::path(m_config_folder);
- if (!m_testnet)
+ if (!m_testnet && !m_fakechain)
{
cryptonote::checkpoints checkpoints;
if (!cryptonote::create_checkpoints(checkpoints))
@@ -257,6 +259,9 @@ namespace cryptonote
boost::filesystem::path folder(m_config_folder);
+ if (m_fakechain)
+ folder /= "fake";
+
folder /= db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ...");
@@ -337,7 +342,7 @@ namespace cryptonote
m_blockchain_storage.set_user_options(blocks_threads,
blocks_per_sync, sync_mode, fast_sync);
- r = m_blockchain_storage.init(db, m_testnet);
+ r = m_blockchain_storage.init(db, m_testnet, m_fakechain);
bool show_time_stats = command_line::get_arg(vm, command_line::arg_show_time_stats) != 0;
m_blockchain_storage.set_show_time_stats(show_time_stats);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index e7a6c4154..5d665cb98 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -199,6 +199,7 @@ namespace cryptonote
uint64_t m_target_blockchain_height;
bool m_testnet;
+ bool m_fakechain;
std::string m_checkpoints_path;
time_t m_last_dns_checkpoints_update;
time_t m_last_json_checkpoints_update;
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index defbeb3b3..e2dcd35f5 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -113,7 +113,7 @@ namespace cryptonote
needed_fee *= FEE_PER_KB;
if (!kept_by_block && fee < needed_fee /*&& fee < MINING_ALLOWED_LEGACY_FEE*/)
{
- LOG_PRINT_L1("transaction fee is not enough: " << print_money(fee) << ", minumim fee: " << print_money(needed_fee));
+ LOG_PRINT_L1("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
tvc.m_verifivation_failed = true;
return false;
}
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
%PDF-1.3
%0123
1 0 obj
<<
/CreationDate (D:20060227103541)
/Producer (Xerox WCP 55)
>>
endobj
2 0 obj
<< /Length 36 >>
stream
q 1226.88 0 0 789.12 0 0 cm /I3 Do Q
endstream
endobj
3 0 obj
<<
/Type /XObject /Subtype /Image
/Width 3408 /Height 2192
/BitsPerComponent 1
/ColorSpace /DeviceGray
/Filter /CCITTFaxDecode
/DecodeParms << /K -1 /Columns 3408 /Rows 2192 /BlackIs1 false >>
/Length 257829     
>>
stream
*=ᰎhEѢкH2rC9FChlآ E8 I$
)R RI$I$]GՕi":I&II$I|EI$-$M@H&!64,#4GIĊ:!";  )4GM*	iI	B $à	Jh2!!: FjH#Ae9 
	AA@$	 BmJh]Dt Ťh3@IQi ,aáҒEy^v0$":Z:#"覍!@D}@4"R:HD!!"kE4Z":	dtRI$I Dw&$HDu)$ h 9L:I (r
h2$h$؍$Dt(Ѻ:`}$RM!A:
$HDtAN<mӆ$GCI$t$	)M) @H 9I@IB]Jh24)$I":RA":Hb1MIR=G.#hH":9EGGDtGFGDts><3FtyDtaGaϣ": fa4%]#:J$t0$tBL!e @8B  ADtBGA"$}]>$tLH$ H NAA
ƑtB%в(r(r;% BGDtBL푲
$ CmhZ#DtfG#$6	#l0H$i!	4i	D}Ii$	ayH $A"?%*?D}H:A&PDtI$M5I6]GVJG+E##y JQAh:#	H:#7ab:#CQGMGDt	SM&a"H AEA	A4"GL$t"AZH!@8B$BG8F"	  @@ ЄL&I0"G`HA8F*$ (Acē	am+
 A
BB]uA	P
$	$H4I4Ia4i&I7h$	l 4A:
0L4[ GA&I]4hvGMDuŠ">AøA4]4GVp#4TAhIZI`r"霑":j)0AA\Մ	C
8A @#a2:at#DtDu @莐
BCP$H$7A7CYCc	 +8@aA	$$$t$a0a0*e$`$L	$ƒB(r$_AaʴfCE1$GA4&eH00">톚h$DtI	>HPEBRV
$*#i$Bfl+4GIiGEj">AG##TGlD}GTGG":#M$AcJÒRA++&hH QQS:	QS
#qHhI$Dtl L0p":.@莡
 J(& 	8F" A0(oH2+8!a08#$$+	$| @$|.H @8FE`B$tI EA$#@a B[i ( h(hIDtMhA q 
$@A&Qi&QA L lDtsH#GA":##Q$
Dt	B#4AՑR
":A)$LEYE 0#I4	MQQaA(tGH	GH H @M#8An4L	:IPDz4@a6a(pDtC- 	$*ނ(pWpFA(r&U`H@$](p@$$H 	$0BI]$(pFI!tG.a(p  :&FDA H ( D}1I4G#0Ӈ
$[-qh$I$G$6Q0I
6M+4	$[#H7 Dt#">HAE	":#a0Dy:G쎚nt%Dudui$D}i$a(vGAdttDt	"NP  dt
t"	LC ih":h @Za @ 2+
@e#| BIRA2PB	 $@ID}"菠@##هƐ`!!	$C@$ A	$H6Dt0mBM$	;A&aAIA0A&Dt
h$AS@$H$hKDtH	$GV":]$GӋAL;#qvGH$I$GVGA":AmGDtI4CI$t	":jQHS
A(pi
&2: IB݄S:& #Gۍ#莅	ʀ	(>.8 I @H#  œ"EY@ A0A @ I F4@`8B(pA("Ci `H FHʴ}II
-M0݂04
4Il4Hl4II aa06V"	$DzJR
H0	:aDtH">mG݆:A@#PDuvH"<#4D|4L ł#":%eRGA#0qDua":B$G@  7qAdtDual P!.	"(:Qi$_@EHAEaN	96	8# B#!A"!AAcH A
 P@)1I FU)@2@ B j#	BI餄$h	">#	A:I">I0M4
3Z#
a:
0DtE	^A$HB##EM8⢬ AÆ@!A":J]H$GHXN
VGQgj:>ѴGD4FDgT!$tg`t&DDDDCB!dvr1!a#0	HHG
G"85D}":#6t#DtEtGD|":HGFAtDtmE#t]tGFDtmGh.>莈.#h0莍膌##8莌#GDtah8tGDtaFF3.##.#h.,$l eYf91ɎsC'q(rDDBDDDDDDDDYPI̸A$A$&Iƅ";#hZ	H$A$$G2$G DvGDsI$L!I$ H$D}$0H$@$		ID|$$DvG4I$	GiE$	Dv0a$	$EAuT% B!I$$PE;6i BEv97$)ɺE;.f̎4PH9rNLr$ܡF9r(r1A(r9'"[9!Ɏq`rC9HÕm
8H &P@		E
rI6ٷhPb M%I$R*H$ICA$$I**$I4	4A
IA*HBE8 i4`$ CI$!L @h$ V":AQLt#iq({(p4a v(x"ACNCH*H4ZI"&9CFP	R[MI$):AE;	ƒ(a#EH$P$P0(r@
MPRHh6[LbPP
6
(0A0i$1M@66hPI$M=#(xh I*H">##} a &8$¤DQ$DDZI!A B @b49N	(tt "APEE@AP A6&,8";E	>H0@l">	4tDt":P8@ hPC BC@A$GHGaGCGN" PECe(p9C#E@a#8 LC:EDth -4a
IՆGEp#B #B	!%g $AA"qN8A9C Gph.Dq#P9C㈤vGDsHaI A#I$	$	DRA#H"	  $@I 	(pE$$$ I(pA	0$ a HII$S;L":		 @A$E&HwI	 A$H H$IIH@i$@II8IE L@ 	e@:H(u(w(v`L!hEPEE:I4P""'HɎdrEF8E$(rc8F81q$	8A @A!0H6(P$I$	@&І`6!0iI I&lS;
!q@0	M(hC(sːń[I"	7,Hdte4ZaI$ԡ(t$P0dtG4PNED
-IDBHhqnȣ4F9CP.MHM "!CHTPP	CP(tҢM4GI#@(pLpN. Li@T*$CAV4I$L@5PP:CC %:B(&G$Dp\"q#BDt&(aE@PŰ<49CGEL ChL h" h HAET
l ";m:&A(w0EC`">@Ct"`$A2A
` "vH#L&HPp0!DtDA8"X BBXq, B!,q#(HF9CAv$8$쎂;pI"@$I$pI$I$I 8;i8 9VH DtAA#9H@
IB#Ai:E$8@@pE$ 	(p@$I$I$G#H"GA I	 8$A$A	$$H$E8#
$H 8I	, Bv	$":!i(t	8dv\k(t9cGt8#+H! 8@ܐHH 	$	
iMI(MmGA4a0a
H[IP*	$ Р@@L APa$@0i!m$eI
ahRHPA4b! aGI$]$)Ld:I$+FkA;LI;a!$iGa4LsC쎈H&qăJ8v6(pEC":EeDtTEDt a8A8D|"nCPMP"cci*EPH"nmGJ
m*0Dt0S8kD|R&:Ei"A$BФ(#RhDPB"
aE"AA"9CCpZ&h`" Ah @P4P菢	G (GRC	& P@4GIXA0EPG@2A l"$vN"(pA2@<$Ce`"<( 
	ai @)±`A	 @A& @ILq8L9CJL9!K	9C9cdk
1RA$EI @I& I F$	 ;H @@$I8":#:	H$ I FI I$&apH$$A$Aㄒ(p	 AApBB&`i	$NI	 I$#DvI `IEtGdtG":		$J 	Dt6HLK:!A .G,)8CChq!#r9#8;mű	l&
6a!a[A&m-
SI6
	I4qa
$"II&L8EPI:aHPb	bA&E8m	IEEgY.#,P":#	=8dpr#DQR	$qHq,t(q㰊":L*(v)"$$CE	Ҋ@==:	A"H.-)*(vC	7CL&jPDtC(tGA;ۅe(tGITi$ tF꤃A",tpdp8#""F>#!GZ(tP&)	P&*)" MPNC# e&A0Dv`0PA0NCML(pZ# @"A@$P"Dy:aI4(pA `4SaDtSH"l4	-!0! f0BUdlH%9ܡĨ%ZDAP'8cc!I$(q,rÉL8 8$ I IAHZA$ #H 	$ I IaI$	$PeGtIGA I!$H#H#sI I	$	 Ds	 @$HII$ Ia!$$H gDq@ I@H0sH DtuTBo@KaZIXA	)R#lP# VaԡhGE$:B)	
Hv`q#8[	*!A
ŶP!(v@$I$,$-8aI$BqhI&*)$S A
&-IBM&A4":l1@cerA$GGis#:!YtEA	TR(ˬ$DuP4NCiDtل<4LH"CLEI"C98A	C(tGJ"aP"DtEPC:h$*A4 PH&m#
(vH	EEEAl$-:GIb#F#m,` "<$!`6GP.$@G8D| Dx#:LpDBDDRrAh&"(tL6L&CLA4"(tL&a҄G@ lC0EBE:(tL"(p LCGATE:E&&		G @"AGA(t&":	AE(tGGjL"J!ZupDtA	N Ir8!3ӸD} C/IRH!0Y#R8p\
	1(9!tÂH$A I$Ar A\i DtRAI
H$	$ÂaH$H"	$ I 8$":#0 A$	$H!$I$	H $I $) @$A$@IH!II
H#A$	${I$%$GBGIA";L @^P4Xm4	#I$H4#:DuJ)"IGZB./2HECqɎP쎈G$BA#"(
D4ML&	!6
$I
b-$	$Im@B(4(tM$m0A1"(t[H!70LH2GZBN<"":#:3DtGFtHD莏":tmDth莭":8#:.DtGDuG:#h莈莋Ȏ,莌GF6I!iջh"[A'(z)^hLs[I	|pCPH8;#TP҇PTPPVP(vPDtm"HMQC:TP;ME":	H""I6EE(vE"a
6TP:0&GIؠI$;JDx@\VP8i!YDZQq
0T"NÌ&ImRE8:	Pe#IXDtGXe9N*$2A
B)""")$&0A(r"0&A08 L D|$LEBI#?	(p@(tGAG@	#CGAEPECP6HLEB#A0CG@0GA`PD|Ca" @bC	"(p	*& Iu9CHZa 'kڷJK另Vڴ,toh F!A">[Dt##I@V"z	8	ܐC0rC&q!8A#GpI@$H#	H DtLH @	8 I X4
$H$@H$CH$!	$@H#I$.dtG`	$$$dt] @A$@III$I F$H	 E8 	$P$ I$ I 8A H FM H$A $A D4GFȈuD}	t"0;