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