github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/README.md (about) 1 # Flow Virtual Machine (FVM) 2 3 The Flow Virtual Machine (FVM) augments the Cadence runtime with the domain-specific 4 functionality required by the Flow protocol. 5 6 ## Usage 7 8 ### Quickstart 9 10 ```go 11 import ( 12 "github.com/onflow/cadence/runtime" 13 "github.com/onflow/flow-go/fvm" 14 "github.com/onflow/flow-go/fvm/storage/state" 15 "github.com/onflow/flow-go/model/flow" 16 ) 17 18 vm := fvm.NewVirtualMachine() 19 20 tx := flow.NewTransactionBody(). 21 SetScript([]byte(`transaction { execute { log("Hello, World!") } }`)) 22 23 ctx := fvm.NewContext() 24 ledger := state.NewMapLedger() 25 26 txIndex := uint32(0) 27 txProc := fvm.Transaction(tx, txIndex) 28 29 executionSnapshot, output, err := vm.Run(ctx, txProc, ledger) 30 if err != nil { 31 panic("fatal error during transaction procedure!") 32 } 33 34 fmt.Println(txProc.Logs[0]) // prints "Hello, World!" 35 ``` 36 37 ### Procedure 38 39 The FVM interacts with the Flow execution state by running atomic procedures against 40 a shared ledger. A `Procedure` is an operation that can be applied to a `Ledger`. 41 42 #### Procedure Types 43 44 ##### Transactions (Read/write) 45 46 A `TransactionProcedure` is an operation that mutates the ledger state. 47 48 A transaction procedure can be created from a `flow.TransactionBody`: 49 50 ```go 51 var tx flow.TransactionBody 52 var txIndex uint32 53 54 i := fvm.Transaction(tx, txIndex) 55 ``` 56 57 A transaction procedure has the following steps: 58 59 1. Verify all transaction signatures against the current ledger state 60 1. Validate and increment the proposal key sequence number 61 1. Deduct transaction fee from the payer account 62 1. Invoke transaction script with provided arguments and authorizers 63 64 ##### Scripts (Read-only) 65 66 A `ScriptProcedure` is an operation that reads from the ledger state. 67 68 ```go 69 foo := fvm.Script([]byte(`fun main(): Int { return 42 }`)) 70 ``` 71 72 A script can have optionally bound arguments: 73 74 ```go 75 script := fvm.Script([]byte(`fun main(x: Int): Int { x * 2 }`)) 76 77 foo := script.WithArguments(argA) 78 bar := script.WithArguments(argB) 79 ``` 80 81 ### Contexts 82 83 The VM runs procedures inside of an execution context that defines the host 84 functionality provided to the Cadence runtime. A `Context` instance is 85 an immutable object, and any changes to a context must be made by spawning 86 a new child context. 87 88 ```go 89 vm := fvm.New(runtime.NewInterpreterRuntime()) 90 91 globalCtx := fvm.NewContext() 92 93 // create separate contexts for different blocks 94 block1Ctx := fvm.NewContextFromParent(globalCtx, fvm.WithBlockHeader(block1)) 95 block2Ctx := fvm.NewContextFromParent(globalCtx, fvm.WithBlockHeader(block2)) 96 97 // contexts can be safely used in parallel 98 go executeBlock(vm, block1Ctx) 99 go executeBlock(vm, block2Ctx) 100 ``` 101 102 #### Context Options 103 104 TODO: document context options 105 106 ## Design 107 108 The structure of the FVM package is intended to promote the following: 109 - **Determinism**: the VM should be consistent and predictable, producing identical results given the 110 same inputs. 111 - **Performance**: the VM should expose functionality that allows the caller to exploit parallelism and pre-computation. 112 - **Flexibility**: the VM should support a variety of use cases including not only execution and verification, but also 113 developer tooling and network emulation. 114 115 ### `Context` 116 117 A `Context` is a reusable component that simply defines the parameters of an execution environment. 118 For example, all transactions within the same block would share a common `Context` configured with the relevant 119 block data. 120 121 Contexts can be arbitrarily nested. A child context inherits the parameters of its parent, but is free to override 122 any parameters that it chooses. 123 124 ### `HostEnvironment` 125 126 A `HostEnvironment` is a short-lived component that is consumed by a procedure. A `HostEnvironment` is the 127 interface through which the VM communicates with the Cadence runtime. The `HostEnvironment` provides information about 128 the current `Context` and also collects logs, events and metrics emitted from the runtime. 129 130 ### Procedure Lifecycle 131 132 The diagram below illustrates the relationship between contexts, host environments and procedures. Multiple procedures 133 can reuse the same context, each of which is supplied with a unique `HostEnvironment` instance. 134 135 ![fvm](./fvm.svg) 136 137 138 ## TODO 139 140 - [ ] Improve error handling 141 - [ ] Create list of all missing test cases 142 - [ ] Implement missing test cases 143 - [ ] Documentation 144 - [ ] Transaction validation (signatures, sequence numbers) 145 - [ ] Fee payments 146 - [ ] Address generation 147 - [ ] Account management 148 - [ ] Bootstrapping 149 - [ ] Ledger usage 150 151 ## Open Questions 152 153 - Currently the caller is responsible for providing the correct `Ledger` instance when running a procedure. When 154 performing atomic operations in batches (i.e blocks or chunks), multiple ledgers are spawned in a hierarchy similar to 155 that of multiple `Context` instances. Does it make sense for the `fvm` package to manage ledgers as well?