SmartWeave Protocol
This document describes the core concepts behind the SmartWeave smart contracts protocol and is based on the original smartweave.js contract-guide.
Introduction
SmartWeave is a data-centered protocol built on top of the Arweave chain that allows to implement smart contracts. The key difference between SmartWeave and other similar solutions is that the contracts can be evaluated on-demand and "lazily".
Most smart contracts treat data as a side-product that slows down processing. Data is digested, pruned, and pushed out to side chains. Nonetheless, the bloated global state is still the biggest challenge of modern blockchains - as it leads to extreme costs of data storage.
SmartWeave approach, on the other hand, has several advantages:
- It decouples the storage from the computation
- It allows for a flexible lazy-evaluation pattern
- It allows to directly process rich content.
Building SmartWeave on the Arweave allows saving time on the development of the basic infrastructure.
Protocol Specification
The SmartWeave protocol consists of few key concepts:
Contract creation
In order to deploy a new contract on Arweave the SmartWeave client must:
- Create an Arweave transaction with contract source code
Transaction field | Value |
---|---|
data | Contract Source Code specification |
tag['App-Name'] | SmartWeaveContractSource |
tag['App-Version'] | the current version of the SDK, e.g. version from package.json |
tag['Content-Type'] | application/javascript |
- Create an Arweave transaction with contract definition
Transaction field | Value |
---|---|
data (*) | Contract initial state - stringified json object - e.g. JSON.stringify(initialState) |
tag['Init-State'] (*) | Contract initial state - as alternative for setting it in data field |
tag['Init-State-TX'] (*) | Id of the transaction the holds the initial state |
tag['App-Name'] | SmartWeaveContract |
tag['App-Version'] | the current version of the SDK, e.g. version from package.json |
tag['Content-Type'] | application/javascript |
tag['Contract-Src'] | id of the transaction created in previous step, eg: ovqOT6dVD7zYZYmIkq52gmSippk2MGs_TjXs3-D4BLU |
(*) Either one of these options must be chosen for storing the initial state.
Contract source code specification
- A contract source code MAY be written in ES module format.
- A contract source MUST contain function (sync or async) named
handle
. - A contract source MAY use IIFE bundling format.
- The
handle
function MUST accept exactly two arguments:state
andaction
- The
state
argument MUST be the current state of the contract. - The
action
argument MUST containcaller
field (i.e. Arweave wallet address) andinput
field. Theinput
field MUST contain thefunction
field and any additional data required to perform given operation. - The maximum size of the JSON.stringified representation of the
input
field MUST NOT exceed 2048 bytes. - The
handle
function MUST terminate by either:- returning
{ state: newState }
- this will cause the contract state to be updated - returning
{ result: newResult }
- throwing
ContractError
- returning
Contract Interactions
Contract interactions allow to modify the contract state. Each interaction MUST be deployed as a separate Arweave transaction:
Transaction field | Value |
---|---|
tag['App-Name'] | SmartWeaveAction |
tag['App-Version'] | the current version of the SDK, e.g. version from package.json |
tag['Contract'] | Transaction id of the contract |
tag['Input'] | JSON.stringified representation of the input |
Lazy-evaluation of the contract state
In its current form, the SmartWeave protocol assumes that smart contract code is a javascript function, defined as:
contractFunction = (state, action) => state;
This function takes a state and an action as input arguments - and produces a new state as a result.
In functional programming terms it acts as a fold
function - the state of the contract is derived from:
- An initial state
- A contract function
- An ordered list of actions
In order to evaluate contract state, SmartWeave Protocol client:
- Loads all the contract's interaction transactions up to the requested block height.
- Sorts the interaction transactions. The order of the interactions is determined firstly by interaction
transaction block height (i.e. when the transaction was mined in the chain) and secondly by
sha256(transactionId + blockHash)
. The full ordering is[ block_height, sha256(transactionId + blockHash) ]
. - Applies the sorted interactions onto the contract's
handler
function - evaluating contract's state up to the requested block height.