diff --git a/build/StarcoinFramework/BuildInfo.yaml b/build/StarcoinFramework/BuildInfo.yaml index ae8f3019..a927d929 100644 --- a/build/StarcoinFramework/BuildInfo.yaml +++ b/build/StarcoinFramework/BuildInfo.yaml @@ -33,6 +33,9 @@ compiled_package_info: ? address: "0x00000000000000000000000000000001" name: ChainId : StarcoinFramework + ? address: "0x00000000000000000000000000000001" + name: CheckpointScript + : StarcoinFramework ? address: "0x00000000000000000000000000000001" name: Collection : StarcoinFramework @@ -261,7 +264,7 @@ compiled_package_info: ? address: "0x00000000000000000000000000000001" name: YieldFarmingV2 : StarcoinFramework - source_digest: 3DB38FA53B8165D50EFE27CA96B9F5C6B7B338D7519835094216173A9B06D40B + source_digest: 9D5BEAD2A40807817B23BF8C474DA0D8ADC2A14B229B1CF06B74F8726614B3F9 build_flags: dev_mode: false test_mode: false diff --git a/build/StarcoinFramework/abis/Block/checkpoint.abi b/build/StarcoinFramework/abis/Block/checkpoint.abi new file mode 100644 index 00000000..97e9e5be Binary files /dev/null and b/build/StarcoinFramework/abis/Block/checkpoint.abi differ diff --git a/build/StarcoinFramework/abis/Block/update_state_root.abi b/build/StarcoinFramework/abis/Block/update_state_root.abi new file mode 100644 index 00000000..c4c2bded Binary files /dev/null and b/build/StarcoinFramework/abis/Block/update_state_root.abi differ diff --git a/build/StarcoinFramework/abis/StdlibUpgradeScripts/upgrade_from_v11_to_v12.abi b/build/StarcoinFramework/abis/StdlibUpgradeScripts/upgrade_from_v11_to_v12.abi new file mode 100644 index 00000000..4e6f60b3 Binary files /dev/null and b/build/StarcoinFramework/abis/StdlibUpgradeScripts/upgrade_from_v11_to_v12.abi differ diff --git a/build/StarcoinFramework/bytecode_modules/Block.mv b/build/StarcoinFramework/bytecode_modules/Block.mv index c6049e5e..d5445c18 100644 Binary files a/build/StarcoinFramework/bytecode_modules/Block.mv and b/build/StarcoinFramework/bytecode_modules/Block.mv differ diff --git a/build/StarcoinFramework/bytecode_modules/CheckpointScript.mv b/build/StarcoinFramework/bytecode_modules/CheckpointScript.mv new file mode 100644 index 00000000..1c29b197 Binary files /dev/null and b/build/StarcoinFramework/bytecode_modules/CheckpointScript.mv differ diff --git a/build/StarcoinFramework/bytecode_modules/Genesis.mv b/build/StarcoinFramework/bytecode_modules/Genesis.mv index ac1c22e9..369bd822 100644 Binary files a/build/StarcoinFramework/bytecode_modules/Genesis.mv and b/build/StarcoinFramework/bytecode_modules/Genesis.mv differ diff --git a/build/StarcoinFramework/bytecode_modules/StdlibUpgradeScripts.mv b/build/StarcoinFramework/bytecode_modules/StdlibUpgradeScripts.mv index 55b53b9d..d5783288 100644 Binary files a/build/StarcoinFramework/bytecode_modules/StdlibUpgradeScripts.mv and b/build/StarcoinFramework/bytecode_modules/StdlibUpgradeScripts.mv differ diff --git a/build/StarcoinFramework/docs/Block.md b/build/StarcoinFramework/docs/Block.md index 7368a1bc..31041c23 100644 --- a/build/StarcoinFramework/docs/Block.md +++ b/build/StarcoinFramework/docs/Block.md @@ -1,150 +1,26 @@ - + -# Module `0x1::Block` +# Module `0x1::CheckpointScript` -Block module provide metadata for generated blocks. -- [Resource `BlockMetadata`](#0x1_Block_BlockMetadata) -- [Struct `NewBlockEvent`](#0x1_Block_NewBlockEvent) -- [Constants](#@Constants_0) -- [Function `initialize`](#0x1_Block_initialize) -- [Function `get_current_block_number`](#0x1_Block_get_current_block_number) -- [Function `get_parent_hash`](#0x1_Block_get_parent_hash) -- [Function `get_current_author`](#0x1_Block_get_current_author) -- [Function `process_block_metadata`](#0x1_Block_process_block_metadata) -- [Module Specification](#@Module_Specification_1) +- [Function `checkpoint`](#0x1_CheckpointScript_checkpoint) +- [Function `update_state_root`](#0x1_CheckpointScript_update_state_root) -
use 0x1::CoreAddresses;
-use 0x1::Errors;
-use 0x1::Event;
-use 0x1::Timestamp;
+
use 0x1::Block;
 
- + -## Resource `BlockMetadata` +## Function `checkpoint` -Block metadata struct. -
struct BlockMetadata has key
-
- - - -
-Fields - - -
-
-number: u64 -
-
- number of the current block -
-
-parent_hash: vector<u8> -
-
- Hash of the parent block. -
-
-author: address -
-
- Author of the current block. -
-
-uncles: u64 -
-
- number of uncles. -
-
-new_block_events: Event::EventHandle<Block::NewBlockEvent> -
-
- Handle of events when new blocks are emitted -
-
- - -
- - - -## Struct `NewBlockEvent` - -Events emitted when new block generated. - - -
struct NewBlockEvent has drop, store
-
- - - -
-Fields - - -
-
-number: u64 -
-
- -
-
-author: address -
-
- -
-
-timestamp: u64 -
-
- -
-
-uncles: u64 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EBLOCK_NUMBER_MISMATCH: u64 = 17;
-
- - - - - -## Function `initialize` - -This can only be invoked by the GENESIS_ACCOUNT at genesis - - -
public fun initialize(account: &signer, parent_hash: vector<u8>)
+
public(script) fun checkpoint(_account: signer)
 
@@ -153,19 +29,8 @@ This can only be invoked by the GENESIS_ACCOUNT at genesis Implementation -
public fun initialize(account: &signer, parent_hash: vector<u8>) {
-    Timestamp::assert_genesis();
-    CoreAddresses::assert_genesis_address(account);
-
-    move_to<BlockMetadata>(
-        account,
-        BlockMetadata {
-            number: 0,
-            parent_hash: parent_hash,
-            author: CoreAddresses::GENESIS_ADDRESS(),
-            uncles: 0,
-            new_block_events: Event::new_event_handle<Self::NewBlockEvent>(account),
-        });
+
public (script) fun checkpoint(_account: signer){
+    Block::checkpoint();
 }
 
@@ -178,23 +43,20 @@ This can only be invoked by the GENESIS_ACCOUNT at genesis -
aborts_if !Timestamp::is_genesis();
-aborts_if Signer::address_of(account) != CoreAddresses::GENESIS_ADDRESS();
-aborts_if exists<BlockMetadata>(Signer::address_of(account));
+
pragma verify = false;
 
- + -## Function `get_current_block_number` +## Function `update_state_root` -Get the current block number -
public fun get_current_block_number(): u64
+
public(script) fun update_state_root(_account: signer, header: vector<u8>)
 
@@ -203,8 +65,8 @@ Get the current block number Implementation -
public fun get_current_block_number(): u64 acquires BlockMetadata {
-  borrow_global<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS()).number
+
public (script) fun update_state_root(_account: signer , header: vector<u8>){
+    Block::update_state_root(header);
 }
 
@@ -217,160 +79,9 @@ Get the current block number -
aborts_if !exists<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
+
pragma verify = false;
 
- - - -## Function `get_parent_hash` - -Get the hash of the parent block. - - -
public fun get_parent_hash(): vector<u8>
-
- - - -
-Implementation - - -
public fun get_parent_hash(): vector<u8> acquires BlockMetadata {
-  *&borrow_global<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS()).parent_hash
-}
-
- - - -
- -
-Specification - - - -
aborts_if !exists<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
-
- - - -
- - - -## Function `get_current_author` - -Gets the address of the author of the current block - - -
public fun get_current_author(): address
-
- - - -
-Implementation - - -
public fun get_current_author(): address acquires BlockMetadata {
-  borrow_global<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS()).author
-}
-
- - - -
- -
-Specification - - - -
aborts_if !exists<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
-
- - - -
- - - -## Function `process_block_metadata` - -Call at block prologue - - -
public fun process_block_metadata(account: &signer, parent_hash: vector<u8>, author: address, timestamp: u64, uncles: u64, number: u64)
-
- - - -
-Implementation - - -
public fun process_block_metadata(account: &signer, parent_hash: vector<u8>,author: address, timestamp: u64, uncles:u64, number:u64) acquires BlockMetadata{
-    CoreAddresses::assert_genesis_address(account);
-
-    let block_metadata_ref = borrow_global_mut<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
-    assert!(number == (block_metadata_ref.number + 1), Errors::invalid_argument(EBLOCK_NUMBER_MISMATCH));
-    block_metadata_ref.number = number;
-    block_metadata_ref.author= author;
-    block_metadata_ref.parent_hash = parent_hash;
-    block_metadata_ref.uncles = uncles;
-
-    Event::emit_event<NewBlockEvent>(
-      &mut block_metadata_ref.new_block_events,
-      NewBlockEvent {
-          number: number,
-          author: author,
-          timestamp: timestamp,
-          uncles: uncles,
-      }
-    );
-}
-
- - - -
- -
-Specification - - - -
aborts_if Signer::address_of(account) != CoreAddresses::GENESIS_ADDRESS();
-aborts_if !exists<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
-aborts_if number != global<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS()).number + 1;
-
- - - - - - - -
schema AbortsIfBlockMetadataNotExist {
-    aborts_if !exists<BlockMetadata>(CoreAddresses::GENESIS_ADDRESS());
-}
-
- - - -
- - - -## Module Specification - - - -
pragma verify;
-pragma aborts_if_is_strict = true;
-
diff --git a/build/StarcoinFramework/docs/Genesis.md b/build/StarcoinFramework/docs/Genesis.md index 9a994b7a..8f7288a0 100644 --- a/build/StarcoinFramework/docs/Genesis.md +++ b/build/StarcoinFramework/docs/Genesis.md @@ -508,6 +508,12 @@ The module for init Genesis GenesisNFT::initialize(&genesis_account, merkle_root, 1639u64, image); }; StdlibUpgradeScripts::do_upgrade_from_v6_to_v7_with_language_version(&genesis_account, 4); + + //v11 -> v12 + { + + }; + StdlibUpgradeScripts::do_upgrade_from_v11_to_v12(&genesis_account); //Start time, Timestamp::is_genesis() will return false. this call should at the end of genesis init. Timestamp::set_time_has_started(&genesis_account); Account::release_genesis_signer(genesis_account); diff --git a/build/StarcoinFramework/docs/README.md b/build/StarcoinFramework/docs/README.md index d15b13b8..e4b52280 100644 --- a/build/StarcoinFramework/docs/README.md +++ b/build/StarcoinFramework/docs/README.md @@ -21,6 +21,7 @@ This is the root document for the Move StarcoinFramework module documentation. T - [`0x1::Block`](Block.md#0x1_Block) - [`0x1::BlockReward`](BlockReward.md#0x1_BlockReward) - [`0x1::ChainId`](ChainId.md#0x1_ChainId) +- [`0x1::CheckpointScript`](Block.md#0x1_CheckpointScript) - [`0x1::Collection`](Collection.md#0x1_Collection) - [`0x1::Collection2`](Collection2.md#0x1_Collection2) - [`0x1::Compare`](Compare.md#0x1_Compare) diff --git a/build/StarcoinFramework/docs/StdlibUpgradeScripts.md b/build/StarcoinFramework/docs/StdlibUpgradeScripts.md index 6bf98043..158da55a 100644 --- a/build/StarcoinFramework/docs/StdlibUpgradeScripts.md +++ b/build/StarcoinFramework/docs/StdlibUpgradeScripts.md @@ -15,10 +15,13 @@ The module for StdlibUpgrade init scripts - [Function `do_upgrade_from_v6_to_v7_with_language_version`](#0x1_StdlibUpgradeScripts_do_upgrade_from_v6_to_v7_with_language_version) - [Function `upgrade_from_v7_to_v8`](#0x1_StdlibUpgradeScripts_upgrade_from_v7_to_v8) - [Function `do_upgrade_from_v7_to_v8`](#0x1_StdlibUpgradeScripts_do_upgrade_from_v7_to_v8) +- [Function `upgrade_from_v11_to_v12`](#0x1_StdlibUpgradeScripts_upgrade_from_v11_to_v12) +- [Function `do_upgrade_from_v11_to_v12`](#0x1_StdlibUpgradeScripts_do_upgrade_from_v11_to_v12) - [Module Specification](#@Module_Specification_0)
use 0x1::Account;
+use 0x1::Block;
 use 0x1::Collection;
 use 0x1::Config;
 use 0x1::CoreAddresses;
@@ -293,6 +296,56 @@ deprecated, use do_upgrade_from_v6_to_v7_with_language_version.
 
 
 
+
+
+
+
+## Function `upgrade_from_v11_to_v12`
+
+
+
+
public(script) fun upgrade_from_v11_to_v12(sender: signer)
+
+ + + +
+Implementation + + +
public(script) fun upgrade_from_v11_to_v12(sender: signer) {
+    do_upgrade_from_v11_to_v12(&sender);
+}
+
+ + + +
+ + + +## Function `do_upgrade_from_v11_to_v12` + + + +
public fun do_upgrade_from_v11_to_v12(sender: &signer)
+
+ + + +
+Implementation + + +
public fun do_upgrade_from_v11_to_v12(sender: &signer) {
+    {
+        Block::checkpoints_init(sender);
+    };
+}
+
+ + +
diff --git a/build/StarcoinFramework/source_maps/Block.mvsm b/build/StarcoinFramework/source_maps/Block.mvsm index eada550c..6d47b606 100644 Binary files a/build/StarcoinFramework/source_maps/Block.mvsm and b/build/StarcoinFramework/source_maps/Block.mvsm differ diff --git a/build/StarcoinFramework/source_maps/CheckpointScript.mvsm b/build/StarcoinFramework/source_maps/CheckpointScript.mvsm new file mode 100644 index 00000000..70d0000d Binary files /dev/null and b/build/StarcoinFramework/source_maps/CheckpointScript.mvsm differ diff --git a/build/StarcoinFramework/source_maps/Genesis.mvsm b/build/StarcoinFramework/source_maps/Genesis.mvsm index f8f0f361..a7b27607 100644 Binary files a/build/StarcoinFramework/source_maps/Genesis.mvsm and b/build/StarcoinFramework/source_maps/Genesis.mvsm differ diff --git a/build/StarcoinFramework/source_maps/StdlibUpgradeScripts.mvsm b/build/StarcoinFramework/source_maps/StdlibUpgradeScripts.mvsm index 99d1ab52..cdb9246a 100644 Binary files a/build/StarcoinFramework/source_maps/StdlibUpgradeScripts.mvsm and b/build/StarcoinFramework/source_maps/StdlibUpgradeScripts.mvsm differ diff --git a/integration-tests/block/block_checkpoints.exp b/integration-tests/block/block_checkpoints.exp new file mode 100644 index 00000000..88a46aa8 --- /dev/null +++ b/integration-tests/block/block_checkpoints.exp @@ -0,0 +1,87 @@ +processed 16 tasks + +task 3 'run'. lines 7-17: +{ + "gas_used": 16339, + "status": { + "Keep": "Executed" + } +} + +task 5 'run'. lines 22-30: +{ + "gas_used": 450121, + "status": { + "Keep": "Executed" + } +} + +task 6 'run'. lines 32-40: +{ + "gas_used": 20027, + "status": { + "Keep": { + "MoveAbort": [ + { + "Module": { + "address": "0x00000000000000000000000000000001", + "name": "Block" + } + }, + 4609 + ] + } + } +} + +task 7 'run'. lines 42-50: +{ + "gas_used": 87834, + "status": { + "Keep": "Executed" + } +} + +task 13 'run'. lines 64-72: +{ + "gas_used": 94920, + "status": { + "Keep": "Executed" + } +} + +task 14 'run'. lines 74-83: +{ + "gas_used": 553900, + "status": { + "Keep": { + "MoveAbort": [ + { + "Module": { + "address": "0x00000000000000000000000000000001", + "name": "Block" + } + }, + 4609 + ] + } + } +} + +task 15 'run'. lines 86-97: +{ + "gas_used": 95673, + "status": { + "Keep": { + "MoveAbort": [ + { + "Module": { + "address": "0x00000000000000000000000000000001", + "name": "Block" + } + }, + 4609 + ] + } + } +} diff --git a/integration-tests/block/block_checkpoints.move b/integration-tests/block/block_checkpoints.move new file mode 100644 index 00000000..7f0ddf8f --- /dev/null +++ b/integration-tests/block/block_checkpoints.move @@ -0,0 +1,97 @@ +//# init -n dev + +//# faucet --addr alice + +//# faucet --addr Genesis + +//# run --signers Genesis +script { + use StarcoinFramework::Block; + use StarcoinFramework::Debug; + + fun get_parent_hash(_account: signer) { + let hash = Block::get_parent_hash(); + Debug::print>(&hash); + } +} +// check: EXECUTED + + +//# block --author 0x1 --timestamp 86400000 + +//# run --signers Genesis +script { + use StarcoinFramework::Block; + + fun checkpoints_init(account: signer) { + Block::checkpoints_init(&account); + } +} +// check: EXECUTED + +//# run --signers Genesis +script { + use StarcoinFramework::Block; + + fun checkpoints_init(_account: signer) { + Block::latest_state_root(); + } +} +// check: MoveAbort 4609 + +//# run --signers Genesis +script { + use StarcoinFramework::Block; + + fun checkpoint(_account: signer) { + Block::checkpoint(); + } +} +// check: EXECUTED + + + +//# block --author 0x1 --timestamp 96400000 + +//# block --author 0x1 --timestamp 96500000 + +//# block --author 0x1 --timestamp 96600000 + +//# block --author 0x1 --timestamp 96700000 + +//# block --author 0x1 --timestamp 96800000 + +//# run --signers alice +script { + use StarcoinFramework::Block; + + fun checkpoint(_account: signer) { + Block::checkpoint(); + } +} +// check: EXECUTED + +//# run --signers alice +script { + use StarcoinFramework::Block; + + fun update_state_root(_account: signer) { + let header = x"20b82a2c11f2df62bf87c2933d0281e5fe47ea94d5f0049eec1485b682df29529abf17ac7d79010000000000000000000000000000000000000000000000000001002043609d52fdf8e4a253c62dfe127d33c77e1fb4afdefb306d46ec42e21b9103ae20414343554d554c41544f525f504c414345484f4c4445525f48415348000000002061125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d00000000000000000000000000000000000000000000000000000000000000000000000000b1ec37207564db97ee270a6c1f2f73fbf517dc0777a6119b7460b7eae2890d1ce504537b010000000000000000"; + Block::update_state_root(header); + } +} +// check: EXECUTED + + +//# run --signers alice +script { + use StarcoinFramework::Block; + use StarcoinFramework::Debug; + + fun latest_state_root(_account: signer) { + let (number,state_root) = Block::latest_state_root(); + Debug::print (&number); + Debug::print (&state_root); + } +} +// check: EXECUTED \ No newline at end of file diff --git a/sources/Block.move b/sources/Block.move index c1e115c3..500dbedc 100644 --- a/sources/Block.move +++ b/sources/Block.move @@ -6,6 +6,11 @@ module Block { use StarcoinFramework::Signer; use StarcoinFramework::CoreAddresses; use StarcoinFramework::Errors; + use StarcoinFramework::Vector; + use StarcoinFramework::Option; + use StarcoinFramework::Ring; + use StarcoinFramework::BCS; + use StarcoinFramework::Hash; spec module { pragma verify; @@ -34,7 +39,32 @@ module Block { uncles: u64, } - const EBLOCK_NUMBER_MISMATCH: u64 = 17; + // + struct Checkpoint has copy,drop,store{ + //number of the block + block_number: u64, + //Hash of the block + block_hash: vector, + //State root of the block + state_root: Option::Option>, + } + + // + struct Checkpoints has key,store{ + //all checkpoints + checkpoints : Ring::Ring, + index : u64, + last_number : u64, + } + + const EBLOCK_NUMBER_MISMATCH : u64 = 17; + const ERROR_NO_HAVE_CHECKPOINT: u64 = 18; + const ERROR_NOT_BLOCK_HEADER : u64 = 19; + const ERROR_INTERVAL_TOO_LITTLE: u64 = 20; + + const CHECKPOINT_LENGTH : u64 = 60; + const BLOCK_HEADER_LENGTH : u64 = 247; + const BLOCK_INTERVAL_NUMBER : u64 = 5; /// This can only be invoked by the GENESIS_ACCOUNT at genesis public fun initialize(account: &signer, parent_hash: vector) { @@ -116,5 +146,268 @@ module Block { spec schema AbortsIfBlockMetadataNotExist { aborts_if !exists(CoreAddresses::GENESIS_ADDRESS()); } + + public fun checkpoints_init(account: &signer){ + CoreAddresses::assert_genesis_address(account); + + let checkpoints = Ring::create_with_capacity(CHECKPOINT_LENGTH); + move_to( + account, + Checkpoints { + checkpoints : checkpoints, + index : 0, + last_number : 0, + }); + } + + spec checkpoints_init { + pragma verify = false; + } + + public fun checkpoint() acquires BlockMetadata, Checkpoints{ + let parent_block_number = get_current_block_number() - 1; + let parent_block_hash = get_parent_hash(); + + let checkpoints = borrow_global_mut(CoreAddresses::GENESIS_ADDRESS()); + base_checkpoint(checkpoints, parent_block_number, parent_block_hash); + + } + + spec checkpoint { + pragma verify = false; + } + + fun base_checkpoint(checkpoints: &mut Checkpoints, parent_block_number: u64, parent_block_hash:vector){ + assert!(checkpoints.last_number + BLOCK_INTERVAL_NUMBER <= parent_block_number || checkpoints.last_number == 0, Errors::invalid_argument(ERROR_INTERVAL_TOO_LITTLE)); + + checkpoints.index = checkpoints.index + 1; + checkpoints.last_number = parent_block_number; + let op_checkpoint = Ring::push(&mut checkpoints.checkpoints, Checkpoint { + block_number: parent_block_number, + block_hash: parent_block_hash, + state_root: Option::none>(), + } ); + if(Option::is_some(&op_checkpoint)){ + Option::destroy_some(op_checkpoint); + }else{ + Option::destroy_none(op_checkpoint); + } + } + + spec base_checkpoint { + pragma verify = false; + } + + public fun latest_state_root():(u64,vector) acquires Checkpoints{ + let checkpoints = borrow_global(CoreAddresses::GENESIS_ADDRESS()); + base_latest_state_root(checkpoints) + } + + spec latest_state_root { + pragma verify = false; + } + + fun base_latest_state_root(checkpoints: &Checkpoints):(u64,vector){ + let len = Ring::capacity(&checkpoints.checkpoints); + let j = if(checkpoints.index < len - 1){ + checkpoints.index + }else{ + len + }; + let i = checkpoints.index; + while( j > 0){ + let op_checkpoint = Ring::borrow(&checkpoints.checkpoints, i - 1 ); + if( Option::is_some(op_checkpoint) && Option::is_some(&Option::borrow(op_checkpoint).state_root) ) { + let state_root = Option::borrow(&Option::borrow(op_checkpoint).state_root); + return (Option::borrow(op_checkpoint).block_number, *state_root) + }; + j = j - 1; + i = i - 1; + }; + + abort Errors::invalid_state(ERROR_NO_HAVE_CHECKPOINT) + } + + spec base_latest_state_root { + pragma verify = false; + } + + public fun update_state_root(header: vector)acquires Checkpoints { + let checkpoints = borrow_global_mut(CoreAddresses::GENESIS_ADDRESS()); + base_update_state_root(checkpoints, header); + } + + spec update_state_root { + pragma verify = false; + } + + fun base_update_state_root(checkpoints: &mut Checkpoints, header: vector){ + let prefix = Hash::sha3_256(b"STARCOIN::BlockHeader"); + + //parent_hash + let new_offset = BCS::skip_bytes(&header,0); + //timestamp + let new_offset = BCS::skip_u64(&header,new_offset); + //number + let (number,new_offset) = BCS::deserialize_u64(&header,new_offset); + //author + new_offset = BCS::skip_address(&header,new_offset); + //author_auth_key + new_offset = BCS::skip_option_bytes(&header,new_offset); + //txn_accumulator_root + new_offset = BCS::skip_bytes(&header,new_offset); + //block_accumulator_root + new_offset = BCS::skip_bytes(&header,new_offset); + //state_root + let (state_root,_new_offset) = BCS::deserialize_bytes(&header,new_offset); + + Vector::append(&mut prefix,header); + let block_hash = Hash::sha3_256(prefix); + + let len = Ring::capacity(&checkpoints.checkpoints); + let j = if(checkpoints.index < len - 1){ + checkpoints.index + }else{ + len + }; + let i = checkpoints.index; + while( j > 0){ + let op_checkpoint = Ring::borrow_mut(&mut checkpoints.checkpoints, i - 1); + + if( Option::is_some(op_checkpoint) && &Option::borrow(op_checkpoint).block_hash == &block_hash && Option::borrow(op_checkpoint).block_number == number) { + + let op_state_root = &mut Option::borrow_mut(op_checkpoint).state_root; + if(Option::is_some(op_state_root)){ + Option::swap(op_state_root, state_root); + }else{ + Option::fill(op_state_root, state_root); + }; + return + }; + j = j - 1; + i = i - 1; + }; + + abort Errors::invalid_state(ERROR_NO_HAVE_CHECKPOINT) + } + + spec base_update_state_root { + pragma verify = false; + } + + #[test] + fun test_header(){ + // Block header Unit test + // Use Main Genesis BlockHeader in Rust + // BlockHeader { + // id: Some(HashValue(0x80848150abee7e9a3bfe9542a019eb0b8b01f124b63b011f9c338fdb935c417d)), + // parent_hash: HashValue(0xb82a2c11f2df62bf87c2933d0281e5fe47ea94d5f0049eec1485b682df29529a), + // timestamp: 1621311100863, + // number: 0, + // author: 0x00000000000000000000000000000001, + // author_auth_key: None, + // txn_accumulator_root: HashValue(0x43609d52fdf8e4a253c62dfe127d33c77e1fb4afdefb306d46ec42e21b9103ae), + // block_accumulator_root: HashValue(0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000), + // state_root: HashValue(0x61125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d), + // gas_used: 0, + // difficulty: 11660343, + // body_hash: HashValue(0x7564db97ee270a6c1f2f73fbf517dc0777a6119b7460b7eae2890d1ce504537b), + // chain_id: ChainId { id: 1 }, + // nonce: 0, + // extra: BlockHeaderExtra([0, 0, 0, 0]) + // } + // Blockheader BCS : 20b82a2c11f2df62bf87c2933d0281e5fe47ea94d5f0049eec1485b682df29529abf17ac7d79010000000000000000000000000000000000000000000000000001002043609d52fdf8e4a253c62dfe127d33c77e1fb4afdefb306d46ec42e21b9103ae20414343554d554c41544f525f504c414345484f4c4445525f48415348000000002061125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d00000000000000000000000000000000000000000000000000000000000000000000000000b1ec37207564db97ee270a6c1f2f73fbf517dc0777a6119b7460b7eae2890d1ce504537b010000000000000000 + + let prefix = Hash::sha3_256(b"STARCOIN::BlockHeader"); + let header = x"20b82a2c11f2df62bf87c2933d0281e5fe47ea94d5f0049eec1485b682df29529abf17ac7d79010000000000000000000000000000000000000000000000000001002043609d52fdf8e4a253c62dfe127d33c77e1fb4afdefb306d46ec42e21b9103ae20414343554d554c41544f525f504c414345484f4c4445525f48415348000000002061125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d00000000000000000000000000000000000000000000000000000000000000000000000000b1ec37207564db97ee270a6c1f2f73fbf517dc0777a6119b7460b7eae2890d1ce504537b010000000000000000"; + let (_parent_hash,new_offset) = BCS::deserialize_bytes(&header,0); + let (_timestamp,new_offset) = BCS::deserialize_u64(&header,new_offset); + let (number,new_offset) = BCS::deserialize_u64(&header,new_offset); + let (_author,new_offset) = BCS::deserialize_address(&header,new_offset); + let (_author_auth_key,new_offset) = BCS::deserialize_option_bytes(&header,new_offset); + let (_txn_accumulator_root,new_offset) = BCS::deserialize_bytes(&header,new_offset); + let (_block_accumulator_root,new_offset) = BCS::deserialize_bytes(&header,new_offset); + let (state_root,new_offset) = BCS::deserialize_bytes(&header,new_offset); + let (_gas_used,new_offset) = BCS::deserialize_u64(&header,new_offset); + let (_difficultyfirst,new_offset) = BCS::deserialize_u128(&header,new_offset); + let (_difficultylast,new_offset) = BCS::deserialize_u128(&header,new_offset); + let (_body_hash,new_offset) = BCS::deserialize_bytes(&header,new_offset); + let (_chain_id,new_offset) = BCS::deserialize_u8(&header,new_offset); + let (_nonce,new_offset) = BCS::deserialize_u32(&header,new_offset); + let (_extra1,new_offset) = BCS::deserialize_u8(&header,new_offset); + let (_extra2,new_offset) = BCS::deserialize_u8(&header,new_offset); + let (_extra3,new_offset) = BCS::deserialize_u8(&header,new_offset); + let (_extra4,_new_offset) = BCS::deserialize_u8(&header,new_offset); + + Vector::append(&mut prefix,header); + let block_hash = Hash::sha3_256(prefix); + assert!(block_hash == x"80848150abee7e9a3bfe9542a019eb0b8b01f124b63b011f9c338fdb935c417d" ,1001); + assert!(number == 0,1002); + assert!(state_root == x"61125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d",1003); + } + + #[test] + fun test_checkpoint(){ + let checkpoints = Checkpoints { + checkpoints : Ring::create_with_capacity(3), + index : 0, + last_number : 0 + }; + + base_checkpoint(&mut checkpoints, 0, x"80848150abee7e9a3bfe9542a019eb0b8b01f124b63b011f9c338fdb935c417d"); + + let Checkpoints{ + checkpoints: ring, + index : index, + last_number: last_number + } = checkpoints; + assert!( index == 1 && last_number == 0 , 10020); + Ring::destroy(ring); + } + + #[test] + fun test_latest_state_root(){ + let header = x"20b82a2c11f2df62bf87c2933d0281e5fe47ea94d5f0049eec1485b682df29529abf17ac7d79010000000000000000000000000000000000000000000000000001002043609d52fdf8e4a253c62dfe127d33c77e1fb4afdefb306d46ec42e21b9103ae20414343554d554c41544f525f504c414345484f4c4445525f48415348000000002061125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d00000000000000000000000000000000000000000000000000000000000000000000000000b1ec37207564db97ee270a6c1f2f73fbf517dc0777a6119b7460b7eae2890d1ce504537b010000000000000000"; + + let checkpoints = Checkpoints { + checkpoints : Ring::create_with_capacity(3), + index : 0, + last_number : 0 + }; + + base_checkpoint(&mut checkpoints, 0, x"80848150abee7e9a3bfe9542a019eb0b8b01f124b63b011f9c338fdb935c417d"); + + base_update_state_root(&mut checkpoints, copy header); + + let (number , state_root ) = base_latest_state_root(&checkpoints); + let Checkpoints{ + checkpoints: ring, + index : index, + last_number: last_number + } = checkpoints; + assert!( index == 1 && last_number == 0 , 10020); + assert!( number == 0 && state_root == x"61125a3ab755b993d72accfea741f8537104db8e022098154f3a66d5c23e828d" , 10020); + Ring::destroy(ring); + } + +} +module CheckpointScript { + use StarcoinFramework::Block; + + public (script) fun checkpoint(_account: signer){ + Block::checkpoint(); + } + + spec checkpoint { + pragma verify = false; + } + + public (script) fun update_state_root(_account: signer , header: vector){ + Block::update_state_root(header); + } + + spec update_state_root { + pragma verify = false; + } } } \ No newline at end of file diff --git a/sources/Genesis.move b/sources/Genesis.move index faab286c..639db785 100644 --- a/sources/Genesis.move +++ b/sources/Genesis.move @@ -446,6 +446,12 @@ module Genesis { GenesisNFT::initialize(&genesis_account, merkle_root, 1639u64, image); }; StdlibUpgradeScripts::do_upgrade_from_v6_to_v7_with_language_version(&genesis_account, 4); + + //v11 -> v12 + { + + }; + StdlibUpgradeScripts::do_upgrade_from_v11_to_v12(&genesis_account); //Start time, Timestamp::is_genesis() will return false. this call should at the end of genesis init. Timestamp::set_time_has_started(&genesis_account); Account::release_genesis_signer(genesis_account); diff --git a/sources/StdlibUpgradeScripts.move b/sources/StdlibUpgradeScripts.move index d6355d6c..e5f7ea5b 100644 --- a/sources/StdlibUpgradeScripts.move +++ b/sources/StdlibUpgradeScripts.move @@ -19,6 +19,7 @@ module StdlibUpgradeScripts { use StarcoinFramework::Config; use StarcoinFramework::GenesisSignerCapability; use StarcoinFramework::Account; + use StarcoinFramework::Block; spec module { pragma verify = false; @@ -99,5 +100,14 @@ module StdlibUpgradeScripts { Account::destroy_signer_cap(cap); }; } + + public(script) fun upgrade_from_v11_to_v12(sender: signer) { + do_upgrade_from_v11_to_v12(&sender); + } + public fun do_upgrade_from_v11_to_v12(sender: &signer) { + { + Block::checkpoints_init(sender); + }; + } } } \ No newline at end of file