Move VM 是一个栈式虚拟机
相关代码:sui/external-crates/move at main · MystenLabs/sui (github.com)
解释器:sui/external-crates/move/crates/move-vm-runtime/src/interpreter.rs · MystenLabs/sui (github.com)
合约在被部署时,bytecode就会被多个verifier验证[1],如类型匹配之类的检查就是在此时进行,程序被部署后,就可以省去运行时类型检查,只需要检查传入合约的参数是否符合类型要求
sui的官方反汇编器位于:sui/external-crates/move/crates/move-disassembler at main · MystenLabs/sui (github.com),可用于反汇编
下方是一个例子:
public entry fun solve(
status: &mut SolveStatus,
fake_coin: FakeCoin,
real_coin: Coin<ZCOIN>,
ctx: &mut TxContext
) {
let mark_: u64 = 0x1111111111111111;
let mut v: vector<Coin<ZCOIN>> = vector[real_coin];
let c: Coin<ZCOIN> = vector::pop_back(&mut v);
vector::destroy_empty(v);
zcoin::solve(status, c, ctx);
let sender = sender(ctx);
let mark_: u64 = 0x2222222222222222;
transfer::public_transfer(fake_coin, sender);
}
entry public solve(Arg0: &mut SolveStatus, Arg1: FakeCoin, Arg2: Coin<ZCOIN>, Arg3: &mut TxContext) {
// arg0/1/2 is stored as local var (index 0-2)
B0:
0: LdU64(1229782938247303441) // push imm into stack
1: Pop
2: MoveLoc[2](Arg2: Coin<ZCOIN>) // push local var (index: 2) into stack
3: VecPack(10, 1) // create vector (10: SignatureIndex (type info), 1: initial object cnt, will pop from stack) and push into stack
4: StLoc[6](loc2: vector<Coin<ZCOIN>>) // pop object from stack and store as local var (index: 6)
5: MutBorrowLoc[6](loc2: vector<Coin<ZCOIN>>) // mut borrow local var and push into stack
6: VecPopBack(10) // pop back from vec (10: SignatureIndex)
7: StLoc[4](loc0: Coin<ZCOIN>)
8: MoveLoc[6](loc2: vector<Coin<ZCOIN>>)
9: VecUnpack(10, 0) // unpack/destroy vector, and pop all items in it (10: SignatureIndex, 0: item cnt)
10: MoveLoc[0](Arg0: &mut SolveStatus)
11: MoveLoc[4](loc0: Coin<ZCOIN>)
12: CopyLoc[3](Arg3: &mut TxContext) // copy local var and push into stack
13: Call zcoin::solve(&mut SolveStatus, Coin<ZCOIN>, &mut TxContext) // normal Call, args will be fetch from stack, operand `FunctionHandleIndex` not print by disassembler
14: MoveLoc[3](Arg3: &mut TxContext)
15: FreezeRef
16: Call tx_context::sender(&TxContext): address
17: StLoc[5](loc1: address)
18: LdU64(2459565876494606882)
19: Pop
20: MoveLoc[1](Arg1: FakeCoin)
21: MoveLoc[5](loc1: address)
22: Call transfer::public_transfer<FakeCoin>(FakeCoin, address) // actually CallGeneric, operand `FunctionInstantiationIndex` not print by disassembler
23: Ret
}
大部分小括号中的内容都是反汇编器进行的类型推导,并不真正存在于bytecode中 (Vec相关的指令除外,那些小括号中的是真的operand…)
Bytecode序列化源码:sui/external-crates/move/crates/move-binary-format/src/serializer.rs · MystenLabs/sui (github.com)
Bytecode编码 建议不要看代码,直接对照源码和Bytecode基本就能看懂,实在不行在像分析的指令前放上一句标识语句(例如上面的_mark,有巨大imm,很容易找到)
部署bytecode参考:部署Bytecode
参考: