From f9013c899a10aa53c5e345cd8c53240f3d457dda Mon Sep 17 00:00:00 2001 From: Michael Vlasov Date: Wed, 8 Feb 2023 18:01:40 +0300 Subject: [PATCH 01/26] NEW: Masterchain block producing. NEW: `global_id` parameter in `ton-node.conf.json` is written into blocks. NEW: `global_id` parameter is used as a `signature_id` if related cap is turned on in the blockchain config. SDK-4341 --- .gitignore | 1 + CHANGELOG.md | 9 + Cargo.toml | 7 + dev/q-server.json | 16 +- docker/ton-node/ton-node.conf.json | 67 +++--- node/Cargo.toml | 23 +- node/src/api/message_api.rs | 4 +- node/src/block/applier.rs | 84 -------- node/src/block/builder.rs | 76 +++---- node/src/block/finality.rs | 311 ++++++++++++++-------------- node/src/block/mod.rs | 6 +- node/src/config.rs | 5 + node/src/data/arango.rs | 2 +- node/src/data/file_based_storage.rs | 48 ++--- node/src/engine/engine.rs | 178 ++++++---------- node/src/engine/masterchain.rs | 110 ++++++++++ node/src/engine/messages.rs | 47 ++--- node/src/engine/mod.rs | 2 + node/src/engine/shardchain.rs | 118 +++++++++++ node/src/main.rs | 7 +- 20 files changed, 608 insertions(+), 513 deletions(-) create mode 100644 Cargo.toml delete mode 100644 node/src/block/applier.rs create mode 100644 node/src/engine/masterchain.rs create mode 100644 node/src/engine/shardchain.rs diff --git a/.gitignore b/.gitignore index 3d251ce..146cb24 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ readme.html /dev/node_modules/ /dev/package-lock.json /node/target/ +/target/ diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d3f1d..921601c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes All notable changes to this project will be documented in this file. +## 0.37.0 Jan 11, 2023 + +### New + +- Masterchain block producing. +- `global_id` parameter in `ton-node.conf.json` is written into blocks. +- `global_id` parameter is used as a `signature_id` if related cap is turned + on in the blockchain config. + ## 0.36.3 Jan 11, 2023 ### Fixed diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c84c873 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "node", +] + +exclude = [ +] diff --git a/dev/q-server.json b/dev/q-server.json index fcfb5dd..72d33c8 100644 --- a/dev/q-server.json +++ b/dev/q-server.json @@ -9,38 +9,38 @@ }, "blockchain": { "accounts": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "blocks": { "hot": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "cold": [] }, - "zerostate": "http://root@localhost:8529" + "zerostate": "http://root@localhost:8529?name=se_master_blocks" }, "slowQueriesBlockchain": { "accounts": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "blocks": { "hot": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529" + "http://root@localhost:8529?name=se_master_blocks" ], "cold": [] }, - "zerostate": "http://root@localhost:8529" + "zerostate": "http://root@localhost:8529?name=se_master_blocks" } } diff --git a/docker/ton-node/ton-node.conf.json b/docker/ton-node/ton-node.conf.json index 44332e0..17654e6 100644 --- a/docker/ton-node/ton-node.conf.json +++ b/docker/ton-node/ton-node.conf.json @@ -1,38 +1,41 @@ { - "node_index": 0, - "port": 40301, - "poa_validators": 2, - "poa_interval": 1, - "private_key": "./private-key", - "keys": ["./pub-key"], - "boot": [], - "shard_id": { - "workchain": 0, - "shardchain_pfx": 0, - "shardchain_pfx_len": 0 - }, - "adnl": { - "address": "127.0.0.1:3030", - "keys": [ - { - "type_id": -1977122418, - "pub_key": "BBKmgGAxz4ZofRgMO2qhYt+K1bGlGeowukPONVAkOcU=", - "pvt_key": "3CFeiTSlGkJf3D8w3ZXS4QS+6/0p+MFZGuv0XYMvMRo=" - } - ] - }, + "node_index": 0, + "port": 40301, + "poa_validators": 2, + "poa_interval": 1, + "private_key": "./private-key", + "keys": [ + "./pub-key" + ], + "boot": [], + "global_id": 100, + "shard_id": { + "workchain": 0, + "shardchain_pfx": 0, + "shardchain_pfx_len": 0 + }, + "adnl": { + "address": "127.0.0.1:3030", + "keys": [ + { + "type_id": -1977122418, + "pub_key": "BBKmgGAxz4ZofRgMO2qhYt+K1bGlGeowukPONVAkOcU=", + "pvt_key": "3CFeiTSlGkJf3D8w3ZXS4QS+6/0p+MFZGuv0XYMvMRo=" + } + ] + }, "api": { "messages": "topics/requests", "live_control": "se", - "address": "127.0.0.1", - "port": 3000 + "address": "127.0.0.1", + "port": 3000 }, - "document_db": { - "server": "127.0.0.1:8529", - "database": "blockchain", - "blocks_collection": "blocks", - "messages_collection": "messages", - "transactions_collection": "transactions", - "accounts_collection": "accounts" - } + "document_db": { + "server": "127.0.0.1:8529", + "database": "se_master_blocks", + "blocks_collection": "blocks", + "messages_collection": "messages", + "transactions_collection": "transactions", + "accounts_collection": "accounts" + } } diff --git a/node/Cargo.toml b/node/Cargo.toml index fa34e6a..c17e9f2 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -2,37 +2,36 @@ edition = '2021' build = 'build.rs' name = 'ton_node_startup' -version = '0.36.3' +version = '0.37.0' [dependencies] # External anyhow = '1.0' base64 = '0.13' -clap = '3.1' +clap = '3.2' ed25519-dalek = '1.0' failure = '0.1' hex = '0.4' -http = '0.1' +http = '0.2' iron = '0.6' jsonrpc-http-server = '10.0.1' lazy_static = '1.4.0' log = '0.4' -log4rs = '1.1' +log4rs = '1.2' num = '0.4' num-traits = '0.2' parking_lot = '0.12' rand = '0.8' -reqwest = '0.9.7' +reqwest = '0.9' router = '0.6.0' serde = '1.0' serde_derive = '1.0' -serde_json = { features = [ 'preserve_order' ], version = '1.0' } +serde_json = { features = ['preserve_order'], version = '1.0' } thiserror = '1.0' # Domestic -ton_block = { git = 'https://github.com/tonlabs/ton-labs-block', tag = '1.9.14' } -ton_block_json = { git = 'https://github.com/tonlabs/ton-labs-block-json.git', tag = '0.7.79' } -ton_executor = { git = 'https://github.com/tonlabs/ton-labs-executor', tag = '1.15.145' } -ton_types = { git = 'https://github.com/tonlabs/ton-labs-types', tag = '1.12.4' } -ton_vm = { git = 'https://github.com/tonlabs/ton-labs-vm', tag = '1.8.89', features = ['gosh'] } - +ton_block = { git = 'https://github.com/tonlabs/ever-block', tag = '1.9.28' } +ton_block_json = { git = 'https://github.com/tonlabs/ever-block-json', tag = '0.7.95' } +ton_executor = { git = 'https://github.com/tonlabs/ever-executor', tag = '1.15.175', features = ['signature_with_id'] } +ton_types = { git = 'https://github.com/tonlabs/ever-types', tag = '1.12.7' } +ton_vm = { git = 'https://github.com/tonlabs/ever-vm', tag = '1.8.116', features = ['gosh'] } diff --git a/node/src/api/message_api.rs b/node/src/api/message_api.rs index 996bdfa..9573258 100644 --- a/node/src/api/message_api.rs +++ b/node/src/api/message_api.rs @@ -14,7 +14,7 @@ * under the License. */ -use crate::engine::messages::{InMessagesQueue, QueuedMessage}; +use crate::engine::messages::InMessagesQueue; use crate::engine::MessagesReceiver; use crate::error::NodeResult; use iron::{ @@ -95,7 +95,7 @@ impl MessageReceiverApi { } }; - let mut message = QueuedMessage::with_message(message).unwrap(); + let mut message = message; while let Err(msg) = queue.queue(message) { if queue.has_delivery_problems() { log::warn!(target: "node", "Request was refused because downstream services are not accessible"); diff --git a/node/src/block/applier.rs b/node/src/block/applier.rs deleted file mode 100644 index e245054..0000000 --- a/node/src/block/applier.rs +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Copyright 2018-2022 TON DEV SOLUTIONS LTD. -* -* Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use -* this file except in compliance with the License. You may obtain a copy of the -* License at: -* -* https://www.ton.dev/licenses -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific TON DEV software governing permissions and limitations -* under the License. -*/ - -use crate::data::DocumentsDb; -use crate::NodeResult; -use std::sync::Arc; -use parking_lot::Mutex; -use ton_block::{BlkPrevInfo, Block, ShardStateUnsplit}; -use ton_types::UInt256; - -/// Trait for save finality states blockchain -pub trait BlockFinality { - fn put_block_with_info( - &mut self, - block: &Block, - shard_state: Arc, - ) -> NodeResult<()>; - - fn get_last_seq_no(&self) -> u32; - - fn get_last_block_info(&self) -> NodeResult; - - fn get_last_shard_state(&self) -> Arc; - - fn find_block_by_hash(&self, hash: &UInt256) -> u64; - - fn rollback_to(&mut self, hash: &UInt256) -> NodeResult<()>; - - fn get_raw_block_by_seqno(&self, seq_no: u32, vert_seq_no: u32) -> NodeResult>; - - fn get_last_finality_shard_hash(&self) -> NodeResult<(u64, UInt256)>; - - fn reset(&mut self) -> NodeResult<()>; -} - -/// Applies changes provided by new block to shard state (in memory instance) -/// and saves all changes into all kinds of storages -#[allow(dead_code)] -pub struct NewBlockApplier -where - F: BlockFinality, -{ - db: Arc, - finality: Arc>, -} - -impl NewBlockApplier -where - F: BlockFinality, -{ - /// Create new NewBlockApplier with given storages and shard state - pub fn with_params(finality: Arc>, db: Arc) -> Self { - NewBlockApplier { finality, db } - } - - /// Applies changes provided by given block, returns new shard state - pub fn apply( - &mut self, - block: &Block, - applied_shard: ShardStateUnsplit, - ) -> NodeResult> { - let mut finality = self.finality.lock(); - let new_shard_state = Arc::new(applied_shard); - - log::info!(target: "node", "Apply block seq_no = {}", block.read_info()?.seq_no()); - - finality.put_block_with_info(block, new_shard_state.clone())?; - - Ok(new_shard_state) - } -} diff --git a/node/src/block/builder.rs b/node/src/block/builder.rs index 689a820..f164af7 100644 --- a/node/src/block/builder.rs +++ b/node/src/block/builder.rs @@ -19,19 +19,19 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use ton_block::{ Account, AddSub, Augmentation, BlkPrevInfo, Block, BlockExtra, BlockInfo, ComputeSkipReason, - CurrencyCollection, Deserializable, EnqueuedMsg, HashUpdate, HashmapAugType, InMsg, InMsgDescr, - MerkleUpdate, Message, MsgEnvelope, OutMsg, OutMsgDescr, OutMsgQueue, OutMsgQueueInfo, - OutMsgQueueKey, Serializable, ShardAccount, ShardAccountBlocks, ShardAccounts, ShardIdent, - ShardStateUnsplit, TrComputePhase, TrComputePhaseVm, Transaction, TransactionDescr, - TransactionDescrOrdinary, UnixTime32, ValueFlow, CopyleftRewards, + CopyleftRewards, CurrencyCollection, Deserializable, EnqueuedMsg, HashUpdate, HashmapAugType, + InMsg, InMsgDescr, MerkleUpdate, Message, MsgEnvelope, OutMsg, OutMsgDescr, OutMsgQueue, + OutMsgQueueInfo, OutMsgQueueKey, Serializable, ShardAccount, ShardAccountBlocks, ShardAccounts, + ShardIdent, ShardStateUnsplit, TrComputePhase, TrComputePhaseVm, Transaction, TransactionDescr, + TransactionDescrOrdinary, UnixTime32, ValueFlow, }; use ton_executor::{ BlockchainConfig, ExecuteParams, ExecutorError, OrdinaryTransactionExecutor, TransactionExecutor, }; -use ton_types::{error, AccountId, Cell, HashmapRemover, HashmapType, Result, UInt256, SliceData}; +use ton_types::{error, AccountId, Cell, HashmapRemover, HashmapType, Result, SliceData, UInt256}; -use crate::engine::{InMessagesQueue, QueuedMessage}; +use crate::engine::InMessagesQueue; use crate::error::NodeResult; #[cfg(test)] @@ -145,6 +145,7 @@ impl BlockBuilder { last_tr_lt: Arc::clone(<), seed_block: self.rand_seed.clone(), debug, + signature_id: self.shard_state.global_id(), ..Default::default() }, ); @@ -201,20 +202,23 @@ impl BlockBuilder { pub fn execute( &mut self, - msg: QueuedMessage, - blockchain_config: BlockchainConfig, + message: Message, + blockchain_config: &BlockchainConfig, acc_id: &AccountId, debug: bool, ) -> NodeResult<()> { let shard_acc = self.accounts.account(acc_id)?.unwrap_or_default(); let mut acc_root = shard_acc.account_cell(); - let executor = OrdinaryTransactionExecutor::new(blockchain_config); + let executor = OrdinaryTransactionExecutor::new((*blockchain_config).clone()); - log::debug!("Executing message {:x}", msg.message_hash()); + log::debug!( + "Executing message {:x}", + message.serialize().unwrap_or_default().repr_hash() + ); let (mut transaction, max_lt) = self.try_prepare_transaction( &executor, &mut acc_root, - msg.message(), + &message, shard_acc.last_trans_lt(), debug, )?; @@ -253,9 +257,9 @@ impl BlockBuilder { pub fn build_block( mut self, queue: &InMessagesQueue, - blockchain_config: BlockchainConfig, + blockchain_config: &BlockchainConfig, debug: bool, - ) -> NodeResult> { + ) -> NodeResult<(Block, ShardStateUnsplit, bool)> { let mut is_empty = true; // first import internal messages @@ -270,15 +274,16 @@ impl BlockBuilder { // key is not matter for one shard sorted.push((key, OutMsgQueue::value_aug(&mut slice)?)); } - sorted.sort_by(|a, b| a.1.1.cmp(&b.1.1)); + sorted.sort_by(|a, b| a.1 .1.cmp(&b.1 .1)); for (key, (enq, _create_lt)) in sorted { let env = enq.read_out_msg()?; let message = env.read_message()?; if let Some(acc_id) = message.int_dst_account_id() { - let msg = QueuedMessage::with_message(message)?; - self.execute(msg, blockchain_config.clone(), &acc_id, debug)?; + self.execute(message, blockchain_config, &acc_id, debug)?; } - self.out_queue_info.out_queue_mut().remove(SliceData::load_cell(key)?)?; + self.out_queue_info + .out_queue_mut() + .remove(SliceData::load_cell(key)?)?; // TODO: check block full is_empty = false; if self.total_gas_used > 1_000_000 { @@ -286,12 +291,13 @@ impl BlockBuilder { break; } } + let workchain_id = self.shard_state.shard().workchain_id(); // second import external messages - while let Some(msg) = queue.dequeue() { - let acc_id = msg.message().int_dst_account_id().unwrap(); + while let Some(msg) = queue.dequeue(workchain_id) { + let acc_id = msg.int_dst_account_id().unwrap(); // lock account in queue - let res = self.execute(msg, blockchain_config.clone(), &acc_id, debug); + let res = self.execute(msg, blockchain_config, &acc_id, debug); if let Err(err) = res { log::warn!(target: "node", "Executor execute failed. {}", err); } else { @@ -328,12 +334,7 @@ impl BlockBuilder { self.out_msg_descr .set(&msg_cell.repr_hash(), &out_msg, &out_msg.aug()?)?; } else { - self.execute( - QueuedMessage::with_message(message)?, - blockchain_config.clone(), - &acc_id, - debug, - )?; + self.execute(message, blockchain_config, &acc_id, debug)?; if self.total_gas_used > 1_000_000 { block_full = true; } @@ -343,15 +344,11 @@ impl BlockBuilder { } if !is_empty { log::info!(target: "node", "in messages queue len={}", queue.len()); - // let seq_no = self.block_info.seq_no(); - let (block, new_shard_state) = self.finalize_block()?; - // let block_text = ton_block_json::debug_block_full(&block)?; - // std::fs::write(&format!("e:\\block_{}.json", seq_no), block_text)?; - Ok(Some((block, new_shard_state))) } else { log::debug!(target: "node", "block is empty in messages queue len={}", queue.len()); - Ok(None) } + let (block, new_shard_state) = self.finalize_block()?; + Ok((block, new_shard_state, is_empty)) } /// @@ -366,9 +363,10 @@ impl BlockBuilder { self.account_blocks .add_serialized_transaction(&transaction, &tr_cell)?; - + if let Some(copyleft_reward) = transaction.copyleft_reward() { - self.copyleft_rewards.add_copyleft_reward(©left_reward.address, ©left_reward.reward)?; + self.copyleft_rewards + .add_copyleft_reward(©left_reward.address, ©left_reward.reward)?; } if let Some(msg_cell) = transaction.in_msg_cell() { @@ -468,7 +466,13 @@ impl BlockBuilder { // let state_update = MerkleUpdate::create(&old_ss_root, &new_ss_root)?; let state_update = MerkleUpdate::default(); - let block = Block::with_params(0, self.block_info, value_flow, state_update, block_extra)?; + let block = Block::with_params( + self.shard_state.global_id(), + self.block_info, + value_flow, + state_update, + block_extra, + )?; Ok((block, new_shard_state)) } } diff --git a/node/src/block/finality.rs b/node/src/block/finality.rs index 9a84bdb..01ada7c 100644 --- a/node/src/block/finality.rs +++ b/node/src/block/finality.rs @@ -14,14 +14,13 @@ * under the License. */ -use crate::block::applier::BlockFinality; use crate::data::{ - BlocksStorage, DocumentsDb, FileBasedStorage, FinalityStorage, ShardStateInfo, - ShardStateStorage, TransactionsStorage, SerializedItem, + BlocksStorage, DocumentsDb, FileBasedStorage, FinalityStorage, SerializedItem, ShardStateInfo, + ShardStateStorage, TransactionsStorage, }; use crate::error::NodeError; use crate::NodeResult; -use std::collections::{HashSet, BTreeMap}; +use std::collections::{BTreeMap, HashSet}; use std::{ collections::HashMap, fs::{create_dir_all, File}, @@ -38,7 +37,7 @@ mod tests; lazy_static::lazy_static!( static ref ACCOUNT_NONE_HASH: UInt256 = Account::default().serialize().unwrap().repr_hash(); - pub static ref MINTER_ADDRESS: MsgAddressInt = + pub static ref MINTER_ADDRESS: MsgAddressInt = MsgAddressInt::AddrStd(MsgAddrStd::with_address(None, 0, [0; 32].into())); ); @@ -67,8 +66,10 @@ where db: Option>, current_block: Box, - blocks_by_hash: HashMap>, // need to remove - blocks_by_no: HashMap>, // need to remove + blocks_by_hash: HashMap>, + // need to remove + blocks_by_no: HashMap>, + // need to remove last_finalized_block: Box, } @@ -86,6 +87,7 @@ where /// Create new instance BlockFinality /// with all kind of storages pub fn with_params( + global_id: i32, shard_ident: ShardIdent, root_path: PathBuf, shard_state_storage: Arc, @@ -99,20 +101,24 @@ where .expect("cannot create shards directory"); OrdinaryBlockFinality { - shard_ident, + shard_ident: shard_ident.clone(), root_path, shard_state_storage, blocks_storage, _tr_storage, fn_storage, db, - current_block: Box::new(ShardBlock::default()), + current_block: Box::new(ShardBlock::new(global_id, shard_ident.clone())), blocks_by_hash: HashMap::new(), blocks_by_no: HashMap::new(), - last_finalized_block: Box::new(ShardBlock::default()), + last_finalized_block: Box::new(ShardBlock::new(global_id, shard_ident.clone())), } } + pub(crate) fn get_last_info(&self) -> NodeResult<(Arc, BlkPrevInfo)> { + Ok((self.get_last_shard_state(), self.get_last_block_info()?)) + } + fn finality_blocks(&mut self, root_hash: UInt256) -> NodeResult<()> { log::debug!("FIN-BLK {:x}", root_hash); if let Some(fin_sb) = self.blocks_by_hash.remove(&root_hash) { @@ -245,7 +251,6 @@ where /// /// Write data BlockFinality to file - /// fn serialize(&self, writer: &mut dyn Write) -> NodeResult<()> { // serialize struct: // 32bit - length of structure ShardBlock @@ -292,7 +297,10 @@ where let seq_no = rdr.read_le_u64()?; log::info!(target: "node", "read_one_sb:seq_no: {}", seq_no); if seq_no == 0 { - Ok(Box::new(ShardBlock::default())) + Ok(Box::new(ShardBlock::new( + self.current_block.block.global_id, + self.shard_ident.clone(), + ))) } else { let mut current_block_name = block_finality_path.clone(); current_block_name.push(hash.to_hex_string()); @@ -342,7 +350,6 @@ where Ok(()) } - fn prepare_messages_from_transaction( transaction: &Transaction, block_id: UInt256, @@ -353,7 +360,7 @@ where if let Some(message_cell) = transaction.in_msg_cell() { let message = Message::construct_from_cell(message_cell.clone())?; let message_id = message_cell.repr_hash(); - let mut doc = + let mut doc = if message.is_inbound_external() || message.src_ref() == Some(&MINTER_ADDRESS) { Self::prepare_message_json( message_cell, @@ -363,21 +370,21 @@ where Some(transaction.now()), )? } else { - messages.remove(&message_id) - .unwrap_or_else(|| { - let mut doc = serde_json::value::Map::with_capacity(2); - doc.insert("id".into(), message_id.as_hex_string().into()); - doc - }) + messages.remove(&message_id).unwrap_or_else(|| { + let mut doc = serde_json::value::Map::with_capacity(2); + doc.insert("id".into(), message_id.as_hex_string().into()); + doc + }) }; - + doc.insert( "dst_chain_order".into(), - format!("{}{}", tr_chain_order, ton_block_json::u64_to_string(0)).into()); - + format!("{}{}", tr_chain_order, ton_block_json::u64_to_string(0)).into(), + ); + messages.insert(message_id, doc); }; - + let mut index: u64 = 1; transaction.out_msgs.iterate_slices(|slice| { let message_cell = slice.reference(0)?; @@ -390,17 +397,18 @@ where block_id.clone(), None, // transaction_now affects ExtIn messages only )?; - + // messages are ordered by created_lt doc.insert( "src_chain_order".into(), - format!("{}{}", tr_chain_order, ton_block_json::u64_to_string(index)).into()); - + format!("{}{}", tr_chain_order, ton_block_json::u64_to_string(index)).into(), + ); + index += 1; messages.insert(message_id, doc); Ok(true) })?; - + Ok(()) } @@ -415,7 +423,7 @@ where let proof = block_root_for_proof .map(|cell| serialize_toc(&message.prepare_proof(true, cell)?)) .transpose()?; - + let set = ton_block_json::MessageSerializationSet { message, id: message_cell.repr_hash(), @@ -438,7 +446,7 @@ where } fn prepare_transaction_json( - tr_cell: Cell, + tr_cell: Cell, transaction: Transaction, block_root: &Cell, block_id: UInt256, @@ -469,7 +477,7 @@ where account: Account, prev_account_state: Option, last_trans_chain_order: Option, - ) -> Result { + ) -> Result { let mut boc1 = None; if account.init_code_hash().is_some() { // new format @@ -487,10 +495,13 @@ where boc1, ..Default::default() }; - + let mut doc = ton_block_json::db_serialize_account("id", &set)?; if let Some(last_trans_chain_order) = last_trans_chain_order { - doc.insert("last_trans_chain_order".to_owned(), last_trans_chain_order.into()); + doc.insert( + "last_trans_chain_order".to_owned(), + last_trans_chain_order.into(), + ); } Ok(Self::doc_to_item(doc)) } @@ -510,7 +521,10 @@ where let mut doc = ton_block_json::db_serialize_deleted_account("id", &set)?; if let Some(last_trans_chain_order) = last_trans_chain_order { - doc.insert("last_trans_chain_order".to_owned(), last_trans_chain_order.into()); + doc.insert( + "last_trans_chain_order".to_owned(), + last_trans_chain_order.into(), + ); } Ok(Self::doc_to_item(doc)) } @@ -537,7 +551,7 @@ where pub fn reflect_block_in_db(&self, shard_block: &ShardBlock) -> Result<()> { let db = match self.db.clone() { Some(db) => db, - None => return Ok(()) + None => return Ok(()), }; let add_proof = false; @@ -554,7 +568,7 @@ where let shard_accounts = shard_block.shard_state.read_accounts()?; let now_all = std::time::Instant::now(); - + // Prepare sorted ton_block transactions and addresses of changed accounts let mut changed_acc = HashSet::new(); let mut deleted_acc = HashSet::new(); @@ -562,44 +576,54 @@ where let now = std::time::Instant::now(); let mut tr_count = 0; let mut transactions = BTreeMap::new(); - block_extra.read_account_blocks()?.iterate_objects(|account_block: AccountBlock| { - // extract ids of changed accounts - let state_upd = account_block.read_state_update()?; - let mut check_account_existed = false; - if state_upd.new_hash == *ACCOUNT_NONE_HASH { - deleted_acc.insert(account_block.account_id().clone()); - if state_upd.old_hash == *ACCOUNT_NONE_HASH { - check_account_existed = true; + block_extra + .read_account_blocks()? + .iterate_objects(|account_block: AccountBlock| { + // extract ids of changed accounts + let state_upd = account_block.read_state_update()?; + let mut check_account_existed = false; + if state_upd.new_hash == *ACCOUNT_NONE_HASH { + deleted_acc.insert(account_block.account_id().clone()); + if state_upd.old_hash == *ACCOUNT_NONE_HASH { + check_account_existed = true; + } + } else { + changed_acc.insert(account_block.account_id().clone()); } - } else { - changed_acc.insert(account_block.account_id().clone()); - } - let mut account_existed = false; - account_block.transactions().iterate_slices(|_, transaction_slice| { - // extract transactions - let cell = transaction_slice.reference(0)?; - let transaction = Transaction::construct_from(&mut SliceData::load_cell(cell.clone())?)?; - let ordering_key = (transaction.logical_time(), transaction.account_id().clone()); - if transaction.orig_status != AccountStatus::AccStateNonexist || - transaction.end_status != AccountStatus::AccStateNonexist - { - account_existed = true; + let mut account_existed = false; + account_block + .transactions() + .iterate_slices(|_, transaction_slice| { + // extract transactions + let cell = transaction_slice.reference(0)?; + let transaction = + Transaction::construct_from(&mut SliceData::load_cell(cell.clone())?)?; + let ordering_key = + (transaction.logical_time(), transaction.account_id().clone()); + if transaction.orig_status != AccountStatus::AccStateNonexist + || transaction.end_status != AccountStatus::AccStateNonexist + { + account_existed = true; + } + transactions.insert(ordering_key, (cell, transaction)); + tr_count += 1; + + Ok(true) + })?; + + if check_account_existed && !account_existed { + deleted_acc.remove(account_block.account_id()); } - transactions.insert(ordering_key, (cell, transaction)); - tr_count += 1; Ok(true) })?; - - if check_account_existed && !account_existed { - deleted_acc.remove(account_block.account_id()); - } - - Ok(true) - })?; - log::trace!("TIME: preliminary prepare {} transactions {}ms; {}", tr_count, now.elapsed().as_millis(), block_id); - + log::trace!( + "TIME: preliminary prepare {} transactions {}ms; {}", + tr_count, + now.elapsed().as_millis(), + block_id + ); // Iterate ton_block transactions to: // - prepare messages and transactions for external db @@ -608,8 +632,12 @@ where let mut index = 0; let mut messages = Default::default(); for (_, (cell, transaction)) in transactions.into_iter() { - let tr_chain_order = format!("{}{}", block_order, ton_block_json::u64_to_string(index as u64)); - + let tr_chain_order = format!( + "{}{}", + block_order, + ton_block_json::u64_to_string(index as u64) + ); + Self::prepare_messages_from_transaction( &transaction, block_root.repr_hash(), @@ -622,16 +650,16 @@ where acc_last_trans_chain_order.insert(account_id, tr_chain_order.clone()); let mut doc = Self::prepare_transaction_json( - cell, + cell, transaction, &block_root, block_root.repr_hash(), workchain_id, - add_proof + add_proof, )?; doc.insert("chain_order".into(), tr_chain_order.into()); db.put_transaction(Self::doc_to_item(doc))?; - + index += 1; } let msg_count = messages.len(); // is 0 if not process_message @@ -646,17 +674,16 @@ where block_id, ); - // Prepare accounts (changed and deleted) let now = std::time::Instant::now(); for account_id in changed_acc.iter() { - let acc = shard_accounts.account(account_id)? - .ok_or_else(|| - NodeError::InvalidData( - "Block and shard state mismatch: \ - state doesn't contain changed account".to_string() - ) - )?; + let acc = shard_accounts.account(account_id)?.ok_or_else(|| { + NodeError::InvalidData( + "Block and shard state mismatch: \ + state doesn't contain changed account" + .to_string(), + ) + })?; let acc = acc.read_account()?; db.put_account(Self::prepare_account_record( @@ -675,35 +702,37 @@ where last_trans_chain_order, )?)?; } - log::trace!("TIME: accounts {} {}ms; {}", changed_acc.len(), now.elapsed().as_millis(), block_id); + log::trace!( + "TIME: accounts {} {}ms; {}", + changed_acc.len(), + now.elapsed().as_millis(), + block_id + ); // Block let now = std::time::Instant::now(); - db.put_block( - Self::prepare_block_record( - block, - &block_root, - block_boc, - &file_hash, - block_order.clone(), - )? - )?; - log::trace!("TIME: block {}ms; {}", now.elapsed().as_millis(), block_id); - log::trace!("TIME: prepare & build jsons {}ms; {}", now_all.elapsed().as_millis(), block_id); + db.put_block(Self::prepare_block_record( + block, + &block_root, + block_boc, + &file_hash, + block_order.clone(), + )?)?; + log::trace!( + "TIME: block {}ms; {}", + now.elapsed().as_millis(), + block_id + ); + log::trace!( + "TIME: prepare & build jsons {}ms; {}", + now_all.elapsed().as_millis(), + block_id + ); Ok(()) } -} - -impl BlockFinality for OrdinaryBlockFinality -where - S: ShardStateStorage, - B: BlocksStorage, - T: TransactionsStorage, - F: FinalityStorage, -{ /// Save block until finality comes - fn put_block_with_info( + pub(crate) fn put_block_with_info( &mut self, block: &Block, shard_state: Arc, @@ -727,7 +756,7 @@ where } /// get last block sequence number - fn get_last_seq_no(&self) -> u32 { + pub(crate) fn get_last_seq_no(&self) -> u32 { self.current_block.block.read_info().unwrap().seq_no() } @@ -749,8 +778,9 @@ where //log::warn!("LAST SHARD BAG {}", self.current_block.shard_bag.get_repr_hash_by_index(0).unwrap().to_hex_string())); Arc::clone(&self.current_block.shard_state) } - /// find block by hash and return his sequence number (for sync) - fn find_block_by_hash(&self, hash: &UInt256) -> u64 { + + #[cfg(test)] + pub fn find_block_by_hash(&self, hash: &UInt256) -> u64 { if self.blocks_by_hash.contains_key(hash) { self.blocks_by_hash.get(hash).unwrap().seq_no() } else { @@ -759,7 +789,8 @@ where } /// Rollback shard state to one of block candidates - fn rollback_to(&mut self, hash: &UInt256) -> NodeResult<()> { + #[cfg(test)] + pub fn rollback_to(&mut self, hash: &UInt256) -> NodeResult<()> { if self.blocks_by_hash.contains_key(hash) { let sb = self.blocks_by_hash.remove(hash).unwrap(); let mut seq_no = sb.seq_no(); @@ -782,41 +813,7 @@ where } } - /// get raw signed block data - for synchronize - fn get_raw_block_by_seqno(&self, seq_no: u32, vert_seq_no: u32) -> NodeResult> { - let key = key_by_seqno(seq_no, vert_seq_no); - if self.blocks_by_no.contains_key(&key) { - /* TODO: which case to use? - return Ok(self.blocks_by_no.get(&key).unwrap().serialized_block.clone()) - TODO rewrite to - return Ok( - self.fn_storage.load_non_finalized_block_by_seq_no(key)?.serialized_block.clone() - )*/ - return Ok(self - .stored_to_loaded(self.blocks_by_no.get(&key).unwrap().clone())? - .serialized_block - .clone()); - } - self.blocks_storage.raw_block(seq_no, vert_seq_no) - } - /// get number of last finalized shard - fn get_last_finality_shard_hash(&self) -> NodeResult<(u64, UInt256)> { - // TODO avoid serialization there - let cell = self.last_finalized_block.shard_state.serialize()?; - - Ok((self.last_finalized_block.seq_no, cell.repr_hash())) - } - - /// reset block finality - /// clean all maps, load last finalized data - fn reset(&mut self) -> NodeResult<()> { - self.current_block = self.last_finalized_block.clone(); - // remove files from disk - self.blocks_by_hash.clear(); - self.blocks_by_no.clear(); - Ok(()) - } } #[derive(Clone, Debug, PartialEq)] @@ -833,6 +830,7 @@ impl FinalityBlock { } } + #[cfg(test)] pub fn root_hash(&self) -> &UInt256 { match self { FinalityBlock::Stored(sb) => &sb.root_hash, @@ -867,20 +865,23 @@ pub struct ShardBlock { shard_state: Arc, } -impl Default for ShardBlock { - fn default() -> Self { +impl ShardBlock { + fn new(global_id: i32, shard: ShardIdent) -> Self { + let mut shard_state = ShardStateUnsplit::default(); + shard_state.set_global_id(global_id); + shard_state.set_shard(shard); + let mut block = Block::default(); + block.global_id = global_id; Self { seq_no: 0, serialized_block: Vec::new(), root_hash: UInt256::ZERO, file_hash: UInt256::ZERO, - block: Block::default(), - shard_state: Arc::new(ShardStateUnsplit::default()), + block, + shard_state: Arc::new(shard_state), } } -} -impl ShardBlock { /// get current block sequence number pub fn get_seq_no(&self) -> u64 { self.seq_no @@ -923,7 +924,7 @@ impl ShardBlock { /// deserialize shard block pub fn deserialize(rdr: &mut R) -> NodeResult { - let mut sb = ShardBlock::default(); + let mut sb = ShardBlock::new(0, ShardIdent::default()); sb.seq_no = rdr.read_le_u64()?; let sb_len = rdr.read_le_u32()?; let mut sb_buf = vec![0; sb_len as usize]; @@ -941,7 +942,6 @@ impl ShardBlock { let cell = deserialize_tree_of_cells(rdr)?; sb.block = Block::construct_from_cell(cell)?; - Ok(sb) } } @@ -967,7 +967,8 @@ pub fn generate_block_with_seq_no( (0..32).map(|_| rand::random::()).collect::>(), 256, ); - let mut transaction = Transaction::with_address_and_status(acc.clone(), AccountStatus::AccStateActive); + let mut transaction = + Transaction::with_address_and_status(acc.clone(), AccountStatus::AccStateActive); let mut value = CurrencyCollection::default(); value.grams = 10202u64.into(); let mut imh = InternalMessageHeader::with_addresses( @@ -990,7 +991,8 @@ pub fn generate_block_with_seq_no( inmsg1.set_body(SliceData::new(vec![0x21; 120])); let ext_in_header = ExternalInboundMessageHeader { - src: MsgAddressExt::with_extern(SliceData::new(vec![0x23, 0x52, 0x73, 0x00, 0x80])).unwrap(), + src: MsgAddressExt::with_extern(SliceData::new(vec![0x23, 0x52, 0x73, 0x00, 0x80])) + .unwrap(), dst: MsgAddressInt::with_standart(None, 0, acc.clone()).unwrap(), import_fee: 10u64.into(), }; @@ -1015,8 +1017,7 @@ pub fn generate_block_with_seq_no( let ext_out_header = ExtOutMessageHeader::with_addresses( MsgAddressInt::with_standart(None, 0, acc.clone()).unwrap(), - MsgAddressExt::with_extern(SliceData::new(vec![0x23, 0x52, 0x73, 0x00, 0x80])) - .unwrap(), + MsgAddressExt::with_extern(SliceData::new(vec![0x23, 0x52, 0x73, 0x00, 0x80])).unwrap(), ); let mut outmsg2 = Message::with_ext_out_header(ext_out_header); @@ -1026,7 +1027,9 @@ pub fn generate_block_with_seq_no( transaction.add_out_message(&outmsg2).unwrap(); let tr_cell = transaction.serialize().unwrap(); - block_builder.add_raw_transaction(transaction, tr_cell).unwrap(); + block_builder + .add_raw_transaction(transaction, tr_cell) + .unwrap(); } let (block, _) = block_builder.finalize_block().unwrap(); block diff --git a/node/src/block/mod.rs b/node/src/block/mod.rs index b264636..d1f514d 100644 --- a/node/src/block/mod.rs +++ b/node/src/block/mod.rs @@ -1,9 +1,5 @@ -mod applier; mod builder; pub mod finality; -pub use applier::{BlockFinality, NewBlockApplier}; pub use builder::BlockBuilder; -pub use finality::{ - FinalityBlock, OrdinaryBlockFinality, ShardBlock, ShardBlockHash, -}; +pub use finality::{FinalityBlock, OrdinaryBlockFinality, ShardBlock, ShardBlockHash}; diff --git a/node/src/config.rs b/node/src/config.rs index 1dcdc71..8c43b6e 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -89,6 +89,8 @@ pub struct NodeConfig { pub private_key: String, pub keys: Vec, pub boot: Vec, + #[serde(default = "NodeConfig::default_global_id")] + pub global_id: i32, pub shard_id: ShardIdConfig, pub document_db: serde_json::Value, #[serde(default = "NodeConfig::default_log_path")] @@ -98,6 +100,9 @@ pub struct NodeConfig { } impl NodeConfig { + fn default_global_id() -> i32 { + 0 + } fn default_log_path() -> String { "./log_cfg.yml".to_string() } diff --git a/node/src/data/arango.rs b/node/src/data/arango.rs index 926fabb..750ea92 100644 --- a/node/src/data/arango.rs +++ b/node/src/data/arango.rs @@ -197,7 +197,7 @@ impl ArangoHelper { log::error!(target: "node", "error sending to arango {}, ({:?})", url, resp.status().canonical_reason()); } else { has_delivery_problems.store(false, Ordering::SeqCst); - log::debug!(target: "node", "sucessfully sent to arango"); + log::debug!(target: "node", "successfully sent to arango"); break; } } diff --git a/node/src/data/file_based_storage.rs b/node/src/data/file_based_storage.rs index 2ca9ed1..df618fe 100644 --- a/node/src/data/file_based_storage.rs +++ b/node/src/data/file_based_storage.rs @@ -15,6 +15,7 @@ */ use super::{BlocksStorage, ShardStateStorage, TransactionsStorage}; +use crate::data::{FinalityStorage, ShardStateInfo}; use crate::error::NodeResult; use parking_lot::Mutex; use std; @@ -30,7 +31,6 @@ use ton_block::{ }; use ton_types::cells_serialization::{deserialize_tree_of_cells, serialize_tree_of_cells}; use ton_types::{types::UInt256, AccountId, Cell}; -use crate::data::{FinalityStorage, ShardStateInfo}; #[cfg(test)] #[path = "../../../../tonos-se-tests/unit/test_file_based_storage.rs"] @@ -54,7 +54,6 @@ impl ShardHash { shard_hash: UInt256::from([0; 32]), } } - } impl Ord for ShardHash { @@ -105,8 +104,7 @@ impl FileBasedStorage { /// Create "Shards" directory pub fn create_workchains_dir(root: &PathBuf) -> NodeResult { - let mut shards = root.clone(); - shards.push("workchains"); + let shards = root.join("workchains"); if !shards.as_path().exists() { create_dir_all(shards.as_path())?; } @@ -115,37 +113,34 @@ impl FileBasedStorage { /// /// Create catalog tree for storage - /// root_path/Shards/ - /// /Shard_(PFX)/Shard - /// /Blocks/Block_(seq_no)_(ver_no) + /// root_path + /// workchains + /// MC | WC + /// shard_(prefix) + /// blocks + /// block_(seq_no)_(ver_no) /// /// returned Shard_state_path and Blocks_dir_path pub fn create_default_shard_catalog( - mut workchains_dir: PathBuf, + workchains_dir: PathBuf, shard_ident: &ShardIdent, ) -> NodeResult<(PathBuf, PathBuf, PathBuf)> { - workchains_dir.push(format!("WC{}", shard_ident.workchain_id())); - workchains_dir.push(format!( - "shard_{:016x}", - shard_ident.shard_prefix_with_tag() - )); - if !workchains_dir.as_path().exists() { - create_dir_all(workchains_dir.as_path())?; - } - - let mut shard_blocks_dir = workchains_dir.clone(); - shard_blocks_dir.push("blocks"); - if !shard_blocks_dir.as_path().exists() { - create_dir_all(shard_blocks_dir.as_path())?; + let workchain_name = if shard_ident.is_masterchain() { + "MC".to_string() + } else { + format!("WC{}", shard_ident.workchain_id()) + }; + let shard_name = format!("shard_{:016x}", shard_ident.shard_prefix_with_tag()); + let shard_dir = workchains_dir.join(workchain_name).join(shard_name); + let blocks_dir = shard_dir.join("blocks"); + let transactions_dir = shard_dir.join("transactions"); + if !blocks_dir.as_path().exists() { + create_dir_all(blocks_dir.as_path())?; } - - let mut transactions_dir = workchains_dir.clone(); - transactions_dir.push("transactions"); if !transactions_dir.as_path().exists() { create_dir_all(transactions_dir.as_path())?; } - - Ok((workchains_dir, shard_blocks_dir, transactions_dir)) + Ok((shard_dir, blocks_dir, transactions_dir)) } fn key_by_seqno(seq_no: u32, vert_seq_no: u32) -> u64 { @@ -516,4 +511,3 @@ impl TransactionsStorage for FileBasedStorage { // shard_data: Option>, shard_hash: &UInt256, // shard_state_info: ShardStateInfo) -> NodeResult<()>; // } - diff --git a/node/src/engine/engine.rs b/node/src/engine/engine.rs index 26035f1..a7769b9 100644 --- a/node/src/engine/engine.rs +++ b/node/src/engine/engine.rs @@ -15,44 +15,39 @@ */ use crate::block::finality::MINTER_ADDRESS; -use crate::block::{BlockBuilder, BlockFinality, NewBlockApplier, OrdinaryBlockFinality}; #[cfg(test)] use crate::config::NodeConfig; -use crate::data::{DocumentsDb, DocumentsDbMock, FileBasedStorage}; +use crate::data::DocumentsDb; +use crate::engine::masterchain::Masterchain; +use crate::engine::shardchain::Shardchain; use crate::engine::{ - InMessagesQueue, LiveControl, LiveControlReceiver, QueuedMessage, - DEPRECATED_GIVER_ABI2_DEPLOY_MSG, GIVER_ABI1_DEPLOY_MSG, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, - MULTISIG_BALANCE, MULTISIG_DEPLOY_MSG, + InMessagesQueue, LiveControl, LiveControlReceiver, DEPRECATED_GIVER_ABI2_DEPLOY_MSG, + GIVER_ABI1_DEPLOY_MSG, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, MULTISIG_BALANCE, + MULTISIG_DEPLOY_MSG, }; -use crate::error::{NodeError, NodeResult}; +use crate::error::NodeResult; use crate::MessagesReceiver; use parking_lot::Mutex; use std::path::PathBuf; use std::{ - io::ErrorKind, sync::{ atomic::{AtomicU32, Ordering}, Arc, }, thread, - time::{Duration, Instant}, + time::Duration, }; use ton_block::{ - Block, CommonMsgInfo, CurrencyCollection, Deserializable, Grams, InternalMessageHeader, - Message, MsgAddressInt, ShardIdent, ShardStateUnsplit, UnixTime32, + CommonMsgInfo, CurrencyCollection, Deserializable, Grams, InternalMessageHeader, Message, + MsgAddressInt, ShardIdent, UnixTime32, }; use ton_executor::BlockchainConfig; -use ton_types::{AccountId, HashmapType}; +use ton_types::AccountId; #[cfg(test)] #[path = "../../../../tonos-se-tests/unit/test_ton_node_engine.rs"] mod tests; -type Storage = FileBasedStorage; -type ArcBlockFinality = Arc>>; -type BlockApplier = - Mutex>>; - pub struct EngineLiveProperties { pub time_delta: Arc, } @@ -108,14 +103,12 @@ impl LiveControl for EngineLiveControl { /// It is top level struct provided node functionality related to transactions processing. /// Initialises instances of: all messages receivers, InMessagesQueue, MessagesProcessor. pub struct TonNodeEngine { - shard_ident: ShardIdent, live_properties: Arc, receivers: Vec>>, live_control_receiver: Option>, - pub blockchain_config: BlockchainConfig, - pub finalizer: ArcBlockFinality, - pub block_applier: BlockApplier, pub message_queue: Arc, + pub masterchain: Masterchain, + pub workchain: Shardchain, } impl TonNodeEngine { @@ -129,12 +122,11 @@ impl TonNodeEngine { control_receiver.run(Box::new(live_control))?; } - if self.finalizer.lock().get_last_seq_no() == 1 { - let workchain_id = self.current_shard_id().workchain_id() as i8; - self.deploy_contracts(workchain_id)?; + if self.workchain.finalizer.lock().get_last_seq_no() == 1 { + self.initialize_blockchain()?; } thread::spawn(move || loop { - if let Err(err) = self.prepare_block(true) { + if let Err(err) = self.generate_blocks(true) { log::error!(target: "node", "failed block generation: {}", err); } }); @@ -150,124 +142,74 @@ impl TonNodeEngine { /// Construct new engine for selected shard /// with given time to generate block candidate pub fn with_params( - shard: ShardIdent, + global_id: i32, + workchain_shard: ShardIdent, receivers: Vec>, live_control_receiver: Option>, - blockchain_config: BlockchainConfig, - documents_db: Option>, + blockchain_config: Arc, + documents_db: Arc, storage_path: PathBuf, ) -> NodeResult { - let documents_db = documents_db.unwrap_or_else(|| Arc::new(DocumentsDbMock)); let message_queue = Arc::new(InMessagesQueue::with_db(10000, documents_db.clone())); - - let storage = Arc::new(Storage::with_path(shard.clone(), storage_path.clone())?); - let block_finality = Arc::new(Mutex::new(OrdinaryBlockFinality::with_params( - shard.clone(), - storage_path, - storage.clone(), - storage.clone(), - storage.clone(), - storage.clone(), - Some(documents_db.clone()), - Vec::new(), - ))); - match block_finality.lock().load() { - Ok(_) => { - log::info!(target: "node", "load block finality successfully"); - } - Err(NodeError::Io(err)) => { - if err.kind() != ErrorKind::NotFound { - return Err(NodeError::Io(err)); - } - } - Err(err) => { - return Err(err); - } - } - let live_properties = Arc::new(EngineLiveProperties::new()); let receivers = receivers .into_iter() .map(|r| Mutex::new(r)) .collect::>(); - Ok(TonNodeEngine { - shard_ident: shard.clone(), + message_queue: message_queue.clone(), receivers, live_properties, live_control_receiver, - blockchain_config, - finalizer: block_finality.clone(), - block_applier: Mutex::new(NewBlockApplier::with_params(block_finality, documents_db)), - message_queue, + masterchain: Masterchain::with_params( + global_id, + blockchain_config.clone(), + message_queue.clone(), + documents_db.clone(), + storage_path.clone(), + )?, + workchain: Shardchain::with_params( + workchain_shard, + global_id, + blockchain_config.clone(), + message_queue.clone(), + documents_db.clone(), + storage_path.clone(), + )?, }) } - /// Getter for current shard identifier - pub fn current_shard_id(&self) -> &ShardIdent { - &self.shard_ident - } - - fn print_block_info(block: &Block) { - let extra = block.read_extra().unwrap(); - log::info!(target: "node", - "block: gen time = {}, in msg count = {}, out msg count = {}, account_blocks = {}", - block.read_info().unwrap().gen_utime(), - extra.read_in_msg_descr().unwrap().len().unwrap(), - extra.read_out_msg_descr().unwrap().len().unwrap(), - extra.read_account_blocks().unwrap().len().unwrap()); - } - - /// - /// Generate new block if possible - /// - pub fn prepare_block(&self, debug: bool) -> NodeResult<()> { - let shard_state = self.finalizer.lock().get_last_shard_state(); - let out_msg_queue_info = shard_state.read_out_msg_queue_info()?; - if out_msg_queue_info.out_queue().is_empty() && self.message_queue.is_empty() { - self.message_queue.wait_new_message(); - } - - let timestamp = UnixTime32::now().as_u32() + self.live_properties.get_time_delta(); - let blk_prev_info = self.finalizer.lock().get_last_block_info()?; - log::debug!(target: "node", "PARENT block: {:?}", blk_prev_info); - - let collator = BlockBuilder::with_params(shard_state, blk_prev_info, timestamp)?; - match collator.build_block(&self.message_queue, self.blockchain_config.clone(), debug)? { - Some((block, new_shard_state)) => { - log::trace!(target: "node", "block generated successfully"); - // TODO remove debug print - Self::print_block_info(&block); - self.finality_and_apply_block(&block, new_shard_state)?; + fn generate_blocks(&self, debug: bool) -> NodeResult<()> { + let mut continue_generating = true; + while continue_generating { + continue_generating = false; + let time_delta = self.live_properties.get_time_delta(); + while let Some(block) = self.workchain.generate_block(time_delta, debug)? { + self.masterchain.register_new_shard_block(&block)?; + continue_generating = true; } - None => { - log::trace!(target: "node", "empty block was not generated"); + if self + .masterchain + .generate_block(time_delta, debug)? + .is_some() + { + continue_generating = true; } } + self.message_queue.wait_new_message(); Ok(()) } - - /// finality and apply block - fn finality_and_apply_block( - &self, - block: &Block, - applied_shard: ShardStateUnsplit, - ) -> NodeResult<(Arc, Vec)> { - let mut time = Vec::new(); - let now = Instant::now(); - let new_state = self.block_applier.lock().apply(block, applied_shard)?; - time.push(now.elapsed().as_micros()); - Ok((new_state, time)) - } } impl TonNodeEngine { - fn deploy_contracts(&self, workchain_id: i8) -> NodeResult<()> { - self.deploy_contract(workchain_id, GIVER_ABI1_DEPLOY_MSG, GIVER_BALANCE, 1)?; - self.deploy_contract(workchain_id, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, 3)?; - self.deploy_contract(workchain_id, MULTISIG_DEPLOY_MSG, MULTISIG_BALANCE, 5)?; - self.deploy_contract( + fn initialize_blockchain(&self) -> NodeResult<()> { + log::info!(target: "node", "Initialize blockchain"); + let workchain_id = self.workchain.shard_ident.workchain_id() as i8; + self.enqueue_deploy_message(workchain_id, GIVER_ABI1_DEPLOY_MSG, GIVER_BALANCE, 1)?; + self.enqueue_deploy_message(workchain_id, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, 3)?; + self.enqueue_deploy_message(workchain_id, MULTISIG_DEPLOY_MSG, MULTISIG_BALANCE, 5)?; + self.enqueue_deploy_message( workchain_id, DEPRECATED_GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, @@ -277,7 +219,7 @@ impl TonNodeEngine { Ok(()) } - fn deploy_contract( + fn enqueue_deploy_message( &self, workchain_id: i8, deploy_msg_boc: &[u8], @@ -300,7 +242,7 @@ impl TonNodeEngine { } fn queue_with_retry(&self, message: Message) -> NodeResult<()> { - let mut message = QueuedMessage::with_message(message)?; + let mut message = message; while let Err(msg) = self.message_queue.queue(message) { message = msg; thread::sleep(Duration::from_micros(100)); diff --git a/node/src/engine/masterchain.rs b/node/src/engine/masterchain.rs new file mode 100644 index 0000000..ea13869 --- /dev/null +++ b/node/src/engine/masterchain.rs @@ -0,0 +1,110 @@ +use crate::data::DocumentsDb; +use crate::engine::shardchain::Shardchain; +use crate::engine::InMessagesQueue; +use crate::error::NodeResult; +use parking_lot::RwLock; +use std::collections::HashMap; +use std::path::PathBuf; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use ton_block::{BinTree, Block, InRefValue, McBlockExtra, Serializable, ShardDescr, ShardIdent}; +use ton_executor::BlockchainConfig; +use ton_types::UInt256; + +pub struct Masterchain { + shardchain: Shardchain, + shards: RwLock>, + shards_has_been_changed: AtomicBool, +} + +impl Masterchain { + pub fn with_params( + global_id: i32, + blockchain_config: Arc, + message_queue: Arc, + documents_db: Arc, + storage_path: PathBuf, + ) -> NodeResult { + let shardchain = Shardchain::with_params( + ShardIdent::masterchain(), + global_id, + blockchain_config, + message_queue, + documents_db, + storage_path, + )?; + Ok(Self { + shardchain, + shards: RwLock::new(HashMap::new()), + shards_has_been_changed: AtomicBool::new(false), + }) + } + + pub fn register_new_shard_block(&self, block: &Block) -> NodeResult<()> { + let info = block.info.read_struct()?; + let block_cell = block.serialize().unwrap(); + let block_boc = ton_types::cells_serialization::serialize_toc(&block_cell)?; + let descr = ShardDescr { + seq_no: info.seq_no(), + reg_mc_seqno: 1, + start_lt: info.start_lt(), + end_lt: info.end_lt(), + root_hash: block_cell.repr_hash(), + file_hash: UInt256::calc_file_hash(&block_boc), + before_split: info.before_split(), + // before_merge: info.before_merge, + want_split: info.want_split(), + want_merge: info.want_merge(), + // nx_cc_updated: info.nx_cc_updated, + flags: info.flags(), + // next_catchain_seqno: info.next_catchain_seqno, + next_validator_shard: info.shard().shard_prefix_with_tag(), + min_ref_mc_seqno: info.min_ref_mc_seqno(), + gen_utime: info.gen_utime().as_u32(), + // split_merge_at: info.split_merge_at, + // fees_collected: info.fees_collected, + // funds_created: info.funds_created, + // copyleft_rewards: info.copyleft_rewards, + // proof_chain: info.proof_chain, + ..ShardDescr::default() + }; + + self.shards.write().insert(info.shard().clone(), descr); + self.shards_has_been_changed.store(true, Ordering::Relaxed); + Ok(()) + } + + /// + /// Generate new block + /// + pub fn generate_block(&self, time_delta: u32, debug: bool) -> NodeResult> { + let (mut master_block, new_shard_state, is_empty) = + self.shardchain.build_block(time_delta, debug)?; + + if is_empty && !self.shards_has_been_changed.load(Ordering::Relaxed) { + return Ok(None); + } + + let mut info = master_block.info.read_struct()?; + info.set_key_block(true); + master_block.info.write_struct(&info)?; + let mut extra = master_block.extra.read_struct()?; + let mut mc_extra = McBlockExtra::default(); + mc_extra.set_config(self.shardchain.blockchain_config.raw_config().clone()); + let shards = mc_extra.shards_mut(); + for (shard, descr) in &*self.shards.read() { + shards.set( + &shard.workchain_id(), + &InRefValue(BinTree::with_item(descr)?), + )?; + } + + extra.write_custom(Some(&mc_extra))?; + master_block.write_extra(&extra)?; + self.shardchain + .finality_and_apply_block(&master_block, new_shard_state)?; + self.shards_has_been_changed.store(false, Ordering::Relaxed); + log::trace!(target: "node", "master block generated successfully"); + Ok(Some(master_block)) + } +} diff --git a/node/src/engine/messages.rs b/node/src/engine/messages.rs index f4e4aa1..de2dc8f 100644 --- a/node/src/engine/messages.rs +++ b/node/src/engine/messages.rs @@ -15,41 +15,20 @@ */ use crate::data::DocumentsDb; -use parking_lot::{Mutex, Condvar}; -use std::{sync::Arc, collections::VecDeque}; -use ton_block::{GetRepresentationHash, Message, Serializable}; -use ton_types::{serialize_toc, Result, UInt256}; +use parking_lot::{Condvar, Mutex}; +use std::{collections::VecDeque, sync::Arc}; +use ton_block::{Message, Serializable}; +use ton_types::serialize_toc; #[cfg(test)] #[path = "../../../../tonos-se-tests/unit/test_messages.rs"] mod tests; -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct QueuedMessage { - message: Message, - hash: UInt256, -} - -impl QueuedMessage { - pub fn with_message(message: Message) -> Result { - let hash = message.hash()?; - Ok(Self { message, hash }) - } - - pub fn message(&self) -> &Message { - &self.message - } - - pub fn message_hash(&self) -> &UInt256 { - &self.hash - } -} - /// This FIFO accumulates inbound messages from all types of receivers. /// The struct might be used from many threads. It provides internal mutability. pub struct InMessagesQueue { present: Condvar, - storage: Mutex>, + storage: Mutex>, db: Option>, capacity: usize, } @@ -82,7 +61,7 @@ impl InMessagesQueue { } /// Include message into end queue. - pub fn queue(&self, msg: QueuedMessage) -> std::result::Result<(), QueuedMessage> { + pub fn queue(&self, msg: Message) -> std::result::Result<(), Message> { if self.has_delivery_problems() { log::debug!(target: "node", "Has delivery problems"); return Err(msg); @@ -93,16 +72,22 @@ impl InMessagesQueue { return Err(msg); } - log::debug!(target: "node", "Queued message: {:?}", msg.message()); + log::debug!(target: "node", "Queued message: {:?}", msg); storage.push_back(msg); self.present.notify_one(); Ok(()) } - /// Extract oldest message from queue. - pub fn dequeue(&self) -> Option { - self.storage.lock().pop_front() + /// Extract oldest message for specified workchain from queue. + pub fn dequeue(&self, workchain_id: i32) -> Option { + let mut storage = self.storage.lock(); + for i in 0..storage.len() { + if storage[i].workchain_id() == Some(workchain_id) { + return storage.remove(i); + } + } + None } pub fn print_message(msg: &Message) { diff --git a/node/src/engine/mod.rs b/node/src/engine/mod.rs index 8431662..4caa37a 100644 --- a/node/src/engine/mod.rs +++ b/node/src/engine/mod.rs @@ -20,6 +20,8 @@ use std::sync::Arc; pub mod messages; pub use self::messages::*; pub mod engine; +pub mod shardchain; +mod masterchain; const GIVER_BALANCE: u128 = 5_000_000_000_000_000_000; const MULTISIG_BALANCE: u128 = 1_000_000_000_000_000; diff --git a/node/src/engine/shardchain.rs b/node/src/engine/shardchain.rs new file mode 100644 index 0000000..e2c5e43 --- /dev/null +++ b/node/src/engine/shardchain.rs @@ -0,0 +1,118 @@ +use crate::block::{BlockBuilder, OrdinaryBlockFinality}; +use crate::data::{DocumentsDb, FileBasedStorage}; +use crate::engine::InMessagesQueue; +use crate::error::{NodeError, NodeResult}; +use parking_lot::Mutex; +use std::io::ErrorKind; +use std::path::PathBuf; +use std::sync::Arc; +use ton_block::{Block, ShardIdent, ShardStateUnsplit, UnixTime32}; +use ton_executor::BlockchainConfig; +use ton_types::HashmapType; + +type Storage = FileBasedStorage; +type ArcBlockFinality = Arc>>; + +pub struct Shardchain { + pub(crate) shard_ident: ShardIdent, + pub(crate) blockchain_config: Arc, + message_queue: Arc, + pub(crate) finalizer: ArcBlockFinality, +} + +impl Shardchain { + pub fn with_params( + shard: ShardIdent, + global_id: i32, + blockchain_config: Arc, + message_queue: Arc, + documents_db: Arc, + storage_path: PathBuf, + ) -> NodeResult { + let storage = Arc::new(Storage::with_path(shard.clone(), storage_path.clone())?); + let block_finality = Arc::new(Mutex::new(OrdinaryBlockFinality::with_params( + global_id, + shard.clone(), + storage_path, + storage.clone(), + storage.clone(), + storage.clone(), + storage.clone(), + Some(documents_db.clone()), + Vec::new(), + ))); + match block_finality.lock().load() { + Ok(_) => { + log::info!(target: "node", "load block finality successfully"); + } + Err(NodeError::Io(err)) => { + if err.kind() != ErrorKind::NotFound { + return Err(NodeError::Io(err)); + } + } + Err(err) => { + return Err(err); + } + } + + Ok(Self { + shard_ident: shard.clone(), + blockchain_config, + message_queue, + finalizer: block_finality.clone(), + }) + } + + pub(crate) fn build_block( + &self, + time_delta: u32, + debug: bool, + ) -> NodeResult<(Block, ShardStateUnsplit, bool)> { + let timestamp = UnixTime32::now().as_u32() + time_delta; + let (shard_state, blk_prev_info) = self.finalizer.lock().get_last_info()?; + log::debug ! (target: "node", "PARENT block: {:?}", blk_prev_info); + + let collator = BlockBuilder::with_params(shard_state, blk_prev_info, timestamp)?; + collator.build_block(&self.message_queue, &self.blockchain_config, debug) + } + + /// + /// Generate new block if possible + /// + pub fn generate_block(&self, time_delta: u32, debug: bool) -> NodeResult> { + let (block, new_shard_state, is_empty) = self.build_block(time_delta, debug)?; + Ok(if !is_empty { + log::trace!(target: "node", "block generated successfully"); + Self::print_block_info(&block); + self.finality_and_apply_block(&block, new_shard_state)?; + Some(block) + } else { + log::trace!(target: "node", "empty block was not generated"); + None + }) + } + + fn print_block_info(block: &Block) { + let extra = block.read_extra().unwrap(); + log::info!(target: "node", + "block: gen time = {}, in msg count = {}, out msg count = {}, account_blocks = {}", + block.read_info().unwrap().gen_utime(), + extra.read_in_msg_descr().unwrap().len().unwrap(), + extra.read_out_msg_descr().unwrap().len().unwrap(), + extra.read_account_blocks().unwrap().len().unwrap()); + } + + /// finality and apply block + pub(crate) fn finality_and_apply_block( + &self, + block: &Block, + applied_shard: ShardStateUnsplit, + ) -> NodeResult> { + log::info!(target: "node", "Apply block seq_no = {}", block.read_info()?.seq_no()); + let new_state = Arc::new(applied_shard); + self.finalizer + .lock() + .put_block_with_info(block, new_state.clone())?; + Ok(new_state) + } +} diff --git a/node/src/main.rs b/node/src/main.rs index ec5a083..0a0a478 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -22,6 +22,7 @@ use crate::engine::MessagesReceiver; use crate::error::{NodeError, NodeResult}; use clap::{Arg, ArgMatches, Command}; use iron::Iron; +use parking_lot::Mutex; use router::Router; use serde_json::Value; use std::{ @@ -31,7 +32,6 @@ use std::{ thread, time::Duration, }; -use parking_lot::Mutex; use ton_executor::BlockchainConfig; pub mod error; @@ -170,11 +170,12 @@ fn start_node(config: StartNodeConfig) -> NodeResult<()> { )?); let ton = TonNodeEngine::with_params( + config.node.global_id, config.node.shard_id_config().shard_ident(), receivers, Some(control_api), - config.blockchain, - Some(db), + Arc::new(config.blockchain), + db, PathBuf::from("./"), )?; From 5b26dcb88614a3ccd27ec4eff5b5bcc69e430fcb Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Thu, 9 Feb 2023 10:06:32 +0300 Subject: [PATCH 02/26] Revert database name --- dev/q-server.json | 16 ++++++++-------- docker/ton-node/ton-node.conf.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/q-server.json b/dev/q-server.json index 72d33c8..fcfb5dd 100644 --- a/dev/q-server.json +++ b/dev/q-server.json @@ -9,38 +9,38 @@ }, "blockchain": { "accounts": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "blocks": { "hot": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "cold": [] }, - "zerostate": "http://root@localhost:8529?name=se_master_blocks" + "zerostate": "http://root@localhost:8529" }, "slowQueriesBlockchain": { "accounts": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "blocks": { "hot": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529?name=se_master_blocks" + "http://root@localhost:8529" ], "cold": [] }, - "zerostate": "http://root@localhost:8529?name=se_master_blocks" + "zerostate": "http://root@localhost:8529" } } diff --git a/docker/ton-node/ton-node.conf.json b/docker/ton-node/ton-node.conf.json index 17654e6..e267f87 100644 --- a/docker/ton-node/ton-node.conf.json +++ b/docker/ton-node/ton-node.conf.json @@ -32,7 +32,7 @@ }, "document_db": { "server": "127.0.0.1:8529", - "database": "se_master_blocks", + "database": "blockchain", "blocks_collection": "blocks", "messages_collection": "messages", "transactions_collection": "transactions", From fd5fd1bae8bd4f51f303d3c85b7f487728508d7f Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:42:46 +0100 Subject: [PATCH 03/26] Remove giverV3 --- contracts/giver_v3/GiverV3.abi.json | 96 +++++++++++++------------- contracts/giver_v3/GiverV3.keys.json | 4 -- contracts/giver_v3/GiverV3.sol | 13 ++-- contracts/giver_v3/GiverV3.tvc | Bin 782 -> 791 bytes contracts/giver_v3/README.md | 78 ++++++++++----------- contracts/giver_v4/.gitignore | 1 - contracts/giver_v4/GiverV4.abi.json | 49 -------------- contracts/giver_v4/GiverV4.sol | 98 --------------------------- contracts/giver_v4/GiverV4.tvc | Bin 791 -> 0 bytes contracts/giver_v4/README.md | 48 ------------- 10 files changed, 94 insertions(+), 293 deletions(-) delete mode 100644 contracts/giver_v3/GiverV3.keys.json delete mode 100644 contracts/giver_v4/.gitignore delete mode 100644 contracts/giver_v4/GiverV4.abi.json delete mode 100644 contracts/giver_v4/GiverV4.sol delete mode 100644 contracts/giver_v4/GiverV4.tvc delete mode 100644 contracts/giver_v4/README.md diff --git a/contracts/giver_v3/GiverV3.abi.json b/contracts/giver_v3/GiverV3.abi.json index a75bcf7..8e53d70 100644 --- a/contracts/giver_v3/GiverV3.abi.json +++ b/contracts/giver_v3/GiverV3.abi.json @@ -1,49 +1,49 @@ { - "ABI version": 2, - "version": "2.2", - "header": ["time", "expire"], - "functions": [ - { - "name": "sendTransaction", - "inputs": [ - {"name":"dest","type":"address"}, - {"name":"value","type":"uint128"}, - {"name":"bounce","type":"bool"} - ], - "outputs": [ - ] - }, - { - "name": "getMessages", - "inputs": [ - ], - "outputs": [ - {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint64"}],"name":"messages","type":"tuple[]"} - ] - }, - { - "name": "upgrade", - "inputs": [ - {"name":"newcode","type":"cell"} - ], - "outputs": [ - ] - }, - { - "name": "constructor", - "inputs": [ - ], - "outputs": [ - ] - } - ], - "data": [ - ], - "events": [ - ], - "fields": [ - {"name":"_pubkey","type":"uint256"}, - {"name":"_constructorFlag","type":"bool"}, - {"name":"m_messages","type":"map(uint256,uint64)"} - ] -} + "ABI version": 2, + "version": "2.3", + "header": ["pubkey", "time", "expire"], + "functions": [ + { + "name": "sendTransaction", + "inputs": [ + {"name":"dest","type":"address"}, + {"name":"value","type":"uint128"}, + {"name":"bounce","type":"bool"} + ], + "outputs": [ + ] + }, + { + "name": "getMessages", + "inputs": [ + ], + "outputs": [ + {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint32"}],"name":"messages","type":"tuple[]"} + ] + }, + { + "name": "upgrade", + "inputs": [ + {"name":"newcode","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "constructor", + "inputs": [ + ], + "outputs": [ + ] + } + ], + "data": [ + ], + "events": [ + ], + "fields": [ + {"name":"_pubkey","type":"uint256"}, + {"name":"_constructorFlag","type":"bool"}, + {"name":"m_messages","type":"map(uint256,uint32)"} + ] +} \ No newline at end of file diff --git a/contracts/giver_v3/GiverV3.keys.json b/contracts/giver_v3/GiverV3.keys.json deleted file mode 100644 index e3d8285..0000000 --- a/contracts/giver_v3/GiverV3.keys.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", - "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3" -} \ No newline at end of file diff --git a/contracts/giver_v3/GiverV3.sol b/contracts/giver_v3/GiverV3.sol index 5f08ed4..b882355 100644 --- a/contracts/giver_v3/GiverV3.sol +++ b/contracts/giver_v3/GiverV3.sol @@ -1,6 +1,7 @@ -pragma ton-solidity >= 0.59.0; +pragma ever-solidity >= 0.61.2; pragma AbiHeader time; pragma AbiHeader expire; +pragma AbiHeader pubkey; abstract contract Upgradable { /* @@ -22,7 +23,7 @@ abstract contract Upgradable { contract GiverV3 is Upgradable { uint8 constant MAX_CLEANUP_MSGS = 30; - mapping(uint256 => uint64) m_messages; + mapping(uint256 => uint32) m_messages; modifier acceptOnlyOwner { require(msg.pubkey() == tvm.pubkey(), 101); @@ -55,7 +56,7 @@ contract GiverV3 is Upgradable { // owner check require(msg.pubkey() == tvm.pubkey(), 101); // load and drop message timestamp (uint64) - (, uint64 expireAt) = body.decode(uint64, uint32); + (, uint32 expireAt) = body.decode(uint64, uint32); require(expireAt > now, 57); uint256 msgHash = tvm.hash(message); require(!m_messages.exists(msgHash), 102); @@ -69,7 +70,7 @@ contract GiverV3 is Upgradable { /// @notice Allows to delete expired messages from dict. function gc() private inline { uint counter = 0; - for ((uint256 msgHash, uint64 expireAt) : m_messages) { + for ((uint256 msgHash, uint32 expireAt) : m_messages) { if (counter >= MAX_CLEANUP_MSGS) { break; } @@ -85,10 +86,10 @@ contract GiverV3 is Upgradable { */ struct Message { uint256 hash; - uint64 expireAt; + uint32 expireAt; } function getMessages() public view returns (Message[] messages) { - for ((uint256 msgHash, uint64 expireAt) : m_messages) { + for ((uint256 msgHash, uint32 expireAt) : m_messages) { messages.push(Message(msgHash, expireAt)); } } diff --git a/contracts/giver_v3/GiverV3.tvc b/contracts/giver_v3/GiverV3.tvc index 8e31859ad1d8bdf75363f5b8988b5d12050aa336..5c880dcc349be26d32dd3b16a8ba4b7eaa78f96f 100644 GIT binary patch delta 477 zcmeBUo6g3)_1&BzMkWbH24?Pw+)g$kY^*E{3{0Qix?H&Kd6@A>n&NGn%M6TtGR+*< zB@})#G6FeMF8^m{oXqsY>5;;Z)Sm*MR!jv7eyVyju~JE;nf(i2{zAh~7t($(DE#nJ zK5<$;5-8^UBP*WyvOME$n@={J6Ax;*2@A8c1Sm8Kh%570?Rv}vVj1l}3}G3@{WOKJ zGPcIs16lk$TpUbF20xtg9y9!K`&4}K2LsR`22SzG#~D=^g(kmYR7@7)7H8NOQmAm^ zd~3rghVv~B=NNx6HDsT6I9dFgq2Py?0?-w0QxzhvbIVW8jaPUySt)OGpO(rY*~c6z zOH6+#@16y8E>KOh!H=wa!9qY*4U*~{<;N27lO-9IS*8P>IoW|xOi_qeoUyMUH=hZI z*()a3F^XHDn`8VUo`sJ=AYX~`#OeR1<(V}MfF63_1NPdLi??kIKpqnk5TD%3WWXdY zIC(#ltf|14B?@2memdYMCdwdEoS&m$pl4>NXT&JBfB_g)w{3p#e_{}4kon>D!wG2U M`Q|SSC*Otu0GcqpKmY&$ delta 515 zcmbQv*2l)Z_1&BzMkYx{24<#-+)g^8Y^*E{3{2PFx?H&Kd6@A>n&NGn%M6TtLXAue z*CiBwGDiGxQuvYjQ{dBzdlNgA)EXHXzVPKQH2icS?FWOx4=?2tr|ly_g3dp(;+ZeY zGv2oOWWzi0yatbm2s=xFLX&{FGLO|{UPf_VAiLb<_@iBqnFRQFCO>0TuKy0?p6704 z%vWMME&qk#WWjHSi3X1zGkjtY=9FM`D9Fuc`r)MjGQDl8Ld11$`^mZS3Xdi$28A!q`Anw4${;N@NLq4?xfulVl^9Q){(st@Ny*@c zQ{H2SA3ScKiZA|P0J@lgS7Nd)ql&sPvz@^Yw@(jzzzP&6U%7bU-YX1Iq^{2038tT>gKV!SD;q#UEKek{Gzaj%4EcvP9v_LUAz$k>dOu o1p_@(OFa`tu>}mk2)%9dgZ~qQ1cS^EuOCi8Z=Y`lhVR=D07FU3$p8QV diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index 056cd5d..2d1e807 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -1,66 +1,66 @@ -# Giver v3 +# Giver v4 -This directory contains Giver v3 (ABI v2.2) contract. This giver is recommended over Giver v1 or v2. +This directory contains Giver v3 contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. -In Evernode SE this giver is predeployed (since version `TODO`) at `0:78fbd6980c10cf41401b32e9b51810415e7578b52403af80dae68ddf99714498` address -and its initial balance is about 5 billion tokens. +## How to deploy GiverV3 on any network -## Keys: - -> ⚠ Using only local and dev environment - -* Public: `2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16` -* Secret: `172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3` - -## Usage -Method: `sendTransaction` - -parameters: -* `dest`: `address` - destination address; -* `value`: `uint128` - amount to send, in nanotokens; -* `bounce`: `bool` - bounce flag of the message. - -### Using tonos-cli: +### Setup your signer +You can skip this step if you already have one. ```shell -npx tonos-cli call 0:78fbd6980c10cf41401b32e9b51810415e7578b52403af80dae68ddf99714498 \ - sendTransaction '{"dest":"
","value":,"bounce":false}' \ - --abi GiverV2.abi.json \ - --sign GiverV2.keys.json +npx everdev signer add devnet_giver_keys +npx everdev signer default devnet_giver_keys ``` -## Self deploy +### [Optional] Verify Giver contract bytecode +This contract is compiled with `0.66.0 ` Solidity and `0.19.3`Linker version. + +To check that the code hash of the compiled version from repository is equal to your freshly compiled version, run this command and check that the Code Hash is +`5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989`. -### Compile ```shell -npx everdev sol set --compiler 0.59.4 --linker 0.15.24 +npx everdev sol set --compiler 0.66.0 --linker 0.19.3 npx everdev sol compile GiverV3.sol -``` +npx everdev c i --signer devnet_giver_keys GiverV3 -> ℹ️ For compiler v0.59.4 and linker v0.15.2 code hash is `726aec999006a2e036af36c46024237acb946c13b4d4b3e1ad3b4ad486d564b1` +Configuration -### Setup yore signer -```shell -npx everdev signer add -npx everdev signer default + Network: se (http://localhost) + Signer: devnet_giver_keys (public 7fbbd813ac8358ed2d8598de156eb62bdddf5191d6ce4a0f307d4eac8d4c8e16) + +Address: 0:dd39b607834a23f7091d4d6d8982c6269c1d71f1b512757cf4d298325a550b6a (calculated from TVC and signer public) +Code Hash: 5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989 (from TVC file) ``` -### Get `` and topup it +### Get your Giver address and top it up +The address is calculated from the compiled contract codehash and your public key. +Run this command to see the address: ```shell -npx everdev contract info GiverV3 +npx everdev c i --signer devnet_giver_keys GiverV3 ``` +Now, you need to top up your giver. Transfer tokens from Surf wallet or Everwallet. -### Deploy + +### Deploy your Giver +After you topped up Giver address, you can deploy it. +Run this command: ```shell npx everdev contract deploy GiverV3 ``` -### Setup yore Giver +### Setup your Giver +Run this command to set up the giver for your network. + ```shell -everdev network giver --signer --type GiverV3 +npx everdev network giver --signer --type GiverV4 +``` + +### Using your Giver +This command under the hood will use predefined signer and configured giver on the default network. +``` +npx everdev contract topup -a `` -v `` ``` ## Files * ABI: [GiverV3.abi.json](GiverV3.abi.json) -* Keypair: [GiverV3.keys.json](GiverV3.keys.json) * Source code: [GiverV3.sol](GiverV3.sol) * TVC file: [GiverV3.tvc](GiverV3.tvc) diff --git a/contracts/giver_v4/.gitignore b/contracts/giver_v4/.gitignore deleted file mode 100644 index a6c7c28..0000000 --- a/contracts/giver_v4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.js diff --git a/contracts/giver_v4/GiverV4.abi.json b/contracts/giver_v4/GiverV4.abi.json deleted file mode 100644 index 3c1e19d..0000000 --- a/contracts/giver_v4/GiverV4.abi.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "ABI version": 2, - "version": "2.2", - "header": ["pubkey", "time", "expire"], - "functions": [ - { - "name": "sendTransaction", - "inputs": [ - {"name":"dest","type":"address"}, - {"name":"value","type":"uint128"}, - {"name":"bounce","type":"bool"} - ], - "outputs": [ - ] - }, - { - "name": "getMessages", - "inputs": [ - ], - "outputs": [ - {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint32"}],"name":"messages","type":"tuple[]"} - ] - }, - { - "name": "upgrade", - "inputs": [ - {"name":"newcode","type":"cell"} - ], - "outputs": [ - ] - }, - { - "name": "constructor", - "inputs": [ - ], - "outputs": [ - ] - } - ], - "data": [ - ], - "events": [ - ], - "fields": [ - {"name":"_pubkey","type":"uint256"}, - {"name":"_constructorFlag","type":"bool"}, - {"name":"m_messages","type":"map(uint256,uint32)"} - ] -} diff --git a/contracts/giver_v4/GiverV4.sol b/contracts/giver_v4/GiverV4.sol deleted file mode 100644 index b882355..0000000 --- a/contracts/giver_v4/GiverV4.sol +++ /dev/null @@ -1,98 +0,0 @@ -pragma ever-solidity >= 0.61.2; -pragma AbiHeader time; -pragma AbiHeader expire; -pragma AbiHeader pubkey; - -abstract contract Upgradable { - /* - * Set code - */ - - function upgrade(TvmCell newcode) public virtual { - require(msg.pubkey() == tvm.pubkey(), 101); - tvm.accept(); - tvm.commit(); - tvm.setcode(newcode); - tvm.setCurrentCode(newcode); - onCodeUpgrade(); - } - - function onCodeUpgrade() internal virtual; -} - -contract GiverV3 is Upgradable { - - uint8 constant MAX_CLEANUP_MSGS = 30; - mapping(uint256 => uint32) m_messages; - - modifier acceptOnlyOwner { - require(msg.pubkey() == tvm.pubkey(), 101); - tvm.accept(); - _; - } - - /* - * Publics - */ - - /// @notice Allows to accept simple transfers. - receive() external {} - - /// @notice Transfers grams to other contracts. - function sendTransaction(address dest, uint128 value, bool bounce) public { - dest.transfer(value, bounce, 3); - gc(); - } - - /* - * Privates - */ - - /// @notice Function with predefined name called after signature check. Used to - /// implement custom replay protection with parallel access. - function afterSignatureCheck(TvmSlice body, TvmCell message) private inline - returns (TvmSlice) - { - // owner check - require(msg.pubkey() == tvm.pubkey(), 101); - // load and drop message timestamp (uint64) - (, uint32 expireAt) = body.decode(uint64, uint32); - require(expireAt > now, 57); - uint256 msgHash = tvm.hash(message); - require(!m_messages.exists(msgHash), 102); - - tvm.accept(); - m_messages[msgHash] = expireAt; - - return body; - } - - /// @notice Allows to delete expired messages from dict. - function gc() private inline { - uint counter = 0; - for ((uint256 msgHash, uint32 expireAt) : m_messages) { - if (counter >= MAX_CLEANUP_MSGS) { - break; - } - counter++; - if (expireAt <= now) { - delete m_messages[msgHash]; - } - } - } - - /* - * Get methods - */ - struct Message { - uint256 hash; - uint32 expireAt; - } - function getMessages() public view returns (Message[] messages) { - for ((uint256 msgHash, uint32 expireAt) : m_messages) { - messages.push(Message(msgHash, expireAt)); - } - } - - function onCodeUpgrade() internal override {} -} diff --git a/contracts/giver_v4/GiverV4.tvc b/contracts/giver_v4/GiverV4.tvc deleted file mode 100644 index 5c880dcc349be26d32dd3b16a8ba4b7eaa78f96f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmaiyUr19?9LIm>+?ms?4c*|A=4WA;B4UTy25=}4B36@Wf7PAaHh~YP7n*C^YlGGe!uhm{C?-R z@Z^s4ZmLu_qN3PECUBvCRjN&GUf>1aGuVFSQsp-|Jp?AlW|7D7EtIcuuz*ez54xB>L6 zIgz2j%%F-#ePy#16yqaISrub69Q9ds=CbZ6(V+;vZq(Lur)5^O)n6_b z$BwtH95w81vt3mB_-b!BS7aK_1?yS%-2>U9lF=NpbCU-kn6VghOR9#peX=K+eoQu| zTrXMwX~%t}xN%CbU_G(}&*Z!TjIWkQvB;Q$|A8_$FzHfo*2_x8*-Io!tX>6o1*N}1 zPJ9p9>cFMAQ8HCZ3EZ&*NSph^aPj!+pR2GtZR#XDHkCZ>em_6BRuR|Ft2w=2EwmPb zSucMWY(FuyvLDb&8h9*QhKA`7RF}t&UDhnImd(V4rX$cep^Or_{iLV812w&2E6%W~ T(*zz`Xn^_|S9+TDUKscdMDs~j diff --git a/contracts/giver_v4/README.md b/contracts/giver_v4/README.md deleted file mode 100644 index b6acb51..0000000 --- a/contracts/giver_v4/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Giver v4 - -This directory contains Giver v4 (ABI v2.2) contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. - -## Self deploy contract on any network - -### Compile Giver contract -This contract is prepared for compilation by `solc_0_61_2` and `tvm_linker_0_17_3` or above. -```shell -npx everdev sol set --compiler 0.61.2 --linker 0.17.3 -npx everdev sol compile GiverV4.sol -``` - -### Setup your signer -You can skip this step if you already have one. But make sure the right signer linked to ``. -```shell -npx everdev signer add -npx everdev signer default -``` - -### Get your Giver `` -The address was calculated using the compiled contract codehash and your public key. -```shell -npx everdev contract info GiverV4 -``` - -### Deploy your Giver -Before deploy you need to transfer tokens to ``. -```shell -npx everdev contract deploy GiverV4 -``` - -### Setup your Giver -Before this step, make sure that you have configured the network with the correct endpoint, which contains your evercloud projectId. -```shell -npx everdev network giver --signer --type GiverV4 -``` - -### Using your Giver -This command under the hood will use predefined signer and configured giver on the default network. -``` -npx everdev contract topup -a `` -v `` -``` - -## Files -* ABI: [GiverV4.abi.json](GiverV4.abi.json) -* Source code: [GiverV4.sol](GiverV4.sol) -* TVC file: [GiverV4.tvc](GiverV4.tvc) From f37960dab87d28f0a7ce0683cd2e8f92cd24c9c8 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:45:19 +0100 Subject: [PATCH 04/26] Update README.md --- contracts/giver_v3/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index 2d1e807..d55449e 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -1,4 +1,4 @@ -# Giver v4 +# Giver v3 This directory contains Giver v3 contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. @@ -51,7 +51,7 @@ npx everdev contract deploy GiverV3 Run this command to set up the giver for your network. ```shell -npx everdev network giver --signer --type GiverV4 +npx everdev network giver --signer --type GiverV3 ``` ### Using your Giver From b2b1a4abeb036042de079895c1fa2ebbf04e0dde Mon Sep 17 00:00:00 2001 From: Michael Vlasov Date: Thu, 9 Feb 2023 17:03:36 +0300 Subject: [PATCH 05/26] FIX: false detection of the first running --- dev/q-server.json | 16 ++++++++-------- dev/reset-db.js | 10 +++++++++- node/src/engine/engine.rs | 2 +- node/src/engine/shardchain.rs | 8 ++++++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/dev/q-server.json b/dev/q-server.json index fcfb5dd..813c90a 100644 --- a/dev/q-server.json +++ b/dev/q-server.json @@ -9,38 +9,38 @@ }, "blockchain": { "accounts": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "blocks": { "hot": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "cold": [] }, - "zerostate": "http://root@localhost:8529" + "zerostate": "http://root@127.0.0.1:8529" }, "slowQueriesBlockchain": { "accounts": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "blocks": { "hot": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "cold": [] }, "transactions": { "hot": [ - "http://root@localhost:8529" + "http://root@127.0.0.1:8529" ], "cold": [] }, - "zerostate": "http://root@localhost:8529" + "zerostate": "http://root@127.0.0.1:8529" } } diff --git a/dev/reset-db.js b/dev/reset-db.js index 41d8caa..7e2b56c 100644 --- a/dev/reset-db.js +++ b/dev/reset-db.js @@ -1,7 +1,9 @@ const { Database } = require("arangojs"); +const fs = require("fs"); +const path = require("path"); const config = { - url: "http://localhost:8529", + url: "http://127.0.0.1:8529", auth: { username: "root", password: "", @@ -158,6 +160,12 @@ async function checkCollections(collections) { try { await checkBlockchainDb(); await checkCollections(COLLECTIONS); + fs.rmSync(path.resolve(__dirname, "..", "docker", "ton-node", "workchains"), + { + recursive: true, + force: true, + }, + ); } catch (err) { console.error(err); process.exit(1); diff --git a/node/src/engine/engine.rs b/node/src/engine/engine.rs index a7769b9..9f80847 100644 --- a/node/src/engine/engine.rs +++ b/node/src/engine/engine.rs @@ -122,7 +122,7 @@ impl TonNodeEngine { control_receiver.run(Box::new(live_control))?; } - if self.workchain.finalizer.lock().get_last_seq_no() == 1 { + if !self.workchain.finality_was_loaded { self.initialize_blockchain()?; } thread::spawn(move || loop { diff --git a/node/src/engine/shardchain.rs b/node/src/engine/shardchain.rs index e2c5e43..74ceb56 100644 --- a/node/src/engine/shardchain.rs +++ b/node/src/engine/shardchain.rs @@ -14,6 +14,7 @@ type Storage = FileBasedStorage; type ArcBlockFinality = Arc>>; pub struct Shardchain { + pub(crate) finality_was_loaded: bool, pub(crate) shard_ident: ShardIdent, pub(crate) blockchain_config: Arc, message_queue: Arc, @@ -41,21 +42,24 @@ impl Shardchain { Some(documents_db.clone()), Vec::new(), ))); - match block_finality.lock().load() { + let finality_was_loaded = match block_finality.lock().load() { Ok(_) => { log::info!(target: "node", "load block finality successfully"); + true } Err(NodeError::Io(err)) => { if err.kind() != ErrorKind::NotFound { return Err(NodeError::Io(err)); } + false } Err(err) => { return Err(err); } - } + }; Ok(Self { + finality_was_loaded, shard_ident: shard.clone(), blockchain_config, message_queue, From 82ed7b58595d6766aae024733e01adfabdd8a941 Mon Sep 17 00:00:00 2001 From: Michael Vlasov Date: Thu, 9 Feb 2023 18:51:00 +0300 Subject: [PATCH 06/26] FIX: set block ent_lt --- node/src/block/builder.rs | 3 ++- node/src/block/finality.rs | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/node/src/block/builder.rs b/node/src/block/builder.rs index f164af7..8fb7415 100644 --- a/node/src/block/builder.rs +++ b/node/src/block/builder.rs @@ -437,7 +437,7 @@ impl BlockBuilder { /// Complete the construction of the block and return it. /// returns generated block and new shard state bag (and transaction count) /// - pub fn finalize_block(self) -> Result<(Block, ShardStateUnsplit)> { + pub fn finalize_block(mut self) -> Result<(Block, ShardStateUnsplit)> { let mut new_shard_state = self.shard_state.deref().clone(); new_shard_state.set_seq_no(self.block_info.seq_no()); new_shard_state.write_accounts(&self.accounts)?; @@ -465,6 +465,7 @@ impl BlockBuilder { // let old_ss_root = self.shard_state.serialize()?; // let state_update = MerkleUpdate::create(&old_ss_root, &new_ss_root)?; let state_update = MerkleUpdate::default(); + self.block_info.set_end_lt(self.end_lt.max(self.start_lt + 1)); let block = Block::with_params( self.shard_state.global_id(), diff --git a/node/src/block/finality.rs b/node/src/block/finality.rs index 01ada7c..12c119b 100644 --- a/node/src/block/finality.rs +++ b/node/src/block/finality.rs @@ -755,11 +755,6 @@ where Ok(()) } - /// get last block sequence number - pub(crate) fn get_last_seq_no(&self) -> u32 { - self.current_block.block.read_info().unwrap().seq_no() - } - /// get last block info fn get_last_block_info(&self) -> NodeResult { let info = &self.current_block.block.read_info()?; From 9d71240eb9bcea00b1e8faadaabc8af15bd38aca Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Fri, 10 Feb 2023 16:02:20 +0300 Subject: [PATCH 07/26] Remove unnecessary spaces --- node/src/block/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/block/builder.rs b/node/src/block/builder.rs index 8fb7415..6045854 100644 --- a/node/src/block/builder.rs +++ b/node/src/block/builder.rs @@ -274,7 +274,7 @@ impl BlockBuilder { // key is not matter for one shard sorted.push((key, OutMsgQueue::value_aug(&mut slice)?)); } - sorted.sort_by(|a, b| a.1 .1.cmp(&b.1 .1)); + sorted.sort_by(|a, b| a.1.1.cmp(&b.1.1)); for (key, (enq, _create_lt)) in sorted { let env = enq.read_out_msg()?; let message = env.read_message()?; From bb26701106568cb2a2b07f9dc040104e5701db00 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Fri, 10 Feb 2023 14:53:16 +0100 Subject: [PATCH 08/26] Update README.md --- contracts/giver_v2/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/giver_v2/README.md b/contracts/giver_v2/README.md index 727f6a3..33835f7 100644 --- a/contracts/giver_v2/README.md +++ b/contracts/giver_v2/README.md @@ -1,11 +1,12 @@ # Giver v2 -This directory contains Giver v2 (ABI v2) contract. This giver is recommended over Giver v1 because ABI v1 is deprecated. +This directory contains Giver v2 (ABI v2) contract. In Evernode SE this giver is predeployed at `0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415` address and its initial balance is about 5 billion tokens. -If you want to compile and deploy your own v2 giver you can find its fresh version in `giver_for_Sol_0.59.0_abi.2.2` folder that is compatible with the latest compiler version. We do not deploy this giver to SE because it has the same ABI, but will cause a breaking change because a lot of tools and scripts use the old `0:ece57bc...` address. +It is not recommented to use in production or recompile Giver V2 because its works on old Solidity version. +If you want to make changes to the Giver contract or use it in production - use [Giver V3](../contracts/giver_v3) version which can be successfully compiled with the latest Solidity compiler. ## Keys: * Public: `2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16` From a3bdc68e91498bdd294aa5d8c34ffe2906f88d19 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Fri, 10 Feb 2023 14:53:59 +0100 Subject: [PATCH 09/26] Update README.md --- contracts/giver_v2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/giver_v2/README.md b/contracts/giver_v2/README.md index 33835f7..9fd9b77 100644 --- a/contracts/giver_v2/README.md +++ b/contracts/giver_v2/README.md @@ -6,7 +6,7 @@ In Evernode SE this giver is predeployed at `0:ece57bcc6c530283becbbd8a3b24d3c59 and its initial balance is about 5 billion tokens. It is not recommented to use in production or recompile Giver V2 because its works on old Solidity version. -If you want to make changes to the Giver contract or use it in production - use [Giver V3](../contracts/giver_v3) version which can be successfully compiled with the latest Solidity compiler. +If you want to make changes to the Giver contract or use it in production - use [Giver V3](../giver_v3) version which can be successfully compiled with the latest Solidity compiler. ## Keys: * Public: `2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16` From 2a642c5c597a1d6b2721cc4cb3e68e60632a71b9 Mon Sep 17 00:00:00 2001 From: Michael Vlasov Date: Fri, 10 Feb 2023 16:56:55 +0300 Subject: [PATCH 10/26] FIX: invalid index field names in reset_db.js --- dev/reset-db.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/reset-db.js b/dev/reset-db.js index 7e2b56c..24a86b7 100644 --- a/dev/reset-db.js +++ b/dev/reset-db.js @@ -23,9 +23,9 @@ const COLLECTIONS = { "workchain_id, key_block", "seq_no", "workchain_id, gen_utime", "workchain_id, tr_count", "gen_utime", - "mastermin_shard_gen_utime", - "prev_refroot_hash,_key", - "prev_alt_refroot_hash,_key", + "master.min_shard_gen_utime", + "prev_ref.root_hash,_key", + "prev_alt_ref.root_hash,_key", "tr_count, gen_utime", "chain_order", "gen_utime, chain_order", From bfc9949a26ed276a429b39864af2f5b68d6b107e Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Fri, 10 Feb 2023 15:10:28 +0100 Subject: [PATCH 11/26] rename giver keys --- contracts/giver_v2/{GiverV2.keys.json => seGiver.keys.json} | 0 contracts/giver_v3/seGiver.keys.json | 4 ++++ 2 files changed, 4 insertions(+) rename contracts/giver_v2/{GiverV2.keys.json => seGiver.keys.json} (100%) create mode 100644 contracts/giver_v3/seGiver.keys.json diff --git a/contracts/giver_v2/GiverV2.keys.json b/contracts/giver_v2/seGiver.keys.json similarity index 100% rename from contracts/giver_v2/GiverV2.keys.json rename to contracts/giver_v2/seGiver.keys.json diff --git a/contracts/giver_v3/seGiver.keys.json b/contracts/giver_v3/seGiver.keys.json new file mode 100644 index 0000000..e3d8285 --- /dev/null +++ b/contracts/giver_v3/seGiver.keys.json @@ -0,0 +1,4 @@ +{ + "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", + "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3" +} \ No newline at end of file From 41a6740072fe36f7ea442b23fb27b742f8981a50 Mon Sep 17 00:00:00 2001 From: Michael Vlasov Date: Mon, 13 Feb 2023 14:20:26 +0300 Subject: [PATCH 12/26] NEW: node generates new key block on startup if blockchain config was changed SDK-4400 --- node/src/block/finality.rs | 4 +-- node/src/engine/engine.rs | 4 ++- node/src/engine/masterchain.rs | 53 ++++++++++++++++++++++++++++++++-- node/src/engine/shardchain.rs | 5 ++++ 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/node/src/block/finality.rs b/node/src/block/finality.rs index 12c119b..2941d8b 100644 --- a/node/src/block/finality.rs +++ b/node/src/block/finality.rs @@ -70,7 +70,7 @@ where // need to remove blocks_by_no: HashMap>, // need to remove - last_finalized_block: Box, + pub(crate) last_finalized_block: Box, } fn key_by_seqno(seq_no: u32, vert_seq_no: u32) -> u64 { @@ -856,7 +856,7 @@ pub struct ShardBlock { serialized_block: Vec, root_hash: UInt256, file_hash: UInt256, - block: Block, + pub(crate) block: Block, shard_state: Arc, } diff --git a/node/src/engine/engine.rs b/node/src/engine/engine.rs index 9f80847..7e5d0e1 100644 --- a/node/src/engine/engine.rs +++ b/node/src/engine/engine.rs @@ -122,7 +122,9 @@ impl TonNodeEngine { control_receiver.run(Box::new(live_control))?; } - if !self.workchain.finality_was_loaded { + if self.workchain.finality_was_loaded { + self.masterchain.restore_state()?; + } else { self.initialize_blockchain()?; } thread::spawn(move || loop { diff --git a/node/src/engine/masterchain.rs b/node/src/engine/masterchain.rs index ea13869..4f4d0f9 100644 --- a/node/src/engine/masterchain.rs +++ b/node/src/engine/masterchain.rs @@ -7,9 +7,11 @@ use std::collections::HashMap; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use ton_block::{BinTree, Block, InRefValue, McBlockExtra, Serializable, ShardDescr, ShardIdent}; +use ton_block::{ + BinTree, BinTreeType, Block, InRefValue, McBlockExtra, Serializable, ShardDescr, ShardIdent, +}; use ton_executor::BlockchainConfig; -use ton_types::UInt256; +use ton_types::{SliceData, UInt256}; pub struct Masterchain { shardchain: Shardchain, @@ -107,4 +109,51 @@ impl Masterchain { log::trace!(target: "node", "master block generated successfully"); Ok(Some(master_block)) } + + fn get_last_finalized_mc_extra(&self) -> Option { + self.shardchain + .get_last_finalized_block() + .map_or(None, |block| block.read_extra().ok()) + .map_or(None, |extra| extra.read_custom().ok()) + .flatten() + } + + pub(crate) fn restore_state(&self) -> NodeResult<()> { + if !self.shardchain.finality_was_loaded { + return Ok(()); + } + if let Some(mc) = self.get_last_finalized_mc_extra() { + { + let mut shards = self.shards.write(); + mc.shards().iterate_with_keys(&mut |workchain_id: i32, + InRefValue(tree): InRefValue< + BinTree, + >| { + tree.iterate(&mut |shard: SliceData, descr: ShardDescr| { + let shard = ShardIdent::with_tagged_prefix( + workchain_id, + shard_ident_to_u64(shard.cell().data()), + ) + .unwrap(); + shards.insert(shard, descr); + Ok(true) + }) + })?; + self.shards_has_been_changed.store(true, Ordering::Relaxed); + } + if let Some(last_config) = mc.config() { + if last_config != self.shardchain.blockchain_config.raw_config() { + self.generate_block(0, false)?; + } + } + } + Ok(()) + } +} + +fn shard_ident_to_u64(shard: &[u8]) -> u64 { + let mut shard_key = [0; 8]; + let len = std::cmp::min(shard.len(), 8); + shard_key[..len].copy_from_slice(&shard[..len]); + u64::from_be_bytes(shard_key) } diff --git a/node/src/engine/shardchain.rs b/node/src/engine/shardchain.rs index 74ceb56..9419c1d 100644 --- a/node/src/engine/shardchain.rs +++ b/node/src/engine/shardchain.rs @@ -119,4 +119,9 @@ impl Shardchain { .put_block_with_info(block, new_state.clone())?; Ok(new_state) } + + /// get last finalized block + pub fn get_last_finalized_block(&self) -> NodeResult { + Ok(self.finalizer.lock().last_finalized_block.block.clone()) + } } From 5ec39830a1deb2723fe4da8309127efff95b6725 Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Mon, 13 Feb 2023 20:48:08 +0300 Subject: [PATCH 13/26] Deploy givers with internal messages --- contracts/giver_v3/README.md | 23 +++++ .../data/deprecated_giver_abi2_deploy_msg.boc | Bin 1114 -> 0 bytes node/data/giver_abi1_deploy_msg.boc | Bin 1511 -> 1540 bytes node/data/giver_abi2_deploy_msg.boc | Bin 1061 -> 1031 bytes node/data/giver_abi2_v3_deploy_msg.boc | Bin 0 -> 876 bytes node/data/safemultisig_deploy_msg.boc | Bin 4545 -> 4479 bytes node/src/engine/engine.rs | 81 ++++++------------ node/src/engine/mod.rs | 3 +- 8 files changed, 51 insertions(+), 56 deletions(-) delete mode 100644 node/data/deprecated_giver_abi2_deploy_msg.boc create mode 100644 node/data/giver_abi2_v3_deploy_msg.boc diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index d55449e..cfbb167 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -2,6 +2,29 @@ This directory contains Giver v3 contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. +In Evernode SE this giver is predeployed at `0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5` address +and its initial balance is about 5 billion tokens. + +## Keys: +* Public: `2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16` +* Secret: `172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3` + +## Usage +Method: `sendTransaction` + +parameters: +* `dest`: `address` - destination address; +* `value`: `uint128` - amount to send, in nanotokens; +* `bounce`: `bool` - bounce flag of the message. + +### Using tonos-cli: +```commandline +tonos-cli call 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 \ + sendTransaction '{"dest":"
","value":,"bounce":false}' \ + --abi GiverV3.abi.json \ + --sign GiverV3.keys.json +``` + ## How to deploy GiverV3 on any network ### Setup your signer diff --git a/node/data/deprecated_giver_abi2_deploy_msg.boc b/node/data/deprecated_giver_abi2_deploy_msg.boc deleted file mode 100644 index 5437b0eb88636a686b57680104c7edd222e964b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1114 zcmZ{jeN0nl6vp587HDg4KkNqB3fzw-n@gy);DT|u7Es2>L>I(CK#Od!jS0Q5Aj@KG zA+;>~s8Ys42pJ#NNFc@1n0yNyg=s~MXR8hn2gzVciUSBdv}@1vW@Kgb@H5Z za-RH7&gVaNH$XxUK};ba?!O1$n#re*oVbg12e&+T6Wcq+h9-V^Ey+L9Id#gM{&7aZ z+V+paKH^Z>ck&9h>bQINH(PSb&wSMsceU|asp`abb;q&E;a_r7E>fFQhWbpk?sta2 zFM1*TjX+NA6TH0ZV||WJU%Cei<2N zqJTyP%@7DGy3HIqs{nC$VHHH{lOn`!6h+e4kMzTVpU9FOU zC2Lhser}<2X_p%QfwJp7TG9P~e21pFT08N0jk^N|6&6Q3$8qy*v?tSGFxUw@JI?Y7 z%m0szkN3X0KyemhG{ zPy!flDX9?Ezk^p)H%mHM-VBF7spqW>pV(2)XET%Y^p*PGL78b3d$cHLd;+69UI9=6 z6u_0m-602h9b6ht7`l&T#_6wb4RpomA8fW}JaRm$NO6uRcVf~)-X>qZc-VPrL|F(- zvXth~E9d7Nm@K5oI*Q~mnN@aMHnT6Uq0U0yv;n!N^X7LsoOeu6q8|* zW&9H`cp?5_yUmrbFt_pB9ZJixNo}>cPhvOaw!4iFeM&AE-Mb@MnYp~ojmlRtTDh!c z*{8Ewlfr&&YPeULB@i$DRB7qm5Z5h8Qw4(bruk#THrIegqt1VGS2B0@w`itRs(MB% zdlGm(Mr2^&g&tI3fDBwYbD7DEYC`{y+$LEKNn|A2PfP%p&)wVKY7;???H%aS{~J-+ zjV_DKCi5w0@>J`C`^w1?K&>Lt1Mg84E`9RxTZ4x|-s<{aq=*~3b-;MqmHOcbb{z=& z)vjL3N`886rxVjM(0Gza;^Z?%>DGp1&QAiJT(yx%=BA@*hO6=BBp_Fjn)D5fTKwhN S37sec3Q(?t57G>i3x5I~!qSES diff --git a/node/data/giver_abi1_deploy_msg.boc b/node/data/giver_abi1_deploy_msg.boc index 2d6108010d13f905edc4fb39182e3c6fdb62fcff..95ded4d727e36439a9febe3bf1cfa03628c32a70 100644 GIT binary patch delta 271 zcmaFP-NM7a_1&BzMkZB82G$=8OshR63M%+$GAObvvi7@LR-FBcae@4S723_L%T`v` zFVcLJIf;`iHfkvYGGLU@n7~xZ#>mKcfQgCuyaFpTBjY_52IdP2430M@CQ3{!V4qki zE+x#)$n|B3!k2{{Ow4B;1UQ)(&+&3GF)HwIPh2I%#LqYJSTU23;ACsY0wyVu$!i&l z7)2*5Fx4@NO`gw`!6-hNgV~l*VzL`^qogDQ%WVUoP8n$i{ymSs3s|<@YyooRWG6ph z_To~KXXM<`$)FyfFxiBqkx_B-HkRp(%9H(A%jHxU%;qUHD2FD-vww78jAy@X@IYA+ G&I158r%5UR delta 218 zcmV<0044u~4Cf0GweFm9K?EiN00005)c^xuh>;H_&)6B3hL0dN8v6_d^Zasd{TK>~gO7n8sOXaN|LDFZzL8IxxN zff*VA1luqI0U#Y501v$5_YgUT*@OZCARiu+0R&14BOn0@xQPHKP$8351c3n}lh*{7 U0VI=e1$O}@ljj8;1oj9l)DC_+`2YX_ diff --git a/node/data/giver_abi2_deploy_msg.boc b/node/data/giver_abi2_deploy_msg.boc index 3eb611d57ff558bf86a853bcae2144a025afc1a7..50781714160dc4b44c09bc6e8a978bafff4994c0 100644 GIT binary patch delta 81 zcmZ3=(ayoY_1&BzMkWPD2Ik)kOshR6@++8XGgw>3eU=tEu;Bfs_ep&xO+Kc{o0sz| e-8=Js_M{m{CONV?FdzX&iHlkL>NhqmW(EM06C3^j delta 111 zcmV-#0FeKO2&D)QweFm90RkWa00bET0_TX44G RfnWds|MrVj^Z2o3qXWOeGJ603 diff --git a/node/data/giver_abi2_v3_deploy_msg.boc b/node/data/giver_abi2_v3_deploy_msg.boc new file mode 100644 index 0000000000000000000000000000000000000000..03bcef403c8a7153705cce8e986496a23ef66ddb GIT binary patch literal 876 zcmZ{iZAep57{|{!cjk1d%eU)?bmwjs5h0r|A+c(xMM_2BqN11erpQt^Q~D5vOS9<3 z^)fAsAPXU*`XpLe*;-JR;qJP^J}idp(i^gf+r^GruA_pip!4Z}9-im?f6sHC-fuS! zLzDplvlpOy8(^C|_4ni3kCrOO$Jv3r^QB`KhnWV5Fs7*H-Mn za78`@DK<%x01FnAGEzjjyv?-tu=x*z&w-Hu literal 0 HcmV?d00001 diff --git a/node/data/safemultisig_deploy_msg.boc b/node/data/safemultisig_deploy_msg.boc index f1ea8b9aa1a492dd2a932e32f50c4a606082452f..c5cde7618394382fb42160d55c6566a0dae654ab 100644 GIT binary patch delta 463 zcmYj~%}W$<9L9g&-*4V_W_D+$tkunIbTfO~Qa9aI$91)`%_YS;*kPfB*t&#^1_=?n zLkA%uSf0HVk<>A)4n@+X{(_}~sIV947zE*-BCNqv&*5`;;Q2hS<9|D>XFu=G6Q3aF zEHLprSGC;XJFM^e!mmU=|7h;wwcI$DU(d4tLd_q%w~Ij` zNaa*r=`sWtbytyyzR1;Yo}+7|Hy*l;+^~TJ70E=6W}WUx(70BBW;?(Z2MRBV zt#k<)t5;OrCaiFuZ{LOiy@=6h14h0FW4xvoZZk$nk(aGj9?F_(H73xA%^~GK`fx6s@SL%7% zk9KX44xpe_=pa68SH&Uvvw64_nxw;cA1au~djj!bZ-BleGI~)QVHZ%AlK7;brG6xh z(|jz2C1Zxt_-gnxfLZf04WVu>l80P)hK6xJT++ufq~ET5mp+al7V#*%IT^*{$Qm8R kEz754h}ix7qa`Je4rwS+$Pa#L@Y?UBJ`= zkwyuvz8(=RSNf$99R--XT_1eNSH8~wHUE3CyS``DI58YOSlD{+LtgaFNKevJsJ@!> zUQv!NWS)}`U$eezw8`HtKlo@ZFBx(+``b9BE9FNwugo;bW$qg_rUFxX)PCvYzDM^R zzQ-?Gj>KLO67>J9&0SR!=lbi2nkEMmX}23#hE7^I4Zs&|WY8-a^uR9;TNa0SLKv_l z36VJkjMxCpl2cSgcCw0eNkz&!oPbW63T@a-T{L1bVLKCM($?c2<_v7W7+NAhe8 zDE7@buBn49C~3nqhjgJR$@o^Qg=iCR32KdvP>MlgC+{l*zAyBh{alWpj9#c% ztL(v!q*66Bpc>+1V{JB^0w;QsWm*F(xWe18KlvElO9s)&Wnh$XVU;BR E2R8z_O#lD@ diff --git a/node/src/engine/engine.rs b/node/src/engine/engine.rs index 9f80847..e6a7594 100644 --- a/node/src/engine/engine.rs +++ b/node/src/engine/engine.rs @@ -21,9 +21,9 @@ use crate::data::DocumentsDb; use crate::engine::masterchain::Masterchain; use crate::engine::shardchain::Shardchain; use crate::engine::{ - InMessagesQueue, LiveControl, LiveControlReceiver, DEPRECATED_GIVER_ABI2_DEPLOY_MSG, - GIVER_ABI1_DEPLOY_MSG, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, MULTISIG_BALANCE, - MULTISIG_DEPLOY_MSG, + InMessagesQueue, LiveControl, LiveControlReceiver, + GIVER_ABI1_DEPLOY_MSG, GIVER_ABI2_DEPLOY_MSG, GIVER_ABI2_V3_DEPLOY_MSG, GIVER_BALANCE, + MULTISIG_BALANCE, MULTISIG_DEPLOY_MSG, }; use crate::error::NodeResult; use crate::MessagesReceiver; @@ -38,8 +38,8 @@ use std::{ time::Duration, }; use ton_block::{ - CommonMsgInfo, CurrencyCollection, Deserializable, Grams, InternalMessageHeader, Message, - MsgAddressInt, ShardIdent, UnixTime32, + CurrencyCollection, Deserializable, Grams, Message, + MsgAddressInt, ShardIdent, UnixTime32, MsgAddressIntOrNone, }; use ton_executor::BlockchainConfig; use ton_types::AccountId; @@ -207,14 +207,9 @@ impl TonNodeEngine { log::info!(target: "node", "Initialize blockchain"); let workchain_id = self.workchain.shard_ident.workchain_id() as i8; self.enqueue_deploy_message(workchain_id, GIVER_ABI1_DEPLOY_MSG, GIVER_BALANCE, 1)?; - self.enqueue_deploy_message(workchain_id, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, 3)?; - self.enqueue_deploy_message(workchain_id, MULTISIG_DEPLOY_MSG, MULTISIG_BALANCE, 5)?; - self.enqueue_deploy_message( - workchain_id, - DEPRECATED_GIVER_ABI2_DEPLOY_MSG, - GIVER_BALANCE, - 7, - )?; + self.enqueue_deploy_message(workchain_id, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, 2)?; + self.enqueue_deploy_message(workchain_id, GIVER_ABI2_V3_DEPLOY_MSG, GIVER_BALANCE, 3)?; + self.enqueue_deploy_message(workchain_id, MULTISIG_DEPLOY_MSG, MULTISIG_BALANCE, 4)?; Ok(()) } @@ -225,20 +220,17 @@ impl TonNodeEngine { deploy_msg_boc: &[u8], initial_balance: u128, transfer_lt: u64, - ) -> NodeResult { - let (deploy_msg, deploy_addr) = - Self::create_contract_deploy_message(workchain_id, deploy_msg_boc); - let transfer_msg = Self::create_transfer_message( + ) -> NodeResult<()> { + let deploy_msg = Self::create_contract_deploy_message( workchain_id, MINTER_ADDRESS.address(), - deploy_addr.clone(), + deploy_msg_boc, initial_balance, transfer_lt, ); - self.queue_with_retry(transfer_msg)?; self.queue_with_retry(deploy_msg)?; - Ok(deploy_addr) + Ok(()) } fn queue_with_retry(&self, message: Message) -> NodeResult<()> { @@ -251,48 +243,29 @@ impl TonNodeEngine { Ok(()) } - fn create_contract_deploy_message(workchain_id: i8, msg_boc: &[u8]) -> (Message, AccountId) { - let mut msg = Message::construct_from_bytes(msg_boc).unwrap(); - if let CommonMsgInfo::ExtInMsgInfo(ref mut header) = msg.header_mut() { - match header.dst { - MsgAddressInt::AddrStd(ref mut addr) => addr.workchain_id = workchain_id, - _ => panic!("Contract deploy message has invalid destination address"), - } - } - - let address = msg.int_dst_account_id().unwrap(); - - (msg, address) - } - - // create transfer funds message for initialize balance - pub fn create_transfer_message( + fn create_contract_deploy_message( workchain_id: i8, src: AccountId, - dst: AccountId, + msg_boc: &[u8], value: u128, lt: u64, ) -> Message { - let hdr = Self::create_transfer_int_header(workchain_id, src, dst, value); - let mut msg = Message::with_int_header(hdr); + let mut msg = Message::construct_from_bytes(msg_boc).expect("Can not parse contract deploy message"); + let mut header = msg.int_header_mut().expect("Contract deploy message is not internal"); + match header.dst { + MsgAddressInt::AddrStd(ref mut addr) => { + addr.workchain_id = workchain_id; + } + _ => panic!("Contract deploy message has invalid destination address"), + } + header.src = MsgAddressIntOrNone::Some(MsgAddressInt::with_standart(None, workchain_id, src).unwrap()); + header.value = CurrencyCollection::from_grams(Grams::new(value).unwrap()); + header.bounce = false; + header.created_lt = lt; + header.created_at = UnixTime32::now(); - msg.set_at_and_lt(UnixTime32::now().as_u32(), lt); msg } - - pub fn create_transfer_int_header( - workchain_id: i8, - src: AccountId, - dst: AccountId, - value: u128, - ) -> InternalMessageHeader { - InternalMessageHeader::with_addresses_and_bounce( - MsgAddressInt::with_standart(None, workchain_id, src).unwrap(), - MsgAddressInt::with_standart(None, workchain_id, dst).unwrap(), - CurrencyCollection::from_grams(Grams::new(value).unwrap()), - false, - ) - } } #[cfg(test)] diff --git a/node/src/engine/mod.rs b/node/src/engine/mod.rs index 4caa37a..eb7f471 100644 --- a/node/src/engine/mod.rs +++ b/node/src/engine/mod.rs @@ -26,9 +26,8 @@ mod masterchain; const GIVER_BALANCE: u128 = 5_000_000_000_000_000_000; const MULTISIG_BALANCE: u128 = 1_000_000_000_000_000; const GIVER_ABI1_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi1_deploy_msg.boc"); -const DEPRECATED_GIVER_ABI2_DEPLOY_MSG: &[u8] = - include_bytes!("../../data/deprecated_giver_abi2_deploy_msg.boc"); const GIVER_ABI2_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi2_deploy_msg.boc"); +const GIVER_ABI2_V3_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi2_v3_deploy_msg.boc"); const MULTISIG_DEPLOY_MSG: &[u8] = include_bytes!("../../data/safemultisig_deploy_msg.boc"); pub trait MessagesReceiver: Send { From 70359d75a7806fef6bb2cee38c6f2c855806dd5a Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Tue, 14 Feb 2023 12:01:04 +0100 Subject: [PATCH 14/26] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 921601c..da8fa73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ All notable changes to this project will be documented in this file. ### New -- Masterchain block producing. -- `global_id` parameter in `ton-node.conf.json` is written into blocks. -- `global_id` parameter is used as a `signature_id` if related cap is turned +- Produces masterchain block for each workchain block. +- Added ability to update blockchain config with node restart (without killing the database). After [changing the config](https://github.com/tonlabs/evernode-se#how-to-change-the-blockchain-configuration) stop and start the node to apply it. It will produce new key block from the new config. +- `CapSignatureWithId` capability is supported: `global_id` parameter is used as a `signature_id` if `CapSignatureWithId` cap is turned on in the blockchain config. +### Fixed +- `global_id` parameter in `ton-node.conf.json` is written into blocks. + + ## 0.36.3 Jan 11, 2023 ### Fixed From 57f16d2b20308a242bb3a8971c19e1a225928542 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Tue, 14 Feb 2023 12:32:43 +0100 Subject: [PATCH 15/26] Update README.md --- contracts/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/README.md b/contracts/README.md index 2111274..b8e1c34 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,5 +1,8 @@ # Smart Contracts, used in Evernode SE -* [Giver v2](giver_v2) -* [SafeMultisig Wallet](safe_multisig) +| Giver type | Address | Note +| ------------ | -------------------------------------------------------------------| +| GiverV1 | 0:841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94 | deprecated. Recommended to use GiverV3 +| [GiverV2](giver_v2) | 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 | deprecated. Recommended to use GiverV3 +| [GiverV3](giver_v3) | 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 | Recommented Giver version From 69e470561cf164c9c4b121c376af9a9497226b0b Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Tue, 14 Feb 2023 12:38:24 +0100 Subject: [PATCH 16/26] Update README.md --- contracts/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/README.md b/contracts/README.md index b8e1c34..17d6f35 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,8 +1,10 @@ # Smart Contracts, used in Evernode SE -| Giver type | Address | Note -| ------------ | -------------------------------------------------------------------| -| GiverV1 | 0:841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94 | deprecated. Recommended to use GiverV3 -| [GiverV2](giver_v2) | 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 | deprecated. Recommended to use GiverV3 +|Giver type | Address | Comment +| --------------- | -------------------------------------------------------------------|------ | [GiverV3](giver_v3) | 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 | Recommented Giver version +| [SafeMultisig](safe_multisig) | 0:d5f5cfc4b52d2eb1bd9d3a8e51707872c7ce0c174facddd0e06ae5ffd17d2fcd | Safe Multisig as Giver. +| [GiverV2](giver_v2) | 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 | Deprecated. Recommended to use GiverV3 +| GiverV1 | 0:841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94 | Deprecated. Recommended to use GiverV3 + From a76d1a0a8ad591ef8a79e59451f1b47f26110392 Mon Sep 17 00:00:00 2001 From: Sergei Voronezhskii Date: Wed, 15 Feb 2023 11:10:25 +0300 Subject: [PATCH 17/26] Rename giver keys in readme --- contracts/giver_v3/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index cfbb167..9e15de6 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -22,7 +22,7 @@ parameters: tonos-cli call 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 \ sendTransaction '{"dest":"
","value":,"bounce":false}' \ --abi GiverV3.abi.json \ - --sign GiverV3.keys.json + --sign seGiver.keys.json ``` ## How to deploy GiverV3 on any network @@ -37,13 +37,13 @@ npx everdev signer default devnet_giver_keys ### [Optional] Verify Giver contract bytecode This contract is compiled with `0.66.0 ` Solidity and `0.19.3`Linker version. -To check that the code hash of the compiled version from repository is equal to your freshly compiled version, run this command and check that the Code Hash is +To check that the code hash of the compiled version from repository is equal to your freshly compiled version, run this command and check that the *Code Hash* is `5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989`. ```shell npx everdev sol set --compiler 0.66.0 --linker 0.19.3 npx everdev sol compile GiverV3.sol -npx everdev c i --signer devnet_giver_keys GiverV3 +npx everdev contract info --signer devnet_giver_keys GiverV3 Configuration @@ -56,9 +56,9 @@ Code Hash: 5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989 (fro ### Get your Giver address and top it up The address is calculated from the compiled contract codehash and your public key. -Run this command to see the address: +Run this command to see the *Address*: ```shell -npx everdev c i --signer devnet_giver_keys GiverV3 +npx everdev contract info --signer devnet_giver_keys GiverV3 ``` Now, you need to top up your giver. Transfer tokens from Surf wallet or Everwallet. From 4d89ed78ff379aaba837faeaadff535b17dcb083 Mon Sep 17 00:00:00 2001 From: Sergei Voronezhskii Date: Wed, 15 Feb 2023 11:13:17 +0300 Subject: [PATCH 18/26] Rename giver keys in readme --- contracts/giver_v2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/giver_v2/README.md b/contracts/giver_v2/README.md index 9fd9b77..00dddab 100644 --- a/contracts/giver_v2/README.md +++ b/contracts/giver_v2/README.md @@ -25,7 +25,7 @@ parameters: tonos-cli call 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 \ sendTransaction '{"dest":"
","value":,"bounce":false}' \ --abi GiverV2.abi.json \ - --sign GiverV2.keys.json + --sign seGiver.keys.json ``` From 49e545d11479a61cd6d7ac5a92129565f4fda577 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Wed, 15 Feb 2023 09:30:58 +0100 Subject: [PATCH 19/26] fix tvc --- contracts/giver_v3/GiverV3.abi.json | 2 +- contracts/giver_v3/GiverV3.tvc | Bin 791 -> 800 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/giver_v3/GiverV3.abi.json b/contracts/giver_v3/GiverV3.abi.json index 8e53d70..7681a38 100644 --- a/contracts/giver_v3/GiverV3.abi.json +++ b/contracts/giver_v3/GiverV3.abi.json @@ -46,4 +46,4 @@ {"name":"_constructorFlag","type":"bool"}, {"name":"m_messages","type":"map(uint256,uint32)"} ] -} \ No newline at end of file +} diff --git a/contracts/giver_v3/GiverV3.tvc b/contracts/giver_v3/GiverV3.tvc index 5c880dcc349be26d32dd3b16a8ba4b7eaa78f96f..854ad68b712532e5c6b6b25b77d2e4228172769a 100644 GIT binary patch delta 229 zcmbQvwt$U$>$^Ecj7$=Y49p@Ext%rGSy>nu7#Y}@{=Id%aNYATlS#?ohg05Th97R9iZA|PxNY-^ zforl2qq?Gv0Z{0H4_H!h@|BAh?)`GOTz`q-;%ys{A|am1t&H?{%Vnl# Nz$mr=Bs7Ux8~~>oSzZ7D delta 195 zcmZ3$Hl2-o>$^Ecj7$=Y49wgUxt-CL{Y~W=1U*ejYB4$%c%=jGU8Q8Pyr>Cg(Cru^ZgB`NSZ^J-L^0 zJ|pjBT_!IzJ_dn&CB_q{|DTp;)-d?t_UVDo52w7x3|B7Rwt=V?5NC>+Jcmh#rpcF>bQKNtj2OihFaTY2+vW%VCkAl_nIB$1oPY+MZ~nq?@@)tJwVXhV From 3bf1e819aa890b8f24608060f16a1a34b44c0281 Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Thu, 16 Feb 2023 20:45:10 +0300 Subject: [PATCH 20/26] Update giver v3 address --- contracts/giver_v3/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index 9e15de6..122adda 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -2,7 +2,7 @@ This directory contains Giver v3 contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. -In Evernode SE this giver is predeployed at `0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5` address +In Evernode SE this giver is predeployed at `0:cbd3ef42dcc261b9369fdb15fb836b460d4806c5b255e31541c46d6676a2f13d` address and its initial balance is about 5 billion tokens. ## Keys: @@ -19,7 +19,7 @@ parameters: ### Using tonos-cli: ```commandline -tonos-cli call 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 \ +tonos-cli call 0:cbd3ef42dcc261b9369fdb15fb836b460d4806c5b255e31541c46d6676a2f13d \ sendTransaction '{"dest":"
","value":,"bounce":false}' \ --abi GiverV3.abi.json \ --sign seGiver.keys.json From af43b3f588ff59f5ad0ad6a3f897e8061039995f Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Thu, 16 Feb 2023 22:11:47 +0300 Subject: [PATCH 21/26] Zerostate with predeployed givers --- .gitignore | 1 - contracts/README.md | 2 +- .../WC0/shard_8000000000000000/zerostate | Bin 0 -> 8974 bytes node/data/giver_abi1_deploy_msg.boc | Bin 1540 -> 0 bytes node/data/giver_abi2_deploy_msg.boc | Bin 1031 -> 0 bytes node/data/giver_abi2_v3_deploy_msg.boc | Bin 876 -> 0 bytes node/data/safemultisig_deploy_msg.boc | Bin 4479 -> 0 bytes node/src/block/finality.rs | 26 +++++- node/src/engine/engine.rs | 83 +----------------- node/src/engine/mod.rs | 7 -- node/src/engine/shardchain.rs | 2 - 11 files changed, 26 insertions(+), 95 deletions(-) create mode 100644 docker/ton-node/workchains/WC0/shard_8000000000000000/zerostate delete mode 100644 node/data/giver_abi1_deploy_msg.boc delete mode 100644 node/data/giver_abi2_deploy_msg.boc delete mode 100644 node/data/giver_abi2_v3_deploy_msg.boc delete mode 100644 node/data/safemultisig_deploy_msg.boc diff --git a/.gitignore b/.gitignore index 146cb24..bf4d05a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ block-signer-config.json /ton-node-se/pub-key /ton-node-se/log_cfg.yml /ton-node-se/tonos-se-tests -workchains docker/.DS_Store readme.html /dev/node_modules/ diff --git a/contracts/README.md b/contracts/README.md index 17d6f35..469f080 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -2,7 +2,7 @@ |Giver type | Address | Comment | --------------- | -------------------------------------------------------------------|------ -| [GiverV3](giver_v3) | 0:ca600a7edcd15c13047b7b0bdf19c624f5c7fa3474d38afe323a373b0bdb30f5 | Recommented Giver version +| [GiverV3](giver_v3) | 0:cbd3ef42dcc261b9369fdb15fb836b460d4806c5b255e31541c46d6676a2f13d | Recommented Giver version | [SafeMultisig](safe_multisig) | 0:d5f5cfc4b52d2eb1bd9d3a8e51707872c7ce0c174facddd0e06ae5ffd17d2fcd | Safe Multisig as Giver. | [GiverV2](giver_v2) | 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 | Deprecated. Recommended to use GiverV3 | GiverV1 | 0:841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94 | Deprecated. Recommended to use GiverV3 diff --git a/docker/ton-node/workchains/WC0/shard_8000000000000000/zerostate b/docker/ton-node/workchains/WC0/shard_8000000000000000/zerostate new file mode 100644 index 0000000000000000000000000000000000000000..b9ecb1f3495cfd2b8890dd34366e61ca5262fd56 GIT binary patch literal 8974 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 U{`8#$yUh-d7OGoT!OY_Q7d5Do%m4rY literal 0 HcmV?d00001 diff --git a/node/data/giver_abi1_deploy_msg.boc b/node/data/giver_abi1_deploy_msg.boc deleted file mode 100644 index 95ded4d727e36439a9febe3bf1cfa03628c32a70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1540 zcmcgsdrVtZ96slkwwISsKpvymb8p)?vMjW>3?VL3;vOXGhK~ktm@A`AM>e>Z+rlIR zDd@Cw%^fa_8d+vthGJ&+pqV_xtu7>V2}&~{FfnA}A2TG~7&Zzzil=p(h54U}H}{^L zbAI3X&hI6~*q<=Q~SZ znxD)CRLtq8cTG0g_RmAN%G!i2$W1m1OKHTLu_0H$P0sKP{r|}`=|E;FIVV-?o>I9!&AXeNka0SF*%li z-zUZq5GBL|c|yS`0y$e{rQFu@WNDSMh4|3x#<8Tw07PK2__DV$t77IxR{3;gmeTo5 zXTs%9XZA3uJm;*s{bftPs&voro}qq~kYl*&b#@JVuD1KShJ7c`bvtKf_^n##(*Z5l;*(-Z~RbY`{H;prXByQuq0*Qf8jm)hs7 z`^X5oyW3hF7cQP3EYkHAd6)rnk=3oR9tMTC+%0L=qbb&-iWP_lg{=_3Mr3ujC~h4- zHehupo8NDBw6#Sq&g<=C@;bbD#|>%l=4xmK)>YTmvz9mP7NNfS03}w2?m?@?&f0_; zw%TkKkROc$hW|#~fU(g59q+s5Hz`TySj|HeYpFN0QcMNKRD4Wf1+_NTQpekySs6};9#`e7$BVb14A>+(ro}ugbZ@=-f*Ol|)djTbY9 zaKn7iL1rH`GIO+cK)a-Fm;BPBaSvP&bA1{Z1lqCqVj6$cSUS2Ecm?Mi#mcnFB3ZAU zHSkhangwvZut${HAZh65-;;~px$!n0K9K{Ce61ZF`oxh$BpQBABJ%EdGvwt3@5*)< z4(|BPuxsLlB%@NCXu6A3MnZXaZ^Eg`-FN)akY}X}n>{4vqE#@q{|I=p3}Lk^u!gI* z*@cK&R>$)ZQEN4eY3O=bG;SEwFtz=J}*7*`o7MFv62T;*HY?P{KwKQP*^M9 zXxqn|Yo4-mHTmH(LmvgU1$J^N_`LpE9F5Y2Jr3u7#A!yVSzG@hKDZ_de0FS0W1yhzReF8qCWKG35N`v+^)rj*Y3N9*+J3 D2}NF` diff --git a/node/data/giver_abi2_deploy_msg.boc b/node/data/giver_abi2_deploy_msg.boc deleted file mode 100644 index 50781714160dc4b44c09bc6e8a978bafff4994c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmbVKZEQ)*U9^w_dL)0Jnx0~N7f;s z2)YE2mO1$N&gX_l#|;Cv9@>(I{xL5*&=@}# zFZZ<&IX4W?){Yp|nmNfIbw?lOJEf?ddFSI8bsXLbfbXO;<5FTHE{vLF*5 zvZ4xKmZteHwNhAETSe)4c~DghLVU^Jp3*Z};JOcwrR{io0s=K(*+&hdrcb zjp%5vPH1B!)A`faVX)IThGW*&!@o>iYGZDxUqe&+lbbhO3-`^6+6B3At-o*|g#TQt zzJ_Nen$XiwY-Fsoi`e>RBTq)=BhDEC#^g9sk-e~{; diff --git a/node/data/giver_abi2_v3_deploy_msg.boc b/node/data/giver_abi2_v3_deploy_msg.boc deleted file mode 100644 index 03bcef403c8a7153705cce8e986496a23ef66ddb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 876 zcmZ{iZAep57{|{!cjk1d%eU)?bmwjs5h0r|A+c(xMM_2BqN11erpQt^Q~D5vOS9<3 z^)fAsAPXU*`XpLe*;-JR;qJP^J}idp(i^gf+r^GruA_pip!4Z}9-im?f6sHC-fuS! zLzDplvlpOy8(^C|_4ni3kCrOO$Jv3r^QB`KhnWV5Fs7*H-Mn za78`@DK<%x01FnAGEzjjyv?-tu=x*z&w-Hu diff --git a/node/data/safemultisig_deploy_msg.boc b/node/data/safemultisig_deploy_msg.boc deleted file mode 100644 index c5cde7618394382fb42160d55c6566a0dae654ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4479 zcmcgv3s6(p89wI*43Y)HLq)*l-Wvr)T@oH*w<<56;A5SL0}I{YV?hzPHz3xvXaZEb zk8TVKtyV0kRIPO#s0E=Y6SZ5TtX?qe#Ak@mx&p+qh zlXL$6|Nig)Ps2Z}3LudLfp;MgG|q>Ax>Nm0&ig-G^^13lg7%xO-)^t+f2TUFWuNZr zHhzDfVh@PkT=?D8tZ^RP< zC?p_AY+v|I==l+T7mw)*wq%dihNXr@Zdi;i?3T~Y{8f7X-y3%8Ak+y60Y{E-fzad% z1nnefY>j(zxIZ)Px#%L#zQ{$s2?Qq20yqithjLVC1U@n|KBRbGXzk z@aJ(g&8D3sT2-NrvRN%sLoh^=leT6&S|OU3uQg#yq@GxiURd~xvGDN*BTr-;iXh>| z#=m`bqg9-K;M10+QBk~|v+JBkS%CwAtpNi8)dT)p#%%ptLUuIj?F`tvL!VlCyQA2Fa&_b6QSrQ$-L@PbmY8ZW8mM8On86K%nEpf63$ z9QrSuD2w7`C4ybezfp2=6gQ?)$;DF_E#!ISLy#`j@tP?pLEpxsL{1co=5iu{l29^Q zjFzB$bcv&tvsfm-vGn4g`@yalKgh`x8I1&Fs zIT0U%#|hl%@tjB{;Y40E=SOkwK%@{shNfx-X=>7*$Pm#c8ZE>iDAoi(45VNOh#XMr zi!-PUUY$mFz=%|1K(6ziBBCQ@1hFA#EELu)ZRrSreJDO(6NZudnvgYh6sgG)PjRW6 zS3(?Gg8iL0@n+9ce^0;$V(Wz1x>y=pNn!oPz7GTy&vU=R)p`G8-wW$zT>fa>W0O93 zv&m>eb9dMxcPdeq#SmleeC=UbLRGetBxY z`I^bqx`!ZOuSb~R*l15a#B9FxB^^H=4rpSQ75Xp)L+dd(gcuyWO!f@)qv*%B7FR-} zNT}M$vaH1c+8%`fV=WzANqdSl=W}}kC>UmX55h}7wl@?GIGZt@9r)y%3#zbG@jPGW zU?tA)#YyqJjF3JJ=DlBiu6+mgJByya_{z?X_P)3- zqle0&8B|@yw}3;t4Dg(Aa8B6O*?|`8pv|1?;GjVQN^%eo0?P^$^xRhU1yIPvU4r4@ zSRbLz!4d@bkchhTW@OThVaWSBbMjld#05}s?YPE_`8 z?=9ad#d(jy;F{U+Yc3qL>Y7Ke*+YWLRd+U~7jb^H|R&>Ee+ z^|-ium#*ZijJE0BHRA5iE;M!5Xm5WfUfuLaJ#|;6N*4uIJ6or5EWT)v*KFt~Ps|&& zVgH)7d~bEH8cV*nthcO>*hKVC>z`H}(;rhD-5(v>FYS*kmi5b+wbecSv^Hje|8z!N z9HLXJHwnc_;Lg@EeUnoBfQ|6qrJF|7Xw+98gV>YQjD2D4F3+=2HgguqcuN#AWkWE1 zwC*fOkt$q{+sxUHkP#H)TT3%OtqC#kh(=B^V`yfygb5fD$;V-&nXxYlB;)@Opk$gE zMJYE*4jBS)>1h*-}X5yC^_tdf(@W>A-sra#uS2&7WIqN{dYMCr# zu$gMLnb%3$^B}9#c+T+&cB^1rAkQ9OjbzA({8wt_-H0^0~>^r z<k7W+ejhZ3W7DYOl1Q1gPs#C?jrAMVjP93Z)RBC8Q2&B9CrD9y)__}(Mm9UD* z%YEg)Tkf-b6eChla_tj9$Gssu$Agn^49^0}OW_6W4l{A*yU$^&qdVXBvhLjZI;Fs| zl}lPo3$3K(I;|EXSNan}dOK%I#pNEKvj+E2* zOmkXH5wpR{p4ZCiC%{KuiV?UDESL+gH#V-3IDK*C>=|P^B?7!(u{kr8-C zzr}I26nsq1!>)QY@kXW)gZ-rY)f&wZGGHdBxI1-gdmeSn2fzQHUMx{I$hpo^=fGaN oz0gP*ML-9&T8o)7dIW24$-Q+zYd$TY2XpVy$$G8%hwJ=*0R9D_UH||9 diff --git a/node/src/block/finality.rs b/node/src/block/finality.rs index 2941d8b..3f07f4e 100644 --- a/node/src/block/finality.rs +++ b/node/src/block/finality.rs @@ -242,10 +242,28 @@ where self.root_path.clone(), &self.shard_ident, )?; - shard_path.push("blocks_finality.info"); - log::info!(target: "node", "load: {}", shard_path.to_str().unwrap()); - let mut file_info = File::open(shard_path)?; - self.deserialize(&mut file_info)?; + let mut info_path = shard_path.clone(); + info_path.push("blocks_finality.info"); + log::info!(target: "node", "load: {}", info_path.to_str().unwrap()); + if let Ok(mut file_info) = File::open(info_path) { + self.deserialize(&mut file_info)?; + } else { + shard_path.push("zerostate"); + log::info!(target: "node", "load: {}", shard_path.to_str().unwrap()); + let zerostate = std::fs::read(shard_path)?; + self.load_zerostate(zerostate)?; + } + Ok(()) + } + + /// + /// Load zerostate + /// + fn load_zerostate(&mut self, zerostate: Vec) -> NodeResult<()> { + let mut zerostate = ShardStateUnsplit::construct_from_bytes(&zerostate)?; + zerostate.set_global_id(self.current_block.block.global_id()); + self.current_block.shard_state = Arc::new(zerostate.clone()); + self.last_finalized_block.shard_state = Arc::new(zerostate); Ok(()) } diff --git a/node/src/engine/engine.rs b/node/src/engine/engine.rs index 4309088..6b094d6 100644 --- a/node/src/engine/engine.rs +++ b/node/src/engine/engine.rs @@ -14,17 +14,12 @@ * under the License. */ -use crate::block::finality::MINTER_ADDRESS; #[cfg(test)] use crate::config::NodeConfig; use crate::data::DocumentsDb; use crate::engine::masterchain::Masterchain; use crate::engine::shardchain::Shardchain; -use crate::engine::{ - InMessagesQueue, LiveControl, LiveControlReceiver, - GIVER_ABI1_DEPLOY_MSG, GIVER_ABI2_DEPLOY_MSG, GIVER_ABI2_V3_DEPLOY_MSG, GIVER_BALANCE, - MULTISIG_BALANCE, MULTISIG_DEPLOY_MSG, -}; +use crate::engine::{InMessagesQueue, LiveControl, LiveControlReceiver}; use crate::error::NodeResult; use crate::MessagesReceiver; use parking_lot::Mutex; @@ -35,14 +30,9 @@ use std::{ Arc, }, thread, - time::Duration, -}; -use ton_block::{ - CurrencyCollection, Deserializable, Grams, Message, - MsgAddressInt, ShardIdent, UnixTime32, MsgAddressIntOrNone, }; +use ton_block::ShardIdent; use ton_executor::BlockchainConfig; -use ton_types::AccountId; #[cfg(test)] #[path = "../../../../tonos-se-tests/unit/test_ton_node_engine.rs"] @@ -124,9 +114,8 @@ impl TonNodeEngine { if self.workchain.finality_was_loaded { self.masterchain.restore_state()?; - } else { - self.initialize_blockchain()?; } + thread::spawn(move || loop { if let Err(err) = self.generate_blocks(true) { log::error!(target: "node", "failed block generation: {}", err); @@ -204,72 +193,6 @@ impl TonNodeEngine { } } -impl TonNodeEngine { - fn initialize_blockchain(&self) -> NodeResult<()> { - log::info!(target: "node", "Initialize blockchain"); - let workchain_id = self.workchain.shard_ident.workchain_id() as i8; - self.enqueue_deploy_message(workchain_id, GIVER_ABI1_DEPLOY_MSG, GIVER_BALANCE, 1)?; - self.enqueue_deploy_message(workchain_id, GIVER_ABI2_DEPLOY_MSG, GIVER_BALANCE, 2)?; - self.enqueue_deploy_message(workchain_id, GIVER_ABI2_V3_DEPLOY_MSG, GIVER_BALANCE, 3)?; - self.enqueue_deploy_message(workchain_id, MULTISIG_DEPLOY_MSG, MULTISIG_BALANCE, 4)?; - - Ok(()) - } - - fn enqueue_deploy_message( - &self, - workchain_id: i8, - deploy_msg_boc: &[u8], - initial_balance: u128, - transfer_lt: u64, - ) -> NodeResult<()> { - let deploy_msg = Self::create_contract_deploy_message( - workchain_id, - MINTER_ADDRESS.address(), - deploy_msg_boc, - initial_balance, - transfer_lt, - ); - self.queue_with_retry(deploy_msg)?; - - Ok(()) - } - - fn queue_with_retry(&self, message: Message) -> NodeResult<()> { - let mut message = message; - while let Err(msg) = self.message_queue.queue(message) { - message = msg; - thread::sleep(Duration::from_micros(100)); - } - - Ok(()) - } - - fn create_contract_deploy_message( - workchain_id: i8, - src: AccountId, - msg_boc: &[u8], - value: u128, - lt: u64, - ) -> Message { - let mut msg = Message::construct_from_bytes(msg_boc).expect("Can not parse contract deploy message"); - let mut header = msg.int_header_mut().expect("Contract deploy message is not internal"); - match header.dst { - MsgAddressInt::AddrStd(ref mut addr) => { - addr.workchain_id = workchain_id; - } - _ => panic!("Contract deploy message has invalid destination address"), - } - header.src = MsgAddressIntOrNone::Some(MsgAddressInt::with_standart(None, workchain_id, src).unwrap()); - header.value = CurrencyCollection::from_grams(Grams::new(value).unwrap()); - header.bounce = false; - header.created_lt = lt; - header.created_at = UnixTime32::now(); - - msg - } -} - #[cfg(test)] pub fn get_config_params(json: &str) -> (NodeConfig, Vec) { match NodeConfig::parse(json) { diff --git a/node/src/engine/mod.rs b/node/src/engine/mod.rs index eb7f471..6d83911 100644 --- a/node/src/engine/mod.rs +++ b/node/src/engine/mod.rs @@ -23,13 +23,6 @@ pub mod engine; pub mod shardchain; mod masterchain; -const GIVER_BALANCE: u128 = 5_000_000_000_000_000_000; -const MULTISIG_BALANCE: u128 = 1_000_000_000_000_000; -const GIVER_ABI1_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi1_deploy_msg.boc"); -const GIVER_ABI2_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi2_deploy_msg.boc"); -const GIVER_ABI2_V3_DEPLOY_MSG: &[u8] = include_bytes!("../../data/giver_abi2_v3_deploy_msg.boc"); -const MULTISIG_DEPLOY_MSG: &[u8] = include_bytes!("../../data/safemultisig_deploy_msg.boc"); - pub trait MessagesReceiver: Send { fn run(&mut self, queue: Arc) -> NodeResult<()>; } diff --git a/node/src/engine/shardchain.rs b/node/src/engine/shardchain.rs index 9419c1d..fa95fdf 100644 --- a/node/src/engine/shardchain.rs +++ b/node/src/engine/shardchain.rs @@ -15,7 +15,6 @@ type ArcBlockFinality = Arc, message_queue: Arc, pub(crate) finalizer: ArcBlockFinality, @@ -60,7 +59,6 @@ impl Shardchain { Ok(Self { finality_was_loaded, - shard_ident: shard.clone(), blockchain_config, message_queue, finalizer: block_finality.clone(), From cb4fcdb51337f2dd83684244e8e6c8b1d49c2f8e Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Fri, 17 Feb 2023 13:17:13 +0300 Subject: [PATCH 22/26] Fix GiverV3 replay proitection to check body hash --- contracts/giver_v3/GiverV3.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/giver_v3/GiverV3.sol b/contracts/giver_v3/GiverV3.sol index b882355..c735ab4 100644 --- a/contracts/giver_v3/GiverV3.sol +++ b/contracts/giver_v3/GiverV3.sol @@ -55,14 +55,14 @@ contract GiverV3 is Upgradable { { // owner check require(msg.pubkey() == tvm.pubkey(), 101); + uint256 bodyHash = tvm.hash(body); // load and drop message timestamp (uint64) (, uint32 expireAt) = body.decode(uint64, uint32); require(expireAt > now, 57); - uint256 msgHash = tvm.hash(message); - require(!m_messages.exists(msgHash), 102); + require(!m_messages.exists(bodyHash), 102); tvm.accept(); - m_messages[msgHash] = expireAt; + m_messages[bodyHash] = expireAt; return body; } @@ -70,13 +70,13 @@ contract GiverV3 is Upgradable { /// @notice Allows to delete expired messages from dict. function gc() private inline { uint counter = 0; - for ((uint256 msgHash, uint32 expireAt) : m_messages) { + for ((uint256 bodyHash, uint32 expireAt) : m_messages) { if (counter >= MAX_CLEANUP_MSGS) { break; } counter++; if (expireAt <= now) { - delete m_messages[msgHash]; + delete m_messages[bodyHash]; } } } From a5c0894909f6e1c709d2d5a31e9ef0b6682f86ac Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Fri, 17 Feb 2023 13:25:02 +0300 Subject: [PATCH 23/26] Remove pubkey from GiverV3 --- contracts/giver_v3/GiverV3.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/giver_v3/GiverV3.sol b/contracts/giver_v3/GiverV3.sol index c735ab4..dbc3172 100644 --- a/contracts/giver_v3/GiverV3.sol +++ b/contracts/giver_v3/GiverV3.sol @@ -1,7 +1,6 @@ pragma ever-solidity >= 0.61.2; pragma AbiHeader time; pragma AbiHeader expire; -pragma AbiHeader pubkey; abstract contract Upgradable { /* From 148059a208c6bd2d5215003a9f0a31d0a940ffd6 Mon Sep 17 00:00:00 2001 From: Ekaterina Pantaz <52739957+elasticLove1@users.noreply.github.com> Date: Fri, 17 Feb 2023 11:36:03 +0100 Subject: [PATCH 24/26] Update GiverV3.tvc --- contracts/giver_v3/GiverV3.abi.json | 2 +- contracts/giver_v3/GiverV3.sol | 2 +- contracts/giver_v3/GiverV3.tvc | Bin 800 -> 780 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/giver_v3/GiverV3.abi.json b/contracts/giver_v3/GiverV3.abi.json index 7681a38..7749f9f 100644 --- a/contracts/giver_v3/GiverV3.abi.json +++ b/contracts/giver_v3/GiverV3.abi.json @@ -1,7 +1,7 @@ { "ABI version": 2, "version": "2.3", - "header": ["pubkey", "time", "expire"], + "header": ["time", "expire"], "functions": [ { "name": "sendTransaction", diff --git a/contracts/giver_v3/GiverV3.sol b/contracts/giver_v3/GiverV3.sol index dbc3172..c1f69e1 100644 --- a/contracts/giver_v3/GiverV3.sol +++ b/contracts/giver_v3/GiverV3.sol @@ -49,7 +49,7 @@ contract GiverV3 is Upgradable { /// @notice Function with predefined name called after signature check. Used to /// implement custom replay protection with parallel access. - function afterSignatureCheck(TvmSlice body, TvmCell message) private inline + function afterSignatureCheck(TvmSlice body, TvmCell) private inline returns (TvmSlice) { // owner check diff --git a/contracts/giver_v3/GiverV3.tvc b/contracts/giver_v3/GiverV3.tvc index 854ad68b712532e5c6b6b25b77d2e4228172769a..96a3c21a3dcc557fb3fe1ed7b87f2c1c30838532 100644 GIT binary patch delta 261 zcmV+g0s8)+28;#^weFm90Rk5R00RJ#3qpSr1_cBF00P|YM9|ks!vXkaA=^CD00E8{ zg9z6cAowWA&d$mC09g1!AoykZ5b~(rBltxiZjvx?-uObg^5A75`2ix+KhqyIF(CLO zyz;pr_)3EZ^bT*KG4jx6_y8gJN+QV1A6bJ3^h5Y+Ujx%00oy$CJP8K_O6^3@*GZA! zAOjK-2a^K_1&BzMkWbH24<0o+)ni(?5r#d42%qHO#j}xT)6IenDIxN;%%GD42*qB z%^cSy6nu z)2>esQWY=TUzRs9RQRF1=hIHbp9~5=yqej+@Z~Qw{B$Ah2Z*bD; Date: Fri, 17 Feb 2023 11:40:55 +0100 Subject: [PATCH 25/26] Update docs --- contracts/README.md | 2 +- contracts/giver_v3/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/README.md b/contracts/README.md index 469f080..6f88f7d 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -2,7 +2,7 @@ |Giver type | Address | Comment | --------------- | -------------------------------------------------------------------|------ -| [GiverV3](giver_v3) | 0:cbd3ef42dcc261b9369fdb15fb836b460d4806c5b255e31541c46d6676a2f13d | Recommented Giver version +| [GiverV3](giver_v3) | 0:96137b99dcd65afce5a54a48dac83c0fd276432abbe3ba7f1bfb0fb795e69025 | Recommented Giver version | [SafeMultisig](safe_multisig) | 0:d5f5cfc4b52d2eb1bd9d3a8e51707872c7ce0c174facddd0e06ae5ffd17d2fcd | Safe Multisig as Giver. | [GiverV2](giver_v2) | 0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415 | Deprecated. Recommended to use GiverV3 | GiverV1 | 0:841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94 | Deprecated. Recommended to use GiverV3 diff --git a/contracts/giver_v3/README.md b/contracts/giver_v3/README.md index 122adda..fdab8c1 100644 --- a/contracts/giver_v3/README.md +++ b/contracts/giver_v3/README.md @@ -2,7 +2,7 @@ This directory contains Giver v3 contract. This giver is recommended to use with solc version above 0.61.2 to deploy it on devnet or mainnet. -In Evernode SE this giver is predeployed at `0:cbd3ef42dcc261b9369fdb15fb836b460d4806c5b255e31541c46d6676a2f13d` address +In Evernode SE this giver is predeployed at `0:96137b99dcd65afce5a54a48dac83c0fd276432abbe3ba7f1bfb0fb795e69025` address and its initial balance is about 5 billion tokens. ## Keys: @@ -38,7 +38,7 @@ npx everdev signer default devnet_giver_keys This contract is compiled with `0.66.0 ` Solidity and `0.19.3`Linker version. To check that the code hash of the compiled version from repository is equal to your freshly compiled version, run this command and check that the *Code Hash* is -`5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989`. +`57a1e5e4304f4db2beb23117e4d85df9cb5caec127531350e73219a8b8dc8afd`. ```shell npx everdev sol set --compiler 0.66.0 --linker 0.19.3 @@ -51,7 +51,7 @@ Configuration Signer: devnet_giver_keys (public 7fbbd813ac8358ed2d8598de156eb62bdddf5191d6ce4a0f307d4eac8d4c8e16) Address: 0:dd39b607834a23f7091d4d6d8982c6269c1d71f1b512757cf4d298325a550b6a (calculated from TVC and signer public) -Code Hash: 5534bff04d2d0a14bb2257ec23027947c722159486ceff9e408d6a4d796a0989 (from TVC file) +Code Hash: 57a1e5e4304f4db2beb23117e4d85df9cb5caec127531350e73219a8b8dc8afd (from TVC file) ``` ### Get your Giver address and top it up From 55e51f65643e70939e371a27481e5e31e2009b98 Mon Sep 17 00:00:00 2001 From: Alexey Vavilin Date: Fri, 17 Feb 2023 15:07:43 +0300 Subject: [PATCH 26/26] Update zerostate --- .../WC0/shard_8000000000000000/zerostate | Bin 8974 -> 9081 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docker/ton-node/workchains/WC0/shard_8000000000000000/zerostate b/docker/ton-node/workchains/WC0/shard_8000000000000000/zerostate index b9ecb1f3495cfd2b8890dd34366e61ca5262fd56..ee3a4273ff5e95a92f4ce815609957059005e373 100644 GIT binary patch delta 1830 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 UQz!tb$U