spacemeshos / svm

SVM - Spacemesh Virtual Machine
https://spacemesh.io
MIT License
85 stars 14 forks source link

Add `calldata` to the `tx_offsets` API of the `svm-codec` #463

Open YaronWittenstein opened 2 years ago

YaronWittenstein commented 2 years ago

Depends on: #457 #461

The calldata transaction is unique since it is contextual. It refers to the input of the function to execute.

If the Runtime is about to execute a verify then the calldata should point to the offsets of the verifydata. If the Spawn ctor is about to execute - the calldata should point to the offsets of the ctordata. If it's "the function" of Call Transaction that is to run - the calldata should point to the offsets of the funcdata.

Seems most elegant to extend the TxPart of #457 to contain a CallData.

#[derive(Debug, PartiaEq, Copy, Clone, Hash)]
enum TxPart {
  // This part is contextual.
  // For `verify` it means the `verifydata`
  // For `spawn ctor` it means the `ctordata`
  // For `call transaction` it means the `funcdata`
  // If we have `authorize` it'll refer to the `authorizedata`
  CallData
}

Usage API

let tx: &[u8] = ...;
let offsets = svm_codec::tx_offsets(tx);
let calldata = offsets.get(&TxPart::Calldata).unwrap();

// Now `calldata` holds to offsets of the input for the function to be running

Now the set_calldata of Runtime should be updated: https://github.com/spacemeshos/svm/blob/6edb73de199fafce0953f82af061ca1090ff911c/crates/runtime/src/runtime/runtime.rs#L784

It probably should also have a different signature, something like:

fn set_calldata(env: &FuncEnv, tx_ptr: WasmPtr<u8>) {
  // `tx_ptr` points to the Wasm Instance Memory 
  // containing the binary Transaction.
  let tx_offset = tx_ptr.offset() as usize;

  let (offset, len) = env.borrow().tx_offsets().get(&TxPart::CallData).unwrap();

  // computing the absolute location in Memory of the `calldata`  
  let offset = tx_offset + offset;

  env.borrow_mut().set_calldata(offset, len);
}

Another option is to manage without this setter function. And compute the calldata lazily when required. That should be feasible since the FuncEnv holds the tx_offsets so as long it will store the tx_ptr we're good. In that case, we can have set_tx helper instead.