Skip to content

Commit

Permalink
support remap module addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
pause125 committed Oct 24, 2023
1 parent 6e87a95 commit 48afeed
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions moveos/moveos-stdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ smallvec = { workspace = true }
hex = { workspace = true }
petgraph = { workspace = true }
parking_lot = { workspace = true }
itertools = { workspace = true }

move-binary-format = { workspace = true }
move-bytecode-utils = { workspace = true }
Expand Down
66 changes: 65 additions & 1 deletion moveos/moveos-stdlib/moveos-stdlib/doc/move_module.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
- [Function `module_name`](#0x2_move_module_module_name)
- [Function `sort_and_verify_modules`](#0x2_move_module_sort_and_verify_modules)
- [Function `check_comatibility`](#0x2_move_module_check_comatibility)
- [Function `remap_module_addresses`](#0x2_move_module_remap_module_addresses)
- [Function `request_init_functions`](#0x2_move_module_request_init_functions)


<pre><code><b>use</b> <a href="">0x1::string</a>;
<pre><code><b>use</b> <a href="">0x1::error</a>;
<b>use</b> <a href="">0x1::string</a>;
</code></pre>


Expand Down Expand Up @@ -62,6 +64,16 @@ Module address is not the same as the signer



<a name="0x2_move_module_ErrorLengthNotMatch"></a>

Vector length not match


<pre><code><b>const</b> <a href="move_module.md#0x2_move_module_ErrorLengthNotMatch">ErrorLengthNotMatch</a>: u64 = 4;
</code></pre>



<a name="0x2_move_module_ErrorModuleIncompatible"></a>

Module incompatible with the old ones.
Expand Down Expand Up @@ -193,6 +205,58 @@ Abort if the new module is not compatible with the old module.



</details>

<a name="0x2_move_module_remap_module_addresses"></a>

## Function `remap_module_addresses`

Remap addresses in module binary where the length of
<code>old_addresses</code> must equal to that of <code>new_addresses</code>.


<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_remap_module_addresses">remap_module_addresses</a>(modules: <a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">move_module::MoveModule</a>&gt;, old_addresses: <a href="">vector</a>&lt;<b>address</b>&gt;, new_addresses: <a href="">vector</a>&lt;<b>address</b>&gt;): <a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">move_module::MoveModule</a>&gt;
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_remap_module_addresses">remap_module_addresses</a>(
modules: <a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a>&gt;,
old_addresses: <a href="">vector</a>&lt;<b>address</b>&gt;,
new_addresses: <a href="">vector</a>&lt;<b>address</b>&gt;,
): <a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a>&gt; {
<b>assert</b>!(
<a href="_length">vector::length</a>(&old_addresses) == <a href="_length">vector::length</a>(&new_addresses),
<a href="_invalid_argument">error::invalid_argument</a>(<a href="move_module.md#0x2_move_module_ErrorLengthNotMatch">ErrorLengthNotMatch</a>)
);
<b>let</b> bytes_vec = <a href="_empty">vector::empty</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;();
<b>let</b> i = 0u64;
<b>let</b> len = <a href="_length">vector::length</a>(&modules);
<b>while</b> (i &lt; len) {
<a href="_push_back">vector::push_back</a>(&<b>mut</b> bytes_vec, <a href="_pop_back">vector::pop_back</a>(&<b>mut</b> modules).byte_codes);
i = i + 1;
};
<b>let</b> remapped_bytes = <a href="move_module.md#0x2_move_module_remap_module_addresses_inner">remap_module_addresses_inner</a>(bytes_vec, old_addresses, new_addresses);
<b>let</b> remapped_modules = <a href="_empty">vector::empty</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a>&gt;();
i = 0u64;
<b>let</b> len = <a href="_length">vector::length</a>(&remapped_bytes);
<b>while</b> (i &lt; len) {
<a href="_push_back">vector::push_back</a>(&<b>mut</b> remapped_modules, <a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a> {
byte_codes: <a href="_pop_back">vector::pop_back</a>(&<b>mut</b> remapped_bytes),
});
i = i + 1;
};
<a href="_destroy_empty">vector::destroy_empty</a>(remapped_bytes);
remapped_modules
}
</code></pre>



</details>

<a name="0x2_move_module_request_init_functions"></a>
Expand Down
13 changes: 13 additions & 0 deletions moveos/moveos-stdlib/moveos-stdlib/sources/account_storage.move
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,17 @@ module moveos_std::account_storage {
} = test;
context::drop_test_context(ctx);
}

#[test(account=@0x42)]
fun test_publish_modules(account: &signer) {
let addr = signer::address_of(account);
let ctx = context::new_test_context(addr);
Self::create_account_storage(&mut ctx, addr);
// The following is the bytes and hex of the compiled module: example/counter/sources/counter.move
// with account 0x42
let module_bytes: vector<u8> = x"a11ceb0b060000000b010006020608030e26043406053a32076c7d08e9014006a902220acb02050cd002560da6030200000101010200030c00020400000005000100000600010000070201000008030400010907080108010a09010108010b0a0b0108040605060606010708010002070801060c0106080101030107080001080002070801050107090003070801060c090002060801050106090007636f756e7465720f6163636f756e745f73746f7261676507636f6e7465787407436f756e74657207436f6e7465787408696e63726561736509696e6372656173655f04696e69740576616c756511676c6f62616c5f626f72726f775f6d75740e676c6f62616c5f6d6f76655f746f0d676c6f62616c5f626f72726f77000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000020520000000000000000000000000000000000000000000000000000000000000004200020108030001040001030b0011010201010000050d0b00070038000c010a01100014060100000000000000160b010f0015020200000001060b000b0106000000000000000012003801020301000001060b000700380210001402000000";
let m: MoveModule = move_module::new(module_bytes);
Self::publish_modules(&mut ctx, account, vector::singleton(m));
context::drop_test_context(ctx);
}
}
84 changes: 81 additions & 3 deletions moveos/moveos-stdlib/moveos-stdlib/sources/move_module.move
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@
/// `move_module` provides some basic functions for handle Move module in Move.
module moveos_std::move_module {
use std::vector;
use std::error;
use std::string::String;

friend moveos_std::account_storage;

/// Module address is not the same as the signer
const ErrorAddressNotMatchWithSigner: u64 = 1;

/// Module verification error
const ErrorModuleVerificationError: u64 = 2;

/// Module incompatible with the old ones.
const ErrorModuleIncompatible: u64 = 3;

/// Vector length not match
const ErrorLengthNotMatch: u64 = 4;

struct MoveModule has store, drop {
byte_codes: vector<u8>,
}
Expand Down Expand Up @@ -54,6 +55,38 @@ module moveos_std::move_module {
check_compatibililty_inner(new_module.byte_codes, old_module.byte_codes);
}

/// Remap addresses in module binary where the length of
/// `old_addresses` must equal to that of `new_addresses`.
public fun remap_module_addresses(
modules: vector<MoveModule>,
old_addresses: vector<address>,
new_addresses: vector<address>,
): vector<MoveModule> {
assert!(
vector::length(&old_addresses) == vector::length(&new_addresses),
error::invalid_argument(ErrorLengthNotMatch)
);
let bytes_vec = vector::empty<vector<u8>>();
let i = 0u64;
let len = vector::length(&modules);
while (i < len) {
vector::push_back(&mut bytes_vec, vector::pop_back(&mut modules).byte_codes);
i = i + 1;
};
let remapped_bytes = remap_module_addresses_inner(bytes_vec, old_addresses, new_addresses);
let remapped_modules = vector::empty<MoveModule>();
i = 0u64;
let len = vector::length(&remapped_bytes);
while (i < len) {
vector::push_back(&mut remapped_modules, MoveModule {
byte_codes: vector::pop_back(&mut remapped_bytes),
});
i = i + 1;
};
vector::destroy_empty(remapped_bytes);
remapped_modules
}

native fun module_name_inner(byte_codes: &vector<u8>): String;

/// Sort modules by dependency order and then verify.
Expand All @@ -66,4 +99,49 @@ module moveos_std::move_module {
native public(friend) fun request_init_functions(module_names: vector<String>, account_address: address);

native fun check_compatibililty_inner(new_bytecodes: vector<u8>, old_bytecodes: vector<u8>);

/// Native function to remap addresses in module binary where the length of
/// `old_addresses` must equal to that of `new_addresses`.
native fun remap_module_addresses_inner(
bytes: vector<vector<u8>>,
old_addresses: vector<address>,
new_addresses: vector<address>,
): vector<vector<u8>>;


#[test_only]
use std::debug;
#[test_only]
use std::signer;
#[test_only]
use moveos_std::context;

#[test(account=@0x42)]
fun test_get_module_name(account: &signer) {
let addr = signer::address_of(account);
let ctx = context::new_test_context(addr);
// The following is the bytes and hex of the compiled module: example/counter/sources/counter.move
// with account 0x42
let module_bytes: vector<u8> = x"a11ceb0b060000000b010006020608030e26043406053a32076c7d08e9014006a902220acb02050cd002560da6030200000101010200030c00020400000005000100000600010000070201000008030400010907080108010a09010108010b0a0b0108040605060606010708010002070801060c0106080101030107080001080002070801050107090003070801060c090002060801050106090007636f756e7465720f6163636f756e745f73746f7261676507636f6e7465787407436f756e74657207436f6e7465787408696e63726561736509696e6372656173655f04696e69740576616c756511676c6f62616c5f626f72726f775f6d75740e676c6f62616c5f6d6f76655f746f0d676c6f62616c5f626f72726f77000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000020520000000000000000000000000000000000000000000000000000000000000004200020108030001040001030b0011010201010000050d0b00070038000c010a01100014060100000000000000160b010f0015020200000001060b000b0106000000000000000012003801020301000001060b000700380210001402000000";
let m: MoveModule = Self::new(module_bytes);
let name = Self::module_name(&m);
debug::print(&name);
context::drop_test_context(ctx);
}

#[test(account=@0x42)]
fun test_verify_modules(account: &signer) {
let addr = signer::address_of(account);
let ctx = context::new_test_context(addr);
// The following is the bytes and hex of the compiled module: example/counter/sources/counter.move
// with account 0x42
let module_bytes: vector<u8> = x"a11ceb0b060000000b010006020608030e26043406053a32076c7d08e9014006a902220acb02050cd002560da6030200000101010200030c00020400000005000100000600010000070201000008030400010907080108010a09010108010b0a0b0108040605060606010708010002070801060c0106080101030107080001080002070801050107090003070801060c090002060801050106090007636f756e7465720f6163636f756e745f73746f7261676507636f6e7465787407436f756e74657207436f6e7465787408696e63726561736509696e6372656173655f04696e69740576616c756511676c6f62616c5f626f72726f775f6d75740e676c6f62616c5f6d6f76655f746f0d676c6f62616c5f626f72726f77000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000020520000000000000000000000000000000000000000000000000000000000000004200020108030001040001030b0011010201010000050d0b00070038000c010a01100014060100000000000000160b010f0015020200000001060b000b0106000000000000000012003801020301000001060b000700380210001402000000";
let m: MoveModule = Self::new(module_bytes);
let modules = vector::singleton(m);
let (module_names, _module_names_with_init_fn) = Self::sort_and_verify_modules(&modules, addr);
debug::print(&module_names);
context::drop_test_context(ctx);
}


}
Loading

0 comments on commit 48afeed

Please sign in to comment.