github.com/koko1123/flow-go-1@v0.29.6/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/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  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?