README.md

## Forge

Forge is a simple elixir blockchain framework to build new chains easily. Built on top of [tendermint](https://github.com/tendermint/tendermint) and [ex_abci](https://github.com/arcblock/ex_abci), Forge implemented the core part of the state db and exposes interfaces to maintain the states so that developers could build their own blockchain app easily.

In a very high level, a typical blockchain app consists of:

* networking: for secure p2p connectivity and data replication. Handled by Tendermint.
* mempool: for broadcasting tx. Handled by Tendermint.
* consensus: for agreeing on most recent block. Handled by Tendermint.
* storage: account states. Handled by Forge.
* VM: for executing turning-complete contracts. TBD.
* app logic: e.g. permissions. Should be handled by application.
* RPC: for providing functionalities for user to interact with the chain. Partly handled by Forge, the rest shall be handled by application.

Forge provides these functionalities:

* An ethereum compatible wallet system. Meaning your existing account, your private key could be used in Forge-enabled application.
* An ethereum-like state db. Forge stores your application state into leveldb (rocksdb in future). All your application states are maintained in a [merkle patricia tree](https://github.com/ethereum/wiki/wiki/Patricia-Tree)(MPT). Every transaction will lead to the change of MPT, which will generate a new root_hash, and every time a block is committed, the current root_hash will be delivered to tendermint as the app_hash for that block.
* Transaction / Account state definition. The transaction and the account state are defined with protobuf, you can find the definition in [lib/protos/forge.proto](./lib/forge/protos) and rebuild it with `make rebuild-proto`. These data structures are designed to be extensible so you can leverage and extend them in your application.
* Tendermint messaage handling. All the following messages are handled:
    * `info`: you can define your application name and version in config. Otherwise Forge will return a default one. See: [config/config.exs](./config/config.exs).
    * `begin_block`: block context are stored in the gen server state.
    * `check_tx`: after verified transaction signature, application provided callback function `verify` will be called to make sure the tx is valid.
    * `deliver_tx`: besides the function of `check_tx`, the application provided callback function `update_state` will be called to persist the update to the states db after this transaction.
    * `end_block`: do nothing.
    * `commit_block`: update the current block height to the states db. Return the current root_hash to tendermint as app_hash.
* Transaction sign and verification. The cryptography part of the transaction sign / verification are handled by Forge. Developer just need to verify whether the tx is valid against the application state.

## Installation

The package can be installed by adding :forge to your list of dependencies in mix.exs:

```elixir
def deps do
  [
    {:forge, "~> 0.4.0"}
  ]
end
```

the docs can be found at https://hexdocs.pm/forge.

## Usage

### Config

After adding Forge into your dependency, you can put these config to define the db and app info:

```elixir
config :forge, db: "./states.db"

config :forge, :app_info, {"Final Chapter", "0.1.0"}
```

### Supervision Tree

You shall add `ExAbci.Listener` and `Forge.Server` into your application supervision tree.
`Forge.Server` needs a module which implements `Forge.Handler` callback:

```elixir
def start(_type, _args) do
  children = [
    ExAbci.Listener.child_spec(Forge.Server),
    {Forge.Server, YourAwesomeChain.Handler}
  ]

  opts = [strategy: :one_for_one, name: Forge.Supervisor]
  Supervisor.start_link(children, opts)
end
```

### Forge.Handler callback

You need to implement two callback functions provided by `Forge.Handler`:

```elixir
@callback verify(TransactionMessage.t(), Account.t(), AccountState.t()) :: true | false
@callback update_state(String.t(), Any.t(), Account.t(), map()) :: Account.t()
```

Forge will call your `verify` callback upon `check_tx` / `deliver_tx` with the transaction, the MPT, and the sender's account state. Once the transaction satisfied the state, you shall return `true` to Forge.

When a tx is being calculated on `deliver_tx`, Forge will call your `update_state` callback with the transaction, the sender address, custom data inside the transaction, MPT and the current context (e.g. block height, tx hash). Once the transaction is processed, the update MPT reference shall be returned.

### Extending the transaction

The transaction is defined in Forge, like this:

```proto
message TransactionMessage {
  bytes from = 1;
  uint64 nonce = 2;
  bytes public_key = 3;
  bytes signature = 4;
  oneof value {
    TransferMessage transfer = 10;
    google.protobuf.Any any = 50;
  }
}

message TransferMessage {
  bytes to = 1;
  uint64 total = 2;
}
```

Forge can process the most basic transfer transactions without application handle anything. But if application want a much wider behavior in the chain, e.g. account holder can publish a post into the chain, then you should define your own transaction message inside the Forge transaction. For example, you can define a CreatePostMessage like this:

```proto
syntax = "proto3";
package Example;
message CreatePostMessage {
  string title = 1;
  string content = 2;
}
```

after building this with [grpc-elixir](https://github.com/tony612/grpc-elixir), you can encode and sign your transaction with [`Forge.CustomTransaction.create`](./lib/forge/tx.ex):

```elixir
type_url = "example.com/CreatePostMessage";
type_mod = Example.CreatePostMessage; # this module is generated by elixir grpc tool.
attrs = %{title: "hello", content: "world"}
CustomTransaction.create(sender_address, nonce, type_url, type_mod, attrs, public_key, private_key)
```

### Extending the account state

The basic account state is defined in Forge, like this:

```proto
message AccountState {
  uint64 balance = 1;
  uint64 nonce = 2;
  uint64 num_txs = 3;
  bytes address = 4;
  bytes owner = 5;

  // 5-9 reserve for future

  bytes genesis_tx = 10;
  bytes renaissance_tx = 11;
  google.protobuf.Timestamp genesis_time = 12;
  google.protobuf.Timestamp renaissance_time = 13;

  // 14-49 reserve for future

  google.protobuf.Any data = 50;
}
```

`nonce`, `num_txs`, `address`, `genesis_tx`, `renaissance_tx`, `tenesis_time` and `renaissance_time` will be updated by Forge, you don't need to worried about them. `balance` will be maintained by the handling of `TransferMessage`, but your custom transaction message can manipulate that as well. You could extend `data` in your way, for example, you want to keep a list of posts for the user, and each post has its own account:

```proto
message UserAccountState {
  string nickname = 1;
  repeated string posts = 2;
}

message PostAccountState {
  bytes title = 1;
  bytes content = 2;
}
```

After compiling the proto definition, you can encode them and use `Account.renaissance` to update it.