2017-02-04 21:43:55 -08:00
|
|
|
# Basecoin Design
|
|
|
|
|
2017-02-06 11:57:35 -08:00
|
|
|
Basecoin is designed to be a simple cryptocurrency application with limited built-in functionality,
|
2017-02-04 21:43:55 -08:00
|
|
|
but with the capacity to be extended by arbitrary plugins.
|
2017-02-06 11:57:35 -08:00
|
|
|
Its basic data structures are inspired by Ethereum, but it is much simpler, as there is no built-in virtual machine.
|
2017-02-04 21:43:55 -08:00
|
|
|
|
|
|
|
## 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.
|
|
|
|
|
2017-02-12 22:57:21 -08:00
|
|
|
```golang
|
2017-02-07 13:28:41 -08:00
|
|
|
type Account struct {
|
|
|
|
PubKey crypto.PubKey `json:"pub_key"` // May be nil, if not known.
|
|
|
|
Sequence int `json:"sequence"`
|
|
|
|
Balance Coins `json:"coins"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Coins []Coin
|
|
|
|
|
|
|
|
type Coin struct {
|
|
|
|
Denom string `json:"denom"`
|
|
|
|
Amount int64 `json:"amount"`
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2017-02-04 21:43:55 -08:00
|
|
|
Accounts are serialized and stored in a Merkle tree using the account's address as the key,
|
2017-02-08 04:18:26 -08:00
|
|
|
In particular, an account is stored in the Merkle tree under the key `base/a/<address>`,
|
2017-02-07 13:28:41 -08:00
|
|
|
where `<address>` is the address of the account.
|
|
|
|
In Basecoin, the address of an account is the 20-byte `RIPEMD160` hash of the public key.
|
|
|
|
The Merkle tree used in Basecoin is a balanced, binary search tree, which we call an [IAVL tree](https://github.com/tendermint/go-merkle).
|
2017-02-04 21:43:55 -08:00
|
|
|
|
|
|
|
## 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:
|
|
|
|
|
2017-02-12 22:57:21 -08:00
|
|
|
```golang
|
2017-02-04 21:43:55 -08:00
|
|
|
type SendTx struct {
|
2017-02-08 04:18:26 -08:00
|
|
|
Gas int64 `json:"gas"`
|
|
|
|
Fee Coin `json:"fee"`
|
2017-02-04 21:43:55 -08:00
|
|
|
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
|
2017-02-19 10:52:02 -08:00
|
|
|
PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0
|
2017-02-04 21:43:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
type TxOutput struct {
|
|
|
|
Address []byte `json:"address"` // Hash of the PubKey
|
|
|
|
Coins Coins `json:"coins"` //
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2017-02-08 04:18:26 -08:00
|
|
|
There are a few things to note. First, the `SendTx` includes a field for `Gas` and `Fee`.
|
2017-02-04 21:43:55 -08:00
|
|
|
The `Gas` limits the total amount of computation that can be done by the transaction,
|
2017-02-08 04:18:26 -08:00
|
|
|
while the `Fee` refers to the total amount paid in fees.
|
2017-02-04 21:43:55 -08:00
|
|
|
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.
|
|
|
|
|
2017-02-12 22:57:21 -08:00
|
|
|
In Tendermint, the `Fee` is meant to be used by the validators to inform the ordering
|
|
|
|
of transactions, like in bitcoin. And the `Gas` is meant to be used by the application
|
|
|
|
plugin to control its execution. There is currently no means to pass `Fee` information
|
|
|
|
to the Tendermint validators, but it will come soon...
|
2017-02-08 04:18:26 -08:00
|
|
|
|
|
|
|
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,
|
2017-02-04 21:43:55 -08:00
|
|
|
using only the `Address` to refer to the sender. Ethereum does not require public keys to be sent in transactions
|
2017-02-12 22:57:21 -08:00
|
|
|
as it uses a different elliptic curve scheme which enables the public key to be derived from the signature itself.
|
2017-02-04 21:43:55 -08:00
|
|
|
|
2017-02-12 22:57:21 -08:00
|
|
|
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. When using multiple
|
|
|
|
inputs and outputs, you must make sure that the sum of coins of the inputs equals the sum of
|
|
|
|
coins of the outputs (no creating money), and that all accounts that provide inputs have signed the transaction.
|
2017-02-04 21:43:55 -08:00
|
|
|
|
2017-02-07 13:28:41 -08:00
|
|
|
## Plugins
|
2017-02-04 21:43:55 -08:00
|
|
|
|
2017-02-08 04:18:26 -08:00
|
|
|
Basecoin actually defines a second transaction type, the `AppTx`,
|
2017-02-07 13:28:41 -08:00
|
|
|
which enables the functionality to be extended via custom plugins.
|
|
|
|
To learn more about the `AppTx` and plugin system, see the [plugin design document](plugin-design.md).
|
|
|
|
To implement your first plugin, see [plugin tutorial](example-plugin.md).
|