cosmos-sdk/Plugins.md

3.6 KiB

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.

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:

type SendTx struct {
  Gas     int64      `json:"gas"` // Gas
  Fee     Coin       `json:"fee"` // 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"`
}

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.

Basecoin also defines another transaction type, the AppTx:

type AppTx struct {
  Gas   int64   `json:"gas"`   // Gas
  Fee   Coin    `json:"fee"`   // Fee
  Name  string  `json:"type"`  // Which plugin
  Input TxInput `json:"input"`
  Data  []byte  `json:"data"`
}

The AppTx enables arbitrary additional functionality through the use of 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 Name field in the AppTx refers to the plugin name, and the Data field of the AppTx is forward to the RunTx function.

You can look at some example plugins in the basecoin repo.

If you want to see how you can write a plugin in your own repo, and make use of all the basecoin tooling, cli, etc. please take a look at the mintcoin example for inspiration, not just the plugin itself, but also the cmd/mintcoin directory to create the custom command.