docs: design, examples
This commit is contained in:
parent
8fda433847
commit
cb253cbdf4
|
@ -40,7 +40,7 @@ See `basecoin --help` and `basecoin [cmd] --help` for more details`.
|
|||
1. Make your own [cryptocurrency using Basecoin plugins](/docs/guide/example-counter.md)
|
||||
1. Learn more about [plugin design](/docs/guide/plugin-design.md)
|
||||
1. See some [more example applications](/docs/guide/more-examples.md)
|
||||
1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md)
|
||||
1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md)
|
||||
1. [Deploy testnets](deployment.md) running your basecoin application.
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# Basecoin Design
|
||||
|
||||
Basecoin is designed to be a simple cryptocurrency application with limitted built-in functionality,
|
||||
but with the capacity to be extended by arbitrary plugins.
|
||||
Its basic data structures are inspired by Ethereum, but it is much simpler, as there is no built in virtual machine.
|
||||
|
||||
## Accounts
|
||||
|
||||
The Basecoin state consists entirely of a set of accounts.
|
||||
Each account contains an ED25519 public key,
|
||||
a balance in many different coin denominations,
|
||||
and a strictly increasing sequence number for replay protection.
|
||||
This type of account was directly inspired by accounts in Ethereum,
|
||||
and is unlike Bitcoin's use of Unspent Transaction Outputs (UTXOs).
|
||||
Note Basecoin is a multi-asset cryptocurrency, so each account can have many different kinds of tokens.
|
||||
|
||||
Accounts are serialized and stored in a Merkle tree using the account's address as the key,
|
||||
where the address is the RIPEMD160 hash of the public key.
|
||||
In particular, an account is stored in the Merkle tree under the key `base/a/<address>`,
|
||||
where `<address>` is the 20-byte address of the account.
|
||||
We use an implementation of a Merkle, balanced, binary search tree, also known as an [IAVL tree](https://github.com/tendermint/go-merkle).
|
||||
|
||||
## Transactions
|
||||
|
||||
Basecoin defines a simple transaction type, the `SendTx`, which allows tokens to be sent to other accounts.
|
||||
The `SendTx` takes a list of inputs and a list of outputs,
|
||||
and transfers all the tokens listed in the inputs from their corresponding accounts to the accounts listed in the output.
|
||||
The `SendTx` is structured as follows:
|
||||
|
||||
```
|
||||
type SendTx struct {
|
||||
Gas int64 `json:"gas"`
|
||||
Fee Coin `json:"fee"`
|
||||
Inputs []TxInput `json:"inputs"`
|
||||
Outputs []TxOutput `json:"outputs"`
|
||||
}
|
||||
|
||||
type TxInput struct {
|
||||
Address []byte `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput
|
||||
Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0
|
||||
}
|
||||
|
||||
type TxOutput struct {
|
||||
Address []byte `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
}
|
||||
|
||||
type Coins []Coin
|
||||
|
||||
type Coin struct {
|
||||
Denom string `json:"denom"`
|
||||
Amount int64 `json:"amount"`
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
There are a few things to note. First, the `SendTx` includes a field for `Gas` and `Fee`.
|
||||
The `Gas` limits the total amount of computation that can be done by the transaction,
|
||||
while the `Fee` refers to the total amount paid in fees.
|
||||
This is slightly different from Ethereum's concept of `Gas` and `GasPrice`,
|
||||
where `Fee = Gas x GasPrice`. In Basecoin, the `Gas` and `Fee` are independent,
|
||||
and the `GasPrice` is implicit.
|
||||
|
||||
Second, notice that the `PubKey` only needs to be sent for `Sequence == 0`.
|
||||
After that, it is stored under the account in the Merkle tree and subsequent transactions can exclude it,
|
||||
using only the `Address` to refer to the sender. Ethereum does not require public keys to be sent in transactions
|
||||
as it uses a different elliptic curve scheme which enables the public key to be derrived from the signature itself.
|
||||
|
||||
Finally, note that the use of multiple inputs and multiple outputs allows us to send many different types of tokens between many different accounts
|
||||
at once in an atomic transaction. Thus, the `SendTx` can serve as a basic unit of decentralized exchange.
|
||||
|
||||
## Next steps
|
||||
|
||||
1. Make your own [cryptocurrency using Basecoin plugins](example-counter.md)
|
||||
1. Learn more about [plugin design](plugin-design.md)
|
||||
1. See some [more example applications](more-examples.md)
|
||||
1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md)
|
||||
1. [Deploy testnets](deployment.md) running your basecoin application.
|
|
@ -1,8 +1,17 @@
|
|||
# Plugin Examples
|
||||
|
||||
Now that we've seen how to use Basecoin, talked about the design,
|
||||
and looked at how to implement a simple plugin, let's take a look at some more interesting examples.
|
||||
|
||||
## Mintcoin
|
||||
|
||||
Basecoin does not provide any functionality for adding new tokens to the system.
|
||||
The state is endowed with tokens by a `genesis.json` file which is read once when the system is first started.
|
||||
From there, tokens can be sent to other accounts, even new accounts, but it's impossible to add more tokens to the system.
|
||||
For this, we need a plugin.
|
||||
|
||||
You just read about the amazing [plugin system](https://github.com/tendermint/basecoin/blob/develop/Plugins.md), and want to use it to print your own money. Me too! Let's get started with a simple plugin extension to basecoin, called [mintcoin](./mintcoin/README.md). This plugin lets you register one or more accounts as "central bankers", who can unilaterally issue more currency into the system. It also serves as a simple test-bed to see how one can not just build a plugin, but also take advantage of existing codebases to provide a simple cli to use it.
|
||||
The `mintcoin` plugin lets you register one or more accounts as "central bankers",
|
||||
who can unilaterally issue more currency into the system.
|
||||
|
||||
## Financial Instruments
|
||||
|
||||
|
|
|
@ -1,50 +1,72 @@
|
|||
# Basecoin Plugins
|
||||
|
||||
Basecoin is an extensible cryptocurrency module.
|
||||
Each Basecoin account contains a ED25519 public key,
|
||||
a balance in many different coin denominations,
|
||||
and a strictly increasing sequence number for replay protection (like in Ethereum).
|
||||
Accounts are serialized and stored in a merkle tree using the account's address as the key,
|
||||
where the address is the RIPEMD160 hash of the public key.
|
||||
Basecoin implements a simple cryptocurrency, which is useful in and of itself,
|
||||
but is far more useful if it can support additional functionality.
|
||||
Here we describe how that functionality can be achieved through a plugin system.
|
||||
|
||||
Sending tokens around is done via the `SendTx`, which takes a list of inputs and a list of outputs,
|
||||
and transfers all the tokens listed in the inputs from their corresponding accounts to the accounts listed in the output.
|
||||
The `SendTx` is structured as follows:
|
||||
|
||||
## AppTx
|
||||
|
||||
In addition to the `SendTx`, Basecoin also defines another transaction type, the `AppTx`:
|
||||
|
||||
```
|
||||
type SendTx struct {
|
||||
Gas int64 `json:"gas"` // Gas
|
||||
Fee Coin `json:"fee"` // Fee
|
||||
Inputs []TxInput `json:"inputs"`
|
||||
Outputs []TxOutput `json:"outputs"`
|
||||
type AppTx struct {
|
||||
Gas int64 `json:"gas"`
|
||||
Fee Coin `json:"fee"`
|
||||
Input TxInput `json:"input"`
|
||||
Name string `json:"type"` // Name of the plugin
|
||||
Data []byte `json:"data"` // Data for the plugin to process
|
||||
}
|
||||
|
||||
type TxInput struct {
|
||||
Address []byte `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput
|
||||
Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx
|
||||
PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0
|
||||
}
|
||||
|
||||
type TxOutput struct {
|
||||
Address []byte `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
}
|
||||
|
||||
type Coins []Coin
|
||||
|
||||
type Coin struct {
|
||||
Denom string `json:"denom"`
|
||||
Amount int64 `json:"amount"`
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Note it also includes a field for `Gas` and `Fee`. The `Gas` limits the total amount of computation that can be done by the transaction,
|
||||
while the `Fee` refers to the total amount paid in fees. This is slightly different from Ethereum's concept of `Gas` and `GasPrice`,
|
||||
where `Fee = Gas x GasPrice`. In Basecoin, the `Gas` and `Fee` are independent.
|
||||
The `AppTx` enables Basecoin to be extended with arbitrary additional functionality through the use of plugins.
|
||||
The `Name` field in the `AppTx` refers to the particular plugin which should process the transasaction,
|
||||
and the `Data` field of the `AppTx` is the data to be forwarded to the plugin for processing.
|
||||
|
||||
Note the `AppTx` also has a `Gas` and `Fee`, with the same meaning as for the `SendTx`.
|
||||
It also includes a single `TxInput`, which specifies the sender of the transaction,
|
||||
and some coins that can be forwarded to the plugin as well.
|
||||
|
||||
## Plugins
|
||||
|
||||
A plugin is simply a Go package that implements the `Plugin` interface:
|
||||
|
||||
```
|
||||
type Plugin interface {
|
||||
|
||||
// Name of this plugin, should be short.
|
||||
Name() string
|
||||
|
||||
// Run a transaction from ABCI DeliverTx
|
||||
RunTx(store KVStore, ctx CallContext, txBytes []byte) (res abci.Result)
|
||||
|
||||
// Other ABCI message handlers
|
||||
SetOption(store KVStore, key string, value string) (log string)
|
||||
InitChain(store KVStore, vals []*abci.Validator)
|
||||
BeginBlock(store KVStore, height uint64)
|
||||
EndBlock(store KVStore, height uint64) []*abci.Validator
|
||||
}
|
||||
|
||||
type CallContext struct {
|
||||
CallerAddress []byte // Caller's Address (hash of PubKey)
|
||||
CallerAccount *Account // Caller's Account, w/ fee & TxInputs deducted
|
||||
Coins Coins // The coins that the caller wishes to spend, excluding fees
|
||||
}
|
||||
```
|
||||
|
||||
The workhorse of the plugin is `RunTx`, which is called when an `AppTx` is processed.
|
||||
The `Data` from the `AppTx` is passed in as the `txBytes`,
|
||||
while the `Input` from the `AppTx` is used to populate the `CallContext`.
|
||||
|
||||
Note that `RunTx` also takes a `KVStore` - this is an abstraction for the underlying Merkle tree which stores the account data.
|
||||
By passing this to the plugin, we enable plugins to update accounts in the Basecoin state directly,
|
||||
and also to store arbitrary other information in the state.
|
||||
In this way, the functionality and state of a Basecoin-derrived cryptocurrency can be greatly extended.
|
||||
One could imagine going so far as to implement the Ethereum Virtual Machine as a plugin!
|
||||
|
||||
|
||||
Basecoin also defines another transaction type, the `AppTx`:
|
||||
## Next steps
|
||||
|
||||
1. Examples of [Basecoin plugins](more-examples.md)
|
||||
1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md)
|
||||
1. [Deploy testnets](deployment.md) running your basecoin application.
|
||||
|
|
Loading…
Reference in New Issue