docs: use x dir for extensions
This commit is contained in:
parent
461c776404
commit
e6b0983e53
|
@ -0,0 +1,321 @@
|
||||||
|
Basecoin Basics
|
||||||
|
===============
|
||||||
|
|
||||||
|
Here we explain how to get started with a basic Basecoin blockchain, how
|
||||||
|
to send transactions between accounts using the ``basecoin`` tool, and
|
||||||
|
what is happening under the hood.
|
||||||
|
|
||||||
|
Install
|
||||||
|
-------
|
||||||
|
|
||||||
|
With go, it's one command:
|
||||||
|
|
||||||
|
.. code:: shelldown[0]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
go get -u github.com/cosmos/cosmos-sdk
|
||||||
|
|
||||||
|
If you have trouble, see the `installation guide <./install.html>`__.
|
||||||
|
|
||||||
|
TODO: update all the below
|
||||||
|
|
||||||
|
Generate some keys
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Let's generate two keys, one to receive an initial allocation of coins,
|
||||||
|
and one to send some coins to later:
|
||||||
|
|
||||||
|
.. code:: shelldown[1]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli keys new cool
|
||||||
|
basecli keys new friend
|
||||||
|
|
||||||
|
You'll need to enter passwords. You can view your key names and
|
||||||
|
addresses with ``basecli keys list``, or see a particular key's address
|
||||||
|
with ``basecli keys get <NAME>``.
|
||||||
|
|
||||||
|
Initialize Basecoin
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
To initialize a new Basecoin blockchain, run:
|
||||||
|
|
||||||
|
.. code:: shelldown[2]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecoin init <ADDRESS>
|
||||||
|
|
||||||
|
If you prefer not to copy-paste, you can provide the address
|
||||||
|
programatically:
|
||||||
|
|
||||||
|
.. code:: shelldown[3]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecoin init $(basecli keys get cool | awk '{print $2}')
|
||||||
|
|
||||||
|
This will create the necessary files for a Basecoin blockchain with one
|
||||||
|
validator and one account (corresponding to your key) in
|
||||||
|
``~/.basecoin``. For more options on setup, see the `guide to using the
|
||||||
|
Basecoin tool </docs/guide/basecoin-tool.md>`__.
|
||||||
|
|
||||||
|
If you like, you can manually add some more accounts to the blockchain
|
||||||
|
by generating keys and editing the ``~/.basecoin/genesis.json``.
|
||||||
|
|
||||||
|
Start Basecoin
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Now we can start Basecoin:
|
||||||
|
|
||||||
|
.. code:: shelldown[4]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecoin start
|
||||||
|
|
||||||
|
You should see blocks start streaming in!
|
||||||
|
|
||||||
|
Initialize Light-Client
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Now that Basecoin is running we can initialize ``basecli``, the
|
||||||
|
light-client utility. Basecli is used for sending transactions and
|
||||||
|
querying the state. Leave Basecoin running and open a new terminal
|
||||||
|
window. Here run:
|
||||||
|
|
||||||
|
.. code:: shelldown[5]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli init --node=tcp://localhost:46657 --genesis=$HOME/.basecoin/genesis.json
|
||||||
|
|
||||||
|
If you provide the genesis file to basecli, it can calculate the proper
|
||||||
|
chainID and validator hash. Basecli needs to get this information from
|
||||||
|
some trusted source, so all queries done with ``basecli`` can be
|
||||||
|
cryptographically proven to be correct according to a known validator
|
||||||
|
set.
|
||||||
|
|
||||||
|
Note: that ``--genesis`` only works if there have been no validator set
|
||||||
|
changes since genesis. If there are validator set changes, you need to
|
||||||
|
find the current set through some other method.
|
||||||
|
|
||||||
|
Send transactions
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Now we are ready to send some transactions. First Let's check the
|
||||||
|
balance of the two accounts we setup earlier:
|
||||||
|
|
||||||
|
.. code:: shelldown[6]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
ME=$(basecli keys get cool | awk '{print $2}')
|
||||||
|
YOU=$(basecli keys get friend | awk '{print $2}')
|
||||||
|
basecli query account $ME
|
||||||
|
basecli query account $YOU
|
||||||
|
|
||||||
|
The first account is flush with cash, while the second account doesn't
|
||||||
|
exist. Let's send funds from the first account to the second:
|
||||||
|
|
||||||
|
.. code:: shelldown[7]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli tx send --name=cool --amount=1000mycoin --to=$YOU --sequence=1
|
||||||
|
|
||||||
|
Now if we check the second account, it should have ``1000`` 'mycoin'
|
||||||
|
coins!
|
||||||
|
|
||||||
|
.. code:: shelldown[8]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli query account $YOU
|
||||||
|
|
||||||
|
We can send some of these coins back like so:
|
||||||
|
|
||||||
|
.. code:: shelldown[9]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli tx send --name=friend --amount=500mycoin --to=$ME --sequence=1
|
||||||
|
|
||||||
|
Note how we use the ``--name`` flag to select a different account to
|
||||||
|
send from.
|
||||||
|
|
||||||
|
If we try to send too much, we'll get an error:
|
||||||
|
|
||||||
|
.. code:: shelldown[10]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli tx send --name=friend --amount=500000mycoin --to=$ME --sequence=2
|
||||||
|
|
||||||
|
Let's send another transaction:
|
||||||
|
|
||||||
|
.. code:: shelldown[11]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli tx send --name=cool --amount=2345mycoin --to=$YOU --sequence=2
|
||||||
|
|
||||||
|
Note the ``hash`` value in the response - this is the hash of the
|
||||||
|
transaction. We can query for the transaction by this hash:
|
||||||
|
|
||||||
|
.. code:: shelldown[12]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli query tx <HASH>
|
||||||
|
|
||||||
|
See ``basecli tx send --help`` for additional details.
|
||||||
|
|
||||||
|
Proof
|
||||||
|
-----
|
||||||
|
|
||||||
|
Even if you don't see it in the UI, the result of every query comes with
|
||||||
|
a proof. This is a Merkle proof that the result of the query is actually
|
||||||
|
contained in the state. And the state's Merkle root is contained in a
|
||||||
|
recent block header. Behind the scenes, ``countercli`` will not only
|
||||||
|
verify that this state matches the header, but also that the header is
|
||||||
|
properly signed by the known validator set. It will even update the
|
||||||
|
validator set as needed, so long as there have not been major changes
|
||||||
|
and it is secure to do so. So, if you wonder why the query may take a
|
||||||
|
second... there is a lot of work going on in the background to make sure
|
||||||
|
even a lying full node can't trick your client.
|
||||||
|
|
||||||
|
Accounts and Transactions
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
For a better understanding of how to further use the tools, it helps to
|
||||||
|
understand the underlying data structures.
|
||||||
|
|
||||||
|
Accounts
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
The Basecoin state consists entirely of a set of accounts. Each account
|
||||||
|
contains a 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.
|
||||||
|
|
||||||
|
.. code:: golang
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
If you want to add more coins to a blockchain, you can do so manually in
|
||||||
|
the ``~/.basecoin/genesis.json`` before you start the blockchain for the
|
||||||
|
first time.
|
||||||
|
|
||||||
|
Accounts are serialized and stored in a Merkle tree under the key
|
||||||
|
``base/a/<address>``, where ``<address>`` is the address of the account.
|
||||||
|
Typically, the address of the account is the 20-byte ``RIPEMD160`` hash
|
||||||
|
of the public key, but other formats are acceptable as well, as defined
|
||||||
|
in the `Tendermint crypto
|
||||||
|
library <https://github.com/tendermint/go-crypto>`__. The Merkle tree
|
||||||
|
used in Basecoin is a balanced, binary search tree, which we call an
|
||||||
|
`IAVL tree <https://github.com/tendermint/iavl>`__.
|
||||||
|
|
||||||
|
Transactions
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Basecoin defines a 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:
|
||||||
|
|
||||||
|
.. code:: golang
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
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"` //
|
||||||
|
}
|
||||||
|
|
||||||
|
Note 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.
|
||||||
|
|
||||||
|
In Basecoin, 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...
|
||||||
|
|
||||||
|
Note also 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 derived 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. 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.
|
||||||
|
|
||||||
|
Clean Up
|
||||||
|
--------
|
||||||
|
|
||||||
|
**WARNING:** Running these commands will wipe out any existing
|
||||||
|
information in both the ``~/.basecli`` and ``~/.basecoin`` directories,
|
||||||
|
including private keys.
|
||||||
|
|
||||||
|
To remove all the files created and refresh your environment (e.g., if
|
||||||
|
starting this tutorial again or trying something new), the following
|
||||||
|
commands are run:
|
||||||
|
|
||||||
|
.. code:: shelldown[end-of-tutorials]
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
basecli reset_all
|
||||||
|
rm -rf ~/.basecoin
|
||||||
|
|
||||||
|
In this guide, we introduced the ``basecoin`` and ``basecli`` tools,
|
||||||
|
demonstrated how to start a new basecoin blockchain and how to send
|
||||||
|
tokens between accounts, and discussed the underlying data types for
|
||||||
|
accounts and transactions, specifically the ``Account`` and the
|
||||||
|
``SendTx``.
|
|
@ -255,42 +255,3 @@ signing, one could also specify the scope(s) that this signature
|
||||||
authorizes. The `oauth
|
authorizes. The `oauth
|
||||||
protocol <https://api.slack.com/docs/oauth-scopes>`__ also has to deal
|
protocol <https://api.slack.com/docs/oauth-scopes>`__ also has to deal
|
||||||
with a similar problem, and maybe could provide some inspiration.
|
with a similar problem, and maybe could provide some inspiration.
|
||||||
|
|
||||||
Replay Protection
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
In order to prevent `replay
|
|
||||||
attacks <https://en.wikipedia.org/wiki/Replay_attack>`__ a multi account
|
|
||||||
nonce system has been constructed as a module, which can be found in
|
|
||||||
``modules/nonce``. By adding the nonce module to the stack, each
|
|
||||||
transaction is verified for authenticity against replay attacks. This is
|
|
||||||
achieved by requiring that a new signed copy of the sequence number
|
|
||||||
which must be exactly 1 greater than the sequence number of the previous
|
|
||||||
transaction. A distinct sequence number is assigned per chain-id,
|
|
||||||
application, and group of signers. Each sequence number is tracked as a
|
|
||||||
nonce-store entry where the key is the marshaled list of actors after
|
|
||||||
having been sorted by chain, app, and address.
|
|
||||||
|
|
||||||
.. code:: golang
|
|
||||||
|
|
||||||
// Tx - Nonce transaction structure, contains list of signers and current sequence number
|
|
||||||
type Tx struct {
|
|
||||||
Sequence uint32 `json:"sequence"`
|
|
||||||
Signers []basecoin.Actor `json:"signers"`
|
|
||||||
Tx basecoin.Tx `json:"tx"`
|
|
||||||
}
|
|
||||||
|
|
||||||
By distinguishing sequence numbers across groups of Signers,
|
|
||||||
multi-signature Actors need not lock up use of their Address while
|
|
||||||
waiting for all the members of a multi-sig transaction to occur. Instead
|
|
||||||
only the multi-sig account will be locked, while other accounts
|
|
||||||
belonging to that signer can be used and signed with other sequence
|
|
||||||
numbers.
|
|
||||||
|
|
||||||
By abstracting out the nonce module in the stack, entire series of
|
|
||||||
transactions can occur without needing to verify the nonce for each
|
|
||||||
member of the series. An common example is a stack which will send coins
|
|
||||||
and charge a fee. Within the SDK this can be achieved using separate
|
|
||||||
modules in a stack, one to send the coins and the other to charge the
|
|
||||||
fee, however both modules do not need to check the nonce. This can occur
|
|
||||||
as a separate module earlier in the stack.
|
|
||||||
|
|
|
@ -27,7 +27,16 @@ Basecoin
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
basecoin/basics.rst
|
basecoin/basics.rst
|
||||||
basecoin/plugins.rst
|
basecoin/extensions.rst
|
||||||
|
|
||||||
|
Extensions
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
x/replay-protection.rst
|
||||||
|
|
||||||
|
|
||||||
Staking Module
|
Staking Module
|
||||||
--------------
|
--------------
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
Replay Protection
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
In order to prevent `replay
|
||||||
|
attacks <https://en.wikipedia.org/wiki/Replay_attack>`__ a multi account
|
||||||
|
nonce system has been constructed as a module, which can be found in
|
||||||
|
``modules/nonce``. By adding the nonce module to the stack, each
|
||||||
|
transaction is verified for authenticity against replay attacks. This is
|
||||||
|
achieved by requiring that a new signed copy of the sequence number
|
||||||
|
which must be exactly 1 greater than the sequence number of the previous
|
||||||
|
transaction. A distinct sequence number is assigned per chain-id,
|
||||||
|
application, and group of signers. Each sequence number is tracked as a
|
||||||
|
nonce-store entry where the key is the marshaled list of actors after
|
||||||
|
having been sorted by chain, app, and address.
|
||||||
|
|
||||||
|
.. code:: golang
|
||||||
|
|
||||||
|
// Tx - Nonce transaction structure, contains list of signers and current sequence number
|
||||||
|
type Tx struct {
|
||||||
|
Sequence uint32 `json:"sequence"`
|
||||||
|
Signers []basecoin.Actor `json:"signers"`
|
||||||
|
Tx basecoin.Tx `json:"tx"`
|
||||||
|
}
|
||||||
|
|
||||||
|
By distinguishing sequence numbers across groups of Signers,
|
||||||
|
multi-signature Actors need not lock up use of their Address while
|
||||||
|
waiting for all the members of a multi-sig transaction to occur. Instead
|
||||||
|
only the multi-sig account will be locked, while other accounts
|
||||||
|
belonging to that signer can be used and signed with other sequence
|
||||||
|
numbers.
|
||||||
|
|
||||||
|
By abstracting out the nonce module in the stack, entire series of
|
||||||
|
transactions can occur without needing to verify the nonce for each
|
||||||
|
member of the series. An common example is a stack which will send coins
|
||||||
|
and charge a fee. Within the SDK this can be achieved using separate
|
||||||
|
modules in a stack, one to send the coins and the other to charge the
|
||||||
|
fee, however both modules do not need to check the nonce. This can occur
|
||||||
|
as a separate module earlier in the stack.
|
Loading…
Reference in New Issue