Merge pull request #56 from tendermint/develop

v0.3.0
This commit is contained in:
Ethan Buchman 2017-03-23 18:15:40 -04:00 committed by GitHub
commit 384a4041d5
50 changed files with 788 additions and 425 deletions

View File

@ -1,5 +1,58 @@
# Changelog
## 0.3.0 (March 23, 2017)
BREAKING CHANGES:
- Remove `--data` flag and use `BCHOME` to set the home directory (defaults to `~/.basecoin`)
- Remove `--in-proc` flag and start Tendermint in-process by default (expect Tendermint files in $BCHOME/tendermint).
To start just the ABCI app/server, use `basecoin start --without-tendermint`.
- Consolidate genesis files so the Basecoin genesis is an object under `app_options` in Tendermint genesis. For instance:
```
{
"app_hash": "",
"chain_id": "foo_bar_chain",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
]
}
],
"app_options": {
"accounts": [{
"pub_key": {
"type": "ed25519",
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
},
"coins": [
{
"denom": "blank",
"amount": 12345
},
{
"denom": "ETH",
"amount": 654321
}
]
}],
"plugin_options": ["plugin1/key1", "value1", "plugin1/key2", "value2"]
}
}
```
Note the array of key-value pairs is now under `app_options.plugin_options` while the `app_options` themselves are well formed.
We also changed `chainID` to `chain_id` and consolidated to have just one of them.
FEATURES:
- Introduce `basecoin init` and `basecoin unsafe_reset_all`
## 0.2.0 (March 6, 2017)
BREAKING CHANGES:

28
Dockerfile Normal file
View File

@ -0,0 +1,28 @@
FROM alpine:3.5
# BCHOME is where your genesis.json, key.json and other files including state are stored.
ENV BCHOME /basecoin
# Create a basecoin user and group first so the IDs get set the same way, even
# as the rest of this may change over time.
RUN addgroup basecoin && \
adduser -S -G basecoin basecoin
RUN mkdir -p $BCHOME && \
chown -R basecoin:basecoin $BCHOME
WORKDIR $BCHOME
# Expose the basecoin home directory as a volume since there's mutable state in there.
VOLUME $BCHOME
# jq and curl used for extracting `pub_key` from private validator while
# deploying tendermint with Kubernetes. It is nice to have bash so the users
# could execute bash commands.
RUN apk add --no-cache bash curl jq
COPY basecoin /usr/bin/basecoin
ENTRYPOINT ["basecoin"]
# By default you will get the basecoin with local MerkleEyes and in-proc Tendermint.
CMD ["start", "--dir=${BCHOME}"]

12
Dockerfile.dev Normal file
View File

@ -0,0 +1,12 @@
FROM golang:latest
RUN mkdir -p /go/src/github.com/tendermint/basecoin
WORKDIR /go/src/github.com/tendermint/basecoin
COPY Makefile /go/src/github.com/tendermint/basecoin/
COPY glide.yaml /go/src/github.com/tendermint/basecoin/
COPY glide.lock /go/src/github.com/tendermint/basecoin/
RUN make get_vendor_deps
COPY . /go/src/github.com/tendermint/basecoin

View File

@ -1,5 +1,3 @@
.PHONY: all test get_deps
all: test install
NOVENDOR = go list github.com/tendermint/basecoin/... | grep -v /vendor/
@ -24,3 +22,11 @@ get_vendor_deps:
go get github.com/Masterminds/glide
glide install
build-docker:
docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin
docker build -t "tendermint/basecoin" .
clean:
@rm -f ./basecoin
.PHONY: all build install test get_deps update_deps get_vendor_deps build-docker clean

View File

@ -15,46 +15,26 @@ WARNING: Currently uses plain-text private keys for transactions and is otherwis
## Prerequisites
* Go to https://golang.org/doc/install to install Golang.
* You will also need to set the $GOPATH environment variable as per the instructions [here](https://golang.org/doc/code.html#GOPATH).
[Install and setup Golang](https://tendermint.com/docs/guides/install-go).
## Installation
On a good day, basecoin can be installed like a normal Go program:
```
go get -u github.com/tendermint/basecoin/cmd/basecoin
```
If that fails, or if another branch is required, you may have to compile from source.
You will first need to install the Golang package manager [`glide`](https://github.com/Masterminds/glide).
```
cd $GOPATH/src/github.com/tendermint/basecoin
git checkout develop # (until we release tendermint v0.9)
make get_vendor_deps
make install
```
This will create the `basecoin` binary in `$GOPATH/bin`.
See the [install guide](/docs/guide/install.md) for more details.
## Command Line Interface
## Guide
The basecoin CLI can be used to start a stand-alone basecoin instance (`basecoin start`),
or to start basecoin with Tendermint in the same process (`basecoin start --in-proc`).
It can also be used to send transactions, eg. `basecoin tx send --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 100btc,10gold`
See `basecoin --help` and `basecoin [cmd] --help` for more details`.
## Learn more
1. Getting started with the [Basecoin tool](/docs/guide/basecoin-basics.md)
1. Getting started with the [Basecoin basics](/docs/guide/basecoin-basics.md)
1. Learn more about [Basecoin's design](/docs/guide/basecoin-design.md)
1. Extend Basecoin [using the plugin system](/docs/guide/example-plugin.md)
1. Learn more about [plugin design](/docs/guide/plugin-design.md)
1. See some [more example applications](/docs/guide/more-examples.md)
1. More features of the [Basecoin tool](/docs/guide/basecoin-tool.md)
1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md)
1. [Deploy testnets](deployment.md) running your basecoin application.
1. [Deploy testnets](/docs/guide/deployment.md) running your basecoin application.

View File

@ -60,12 +60,12 @@ func (app *Basecoin) SetOption(key string, value string) string {
if plugin == nil {
return "Invalid plugin name: " + pluginName
}
log.Info("SetOption on plugin", "plugin", pluginName, "key", key, "value", value)
log.Notice("SetOption on plugin", "plugin", pluginName, "key", key, "value", value)
return plugin.SetOption(app.state, key, value)
} else {
// Set option on basecoin
switch key {
case "chainID":
case "chain_id":
app.state.SetChainID(value)
return "Success"
case "account":
@ -75,7 +75,8 @@ func (app *Basecoin) SetOption(key string, value string) string {
return "Error decoding acc message: " + err.Error()
}
app.state.SetAccount(acc.PubKey.Address(), &acc)
log.Info("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
log.Notice("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
return "Success"
}
return "Unrecognized option key " + key

View File

@ -4,16 +4,35 @@ import (
"encoding/json"
"github.com/pkg/errors"
"github.com/tendermint/basecoin/types"
cmn "github.com/tendermint/go-common"
//tmtypes "github.com/tendermint/tendermint/types"
)
func (app *Basecoin) LoadGenesis(path string) error {
kvz, err := loadGenesis(path)
genDoc, err := loadGenesis(path)
if err != nil {
return err
}
for _, kv := range kvz {
app.SetOption(kv.Key, kv.Value)
// set chain_id
app.SetOption("base/chain_id", genDoc.ChainID)
// set accounts
for _, acc := range genDoc.AppOptions.Accounts {
accBytes, err := json.Marshal(acc)
if err != nil {
return err
}
r := app.SetOption("base/account", string(accBytes))
// TODO: SetOption returns an error
log.Notice("Done setting Account via SetOption", "result", r)
}
// set plugin options
for _, kv := range genDoc.AppOptions.pluginOptions {
r := app.SetOption(kv.Key, kv.Value)
log.Notice("Done setting Plugin key-value pair via SetOption", "result", r, "k", kv.Key, "v", kv.Value)
}
return nil
}
@ -23,16 +42,45 @@ type keyValue struct {
Value string `json:"value"`
}
func loadGenesis(filePath string) (kvz []keyValue, err error) {
kvz_ := []json.RawMessage{}
// includes tendermint (in the json, we ignore here)
type FullGenesisDoc struct {
ChainID string `json:"chain_id"`
AppOptions *GenesisDoc `json:"app_options"`
}
type GenesisDoc struct {
Accounts []types.Account `json:"accounts"`
PluginOptions []json.RawMessage `json:"plugin_options"`
pluginOptions []keyValue // unmarshaled rawmessages
}
func loadGenesis(filePath string) (*FullGenesisDoc, error) {
bytes, err := cmn.ReadFile(filePath)
if err != nil {
return nil, errors.Wrap(err, "loading genesis file")
}
err = json.Unmarshal(bytes, &kvz_)
// the tendermint genesis is go-wire
// tmGenesis := new(tmtypes.GenesisDoc)
// err = wire.ReadJSONBytes(bytes, tmGenesis)
// the basecoin genesis go-data :)
genDoc := new(FullGenesisDoc)
err = json.Unmarshal(bytes, genDoc)
if err != nil {
return nil, errors.Wrap(err, "parsing genesis file")
return nil, errors.Wrap(err, "unmarshaling genesis file")
}
pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions)
if err != nil {
return nil, err
}
genDoc.AppOptions.pluginOptions = pluginOpts
return genDoc, nil
}
func parseGenesisList(kvz_ []json.RawMessage) (kvz []keyValue, err error) {
if len(kvz_)%2 != 0 {
return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]")
}

View File

@ -1,19 +1,22 @@
[
"base/chainID", "foo_bar_chain",
"base/account", {
"pub_key": {
"type": "ed25519",
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
},
"coins": [
{
"denom": "blank",
"amount": 12345
{
"chain_id": "foo_bar_chain",
"app_options": {
"accounts": [{
"pub_key": {
"type": "ed25519",
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
},
{
"denom": "ETH",
"amount": 654321
}
]
"coins": [
{
"denom": "blank",
"amount": 12345
},
{
"denom": "ETH",
"amount": 654321
}
]
}],
"plugin_options": ["plugin1/key1", "value1", "plugin1/key2", "value2"]
}
]
}

View File

@ -14,6 +14,7 @@ func main() {
app.Usage = "basecoin [command] [args...]"
app.Version = version.Version
app.Commands = []cli.Command{
commands.InitCmd,
commands.StartCmd,
commands.TxCmd,
commands.QueryCmd,
@ -21,6 +22,7 @@ func main() {
commands.VerifyCmd,
commands.BlockCmd,
commands.AccountCmd,
commands.UnsafeResetAllCmd,
}
app.Run(os.Args)
}

View File

@ -21,15 +21,9 @@ var (
// TODO: move to config file
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
DirFlag = cli.StringFlag{
Name: "dir",
Value: ".",
Usage: "Root directory",
}
InProcTMFlag = cli.BoolFlag{
Name: "in-proc",
Usage: "Run Tendermint in-process with the App",
WithoutTendermintFlag = cli.BoolFlag{
Name: "without-tendermint",
Usage: "Run the Basecoin app without Tendermint",
}
)

122
cmd/commands/init.go Normal file
View File

@ -0,0 +1,122 @@
package commands
import (
"io/ioutil"
"path"
"github.com/urfave/cli"
cmn "github.com/tendermint/go-common"
)
var InitCmd = cli.Command{
Name: "init",
Usage: "Initialize a basecoin blockchain",
ArgsUsage: "",
Action: func(c *cli.Context) error {
return cmdInit(c)
},
Flags: []cli.Flag{
ChainIDFlag,
},
}
func cmdInit(c *cli.Context) error {
rootDir := BasecoinRoot("")
cmn.EnsureDir(rootDir, 0777)
// initalize basecoin
genesisFile := path.Join(rootDir, "genesis.json")
privValFile := path.Join(rootDir, "priv_validator.json")
key1File := path.Join(rootDir, "key.json")
key2File := path.Join(rootDir, "key2.json")
if err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644); err != nil {
return err
}
if err := ioutil.WriteFile(privValFile, []byte(privValJSON), 0400); err != nil {
return err
}
if err := ioutil.WriteFile(key1File, []byte(key1JSON), 0400); err != nil {
return err
}
if err := ioutil.WriteFile(key2File, []byte(key2JSON), 0400); err != nil {
return err
}
log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File)
return nil
}
const privValJSON = `{
"address": "7A956FADD20D3A5B2375042B2959F8AB172A058F",
"last_height": 0,
"last_round": 0,
"last_signature": null,
"last_signbytes": "",
"last_step": 0,
"priv_key": [
1,
"D07ABE82A8B15559A983B2DB5D4842B2B6E4D6AF58B080005662F424F17D68C17B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
],
"pub_key": [
1,
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
]
}`
const genesisJSON = `{
"app_hash": "",
"chain_id": "test_chain_id",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
]
}
],
"app_options": {
"accounts": [{
"pub_key": {
"type": "ed25519",
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}]
}
}`
const key1JSON = `{
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
"priv_key": {
"type": "ed25519",
"data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
},
"pub_key": {
"type": "ed25519",
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
}
}`
const key2JSON = `{
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
"priv_key": {
"type": "ed25519",
"data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
},
"pub_key": {
"type": "ed25519",
"data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
}
}`

View File

@ -1,14 +1,17 @@
package commands
import (
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"path"
"strings"
"github.com/urfave/cli"
cmn "github.com/tendermint/go-common"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
)
var (
@ -31,18 +34,36 @@ var (
func cmdNewKey(c *cli.Context) error {
key := genKey()
keyJSON := wire.JSONBytesPretty(key)
fmt.Println(string(keyJSON))
keyJSON, err := json.MarshalIndent(key, "", "\t")
if err != nil {
return err
}
fmt.Println(keyJSON)
return nil
}
//---------------------------------------------
// simple implementation of a key
type Address [20]byte
func (a Address) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%x"`, a[:])), nil
}
func (a *Address) UnmarshalJSON(addrHex []byte) error {
addr, err := hex.DecodeString(strings.Trim(string(addrHex), `"`))
if err != nil {
return err
}
copy(a[:], addr)
return nil
}
type Key struct {
Address []byte `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
PrivKey crypto.PrivKey `json:"priv_key"`
Address Address `json:"address"`
PubKey crypto.PubKeyS `json:"pub_key"`
PrivKey crypto.PrivKeyS `json:"priv_key"`
}
// Implements Signer
@ -53,21 +74,26 @@ func (k *Key) Sign(msg []byte) crypto.Signature {
// Generates a new validator with private key.
func genKey() *Key {
privKey := crypto.GenPrivKeyEd25519()
addrBytes := privKey.PubKey().Address()
var addr Address
copy(addr[:], addrBytes)
return &Key{
Address: privKey.PubKey().Address(),
PubKey: privKey.PubKey(),
PrivKey: privKey,
Address: addr,
PubKey: crypto.PubKeyS{privKey.PubKey()},
PrivKey: crypto.PrivKeyS{privKey},
}
}
func LoadKey(filePath string) *Key {
func LoadKey(keyFile string) *Key {
filePath := path.Join(BasecoinRoot(""), keyFile)
keyJSONBytes, err := ioutil.ReadFile(filePath)
if err != nil {
cmn.Exit(err.Error())
}
key := wire.ReadJSON(&Key{}, keyJSONBytes, &err).(*Key)
key := new(Key)
err = json.Unmarshal(keyJSONBytes, key)
if err != nil {
cmn.Exit(cmn.Fmt("Error reading PrivValidator from %v: %v\n", filePath, err))
cmn.Exit(cmn.Fmt("Error reading key from %v: %v\n", filePath, err))
}
return key
}

7
cmd/commands/log.go Normal file
View File

@ -0,0 +1,7 @@
package commands
import (
"github.com/tendermint/go-logger"
)
var log = logger.New("module", "commands")

47
cmd/commands/reset.go Normal file
View File

@ -0,0 +1,47 @@
package commands
import (
"os"
"path"
"github.com/urfave/cli"
tmcfg "github.com/tendermint/tendermint/config/tendermint"
types "github.com/tendermint/tendermint/types"
)
var UnsafeResetAllCmd = cli.Command{
Name: "unsafe_reset_all",
Usage: "Reset all blockchain data",
ArgsUsage: "",
Action: func(c *cli.Context) error {
return cmdUnsafeResetAll(c)
},
}
func cmdUnsafeResetAll(c *cli.Context) error {
basecoinDir := BasecoinRoot("")
tmDir := path.Join(basecoinDir)
tmConfig := tmcfg.GetConfig(tmDir)
// Get and Reset PrivValidator
var privValidator *types.PrivValidator
privValidatorFile := tmConfig.GetString("priv_validator_file")
if _, err := os.Stat(privValidatorFile); err == nil {
privValidator = types.LoadPrivValidator(privValidatorFile)
privValidator.Reset()
log.Notice("Reset PrivValidator", "file", privValidatorFile)
} else {
privValidator = types.GenPrivValidator()
privValidator.SetFile(privValidatorFile)
privValidator.Save()
log.Notice("Generated PrivValidator", "file", privValidatorFile)
}
// Remove all tendermint data
tmDataDir := tmConfig.GetString("db_dir")
os.RemoveAll(tmDataDir)
log.Notice("Removed all data", "dir", tmDataDir)
return nil
}

View File

@ -10,8 +10,6 @@ import (
"github.com/tendermint/abci/server"
cmn "github.com/tendermint/go-common"
cfg "github.com/tendermint/go-config"
//logger "github.com/tendermint/go-logger"
eyes "github.com/tendermint/merkleeyes/client"
tmcfg "github.com/tendermint/tendermint/config/tendermint"
@ -23,8 +21,6 @@ import (
"github.com/tendermint/basecoin/types"
)
var config cfg.Config
const EyesCacheSize = 10000
var StartCmd = cli.Command{
@ -37,8 +33,7 @@ var StartCmd = cli.Command{
Flags: []cli.Flag{
AddrFlag,
EyesFlag,
DirFlag,
InProcTMFlag,
WithoutTendermintFlag,
ChainIDFlag,
},
}
@ -56,11 +51,12 @@ func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
}
func cmdStart(c *cli.Context) error {
basecoinDir := BasecoinRoot("")
// Connect to MerkleEyes
var eyesCli *eyes.Client
if c.String("eyes") == "local" {
eyesCli = eyes.NewLocalClient(path.Join(c.String("dir"), "merkleeyes.db"), EyesCacheSize)
eyesCli = eyes.NewLocalClient(path.Join(basecoinDir, "data", "merkleeyes.db"), EyesCacheSize)
} else {
var err error
eyesCli, err = eyes.NewClient(c.String("eyes"))
@ -80,23 +76,30 @@ func cmdStart(c *cli.Context) error {
basecoinApp.RegisterPlugin(p.newPlugin())
}
// If genesis file exists, set key-value options
genesisFile := path.Join(c.String("dir"), "genesis.json")
if _, err := os.Stat(genesisFile); err == nil {
err := basecoinApp.LoadGenesis(genesisFile)
if err != nil {
return errors.New(cmn.Fmt("%+v", err))
// if chain_id has not been set yet, load the genesis.
// else, assume it's been loaded
if basecoinApp.GetState().GetChainID() == "" {
// If genesis file exists, set key-value options
genesisFile := path.Join(basecoinDir, "genesis.json")
if _, err := os.Stat(genesisFile); err == nil {
err := basecoinApp.LoadGenesis(genesisFile)
if err != nil {
return errors.New(cmn.Fmt("%+v", err))
}
} else {
fmt.Printf("No genesis file at %s, skipping...\n", genesisFile)
}
} else {
fmt.Printf("No genesis file at %s, skipping...\n", genesisFile)
}
if c.Bool("in-proc") {
startTendermint(c, basecoinApp)
chainID := basecoinApp.GetState().GetChainID()
if c.Bool("without-tendermint") {
log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID)
// run just the abci app/server
return startBasecoinABCI(c, basecoinApp)
} else {
if err := startBasecoinABCI(c, basecoinApp); err != nil {
return err
}
log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID)
// start the app with tendermint in-process
return startTendermint(basecoinDir, basecoinApp)
}
return nil
@ -117,23 +120,29 @@ func startBasecoinABCI(c *cli.Context, basecoinApp *app.Basecoin) error {
}
func startTendermint(c *cli.Context, basecoinApp *app.Basecoin) {
func startTendermint(dir string, basecoinApp *app.Basecoin) error {
// Get configuration
config = tmcfg.GetConfig("")
tmConfig := tmcfg.GetConfig(dir)
// logger.SetLogLevel("notice") //config.GetString("log_level"))
// parseFlags(config, args[1:]) // Command line overrides
// Create & start tendermint node
privValidatorFile := config.GetString("priv_validator_file")
privValidatorFile := tmConfig.GetString("priv_validator_file")
privValidator := tmtypes.LoadOrGenPrivValidator(privValidatorFile)
n := node.NewNode(config, privValidator, proxy.NewLocalClientCreator(basecoinApp))
n := node.NewNode(tmConfig, privValidator, proxy.NewLocalClientCreator(basecoinApp))
n.Start()
_, err := n.Start()
if err != nil {
return err
}
// Wait forever
cmn.TrapSignal(func() {
// Cleanup
n.Stop()
})
return nil
}

View File

@ -14,7 +14,6 @@ import (
client "github.com/tendermint/go-rpc/client"
"github.com/tendermint/go-wire"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
)
var TxFlags = []cli.Flag{
@ -87,7 +86,7 @@ func cmdSendTx(c *cli.Context) error {
privKey := LoadKey(fromFile)
// get the sequence number for the tx
sequence, err := getSeq(c, privKey.Address)
sequence, err := getSeq(c, privKey.Address[:])
if err != nil {
return err
}
@ -144,9 +143,9 @@ func AppTx(c *cli.Context, name string, data []byte) error {
gas := int64(c.Int("gas"))
chainID := c.String("chain_id")
privKey := tmtypes.LoadPrivValidator(fromFile)
privKey := LoadKey(fromFile)
sequence, err := getSeq(c, privKey.Address)
sequence, err := getSeq(c, privKey.Address[:])
if err != nil {
return err
}

View File

@ -3,6 +3,7 @@ package commands
import (
"encoding/hex"
"errors"
"os"
"regexp"
"strconv"
"strings"
@ -20,6 +21,16 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
func BasecoinRoot(rootDir string) string {
if rootDir == "" {
rootDir = os.Getenv("BCHOME")
}
if rootDir == "" {
rootDir = os.Getenv("HOME") + "/.basecoin"
}
return rootDir
}
// Returns true for non-empty hex-string prefixed with "0x"
func isHex(s string) bool {
if len(s) > 2 && s[:2] == "0x" {

View File

@ -1,15 +0,0 @@
[
"base/chainID", "test_chain_id",
"base/account", {
"pub_key": {
"type": "ed25519",
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}
]

View File

@ -1,11 +0,0 @@
{
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
"priv_key": [
1,
"C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
],
"pub_key": [
1,
"619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
]
}

View File

@ -1,11 +0,0 @@
{
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
"priv_key": [
1,
"34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
],
"pub_key": [
1,
"352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
]
}

View File

@ -1,13 +1,10 @@
#! /bin/bash
killall -9 basecoin tendermint
TMROOT=./data/chain1/tendermint tendermint unsafe_reset_all
TMROOT=./data/chain2/tendermint tendermint unsafe_reset_all
rm -rf ./data/chain1/basecoin/merkleeyes.db
rm -rf ./data/chain2/basecoin/merkleeyes.db
TMROOT=./data/chain1 tendermint unsafe_reset_all
TMROOT=./data/chain2 tendermint unsafe_reset_all
rm ./*.log
rm ./data/chain1/tendermint/*.bak
rm ./data/chain2/tendermint/*.bak
rm ./data/chain1/*.bak
rm ./data/chain2/*.bak

View File

@ -1,15 +0,0 @@
[
"base/chainID", "test_chain_1",
"base/account", {
"pub_key": {
"type": "ed25519",
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}
]

View File

@ -1,12 +0,0 @@
{
"address": "D397BC62B435F3CF50570FBAB4340FE52C60858F",
"priv_key": [
1,
"39E75AA1CF7BC710585977EFC375CD1730519186BD231478C339F2819C3C26E7B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
],
"pub_key": [
1,
"B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
]
}

View File

@ -0,0 +1,31 @@
{
"app_hash": "",
"chain_id": "test_chain_1",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"
]
}
],
"app_options": {
"accounts": [
{
"pub_key": {
"type": "ed25519",
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}
]
}
}

12
demo/data/chain1/key.json Normal file
View File

@ -0,0 +1,12 @@
{
"address": "D397BC62B435F3CF50570FBAB4340FE52C60858F",
"priv_key": {
"type": "ed25519",
"data": "39E75AA1CF7BC710585977EFC375CD1730519186BD231478C339F2819C3C26E7B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
},
"pub_key": {
"type": "ed25519",
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
}
}

View File

@ -1,15 +0,0 @@
{
"app_hash": "",
"chain_id": "test_chain_1",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"
]
}
]
}

View File

@ -1,15 +0,0 @@
[
"base/chainID", "test_chain_2",
"base/account", {
"pub_key": {
"type": "ed25519",
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}
]

View File

@ -1,11 +0,0 @@
{
"address": "053BA0F19616AFF975C8756A2CBFF04F408B4D47",
"priv_key": [
1,
"22920C428043D869987F253D7C9B2305E7010642C40CE88A52C9F6CE5ACC42080628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
],
"pub_key": [
1,
"0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
]
}

View File

@ -0,0 +1,31 @@
{
"app_hash": "",
"chain_id": "test_chain_2",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"
]
}
],
"app_options": {
"accounts": [
{
"pub_key": {
"type": "ed25519",
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
},
"coins": [
{
"denom": "mycoin",
"amount": 9007199254740992
}
]
}
]
}
}

11
demo/data/chain2/key.json Normal file
View File

@ -0,0 +1,11 @@
{
"address": "053BA0F19616AFF975C8756A2CBFF04F408B4D47",
"priv_key": {
"type": "ed25519",
"data": "22920C428043D869987F253D7C9B2305E7010642C40CE88A52C9F6CE5ACC42080628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
},
"pub_key": {
"type": "ed25519",
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
}
}

View File

@ -1,15 +0,0 @@
{
"app_hash": "",
"chain_id": "test_chain_2",
"genesis_time": "0001-01-01T00:00:00.000Z",
"validators": [
{
"amount": 10,
"name": "",
"pub_key": [
1,
"9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"
]
}
]
}

View File

@ -60,29 +60,34 @@ function waitForBlock() {
done
}
# make basecoin root vars
export BCHOME="."
BCHOME1="./data/chain1"
BCHOME2="./data/chain2"
# grab the chain ids
CHAIN_ID1=$(cat ./data/chain1/basecoin/genesis.json | jq .[1])
CHAIN_ID1=$(cat $BCHOME1/genesis.json | jq .chain_id)
CHAIN_ID1=$(removeQuotes $CHAIN_ID1)
CHAIN_ID2=$(cat ./data/chain2/basecoin/genesis.json | jq .[1])
CHAIN_ID2=$(cat $BCHOME2/genesis.json | jq .chain_id)
CHAIN_ID2=$(removeQuotes $CHAIN_ID2)
echo "CHAIN_ID1: $CHAIN_ID1"
echo "CHAIN_ID2: $CHAIN_ID2"
# make reusable chain flags
CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/basecoin/key.json"
CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/key.json --node tcp://localhost:36657"
CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from $BCHOME1/key.json"
CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from $BCHOME2/key.json --node tcp://localhost:36657"
echo ""
echo "... starting chains"
echo ""
# start the first node
TMROOT=./data/chain1/tendermint tendermint node --skip_upnp --log_level=info &> $LOG_DIR/chain1_tendermint.log &
basecoin start --dir ./data/chain1/basecoin &> $LOG_DIR/chain1_basecoin.log &
TMROOT=./data/chain1 tendermint node --skip_upnp --log_level=info &> $LOG_DIR/chain1_tendermint.log &
BCHOME=$BCHOME1 basecoin start --without-tendermint &> $LOG_DIR/chain1_basecoin.log &
# start the second node
TMROOT=./data/chain2/tendermint tendermint node --skip_upnp --log_level=info --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> $LOG_DIR/chain2_tendermint.log &
basecoin start --address tcp://localhost:36658 --dir ./data/chain2/basecoin &> $LOG_DIR/chain2_basecoin.log &
TMROOT=./data/chain2 tendermint node --skip_upnp --log_level=info --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> $LOG_DIR/chain2_tendermint.log &
BCHOME=$BCHOME2 basecoin start --address tcp://localhost:36658 --without-tendermint &> $LOG_DIR/chain2_basecoin.log &
echo ""
echo "... waiting for chains to start"
@ -98,7 +103,7 @@ sleep 3
echo "... registering chain1 on chain2"
echo ""
# register chain1 on chain2
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
echo ""
echo "... creating egress packet on chain1"

View File

@ -5,77 +5,34 @@ and how to send transactions between accounts using the `basecoin` tool.
## Install
Make sure you have [basecoin installed](install.md).
You will also need to [install Tendermint](https://tendermint.com/intro/getting-started/download).
Installing basecoin is simple:
**Note** All code is on the 0.9 pre-release branch, you may have to
[install Tendermint from source](https://tendermint.com/docs/guides/install)
until 0.9 is released. (Make sure to add `git checkout develop` to the linked install instructions)
```
go get -u github.com/tendermint/basecoin/cmd/basecoin
```
If you have trouble, see the [installation guide](install.md).
## Initialization
Basecoin is an ABCI application that runs on Tendermint, so we first need to initialize Tendermint:
To initialize a new Basecoin blockchain, run:
```
tendermint init
basecoin init
```
This will create the necessary files for a single Tendermint node in `~/.tendermint`.
If you had previously run Tendermint, make sure you reset the chain
(note this will delete all chain data, so back it up if you need it):
```
tendermint unsafe_reset_all
```
Now we need some initialization files for basecoin.
We have included some defaults in the basecoin directory, under `data`.
For purposes of convenience, change to that directory:
```
cd $GOPATH/src/github.com/tendermint/basecoin/data
```
The directory contains a genesis file and two private keys.
You can generate your own private keys with `tendermint gen_validator`,
and construct the `genesis.json` as you like.
Note, however, that you must be careful with the `chain_id` field,
as every transaction must contain the correct `chain_id`
(default is `test_chain_id`).
This will create the necessary files for a Basecoin blockchain with one validator and one account in `~/.basecoin`.
For more options on setup, see the [guide to using the Basecoin tool](/docs/guide/basecoin-tool.md).
## Start
Now we can start basecoin:
```
basecoin start --in-proc
```
This will initialize the chain with the `genesis.json` file from the current directory.
If you want to specify another location, you can run:
```
basecoin start --in-proc --dir PATH/TO/CUSTOM/DATA
```
Note that `--in-proc` stands for "in process", which means
basecoin will be started with the Tendermint node running in the same process.
To start Tendermint in a separate process instead, use:
```
basecoin start
```
and in another window:
```
tendermint node
```
In either case, you should see blocks start streaming in!
Note, however, that currently basecoin currently requires the
`develop` branch of Tendermint for this to work.
You should see blocks start streaming in!
## Send transactions
@ -98,8 +55,7 @@ Let's send funds from the first account to the second:
basecoin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 10mycoin
```
By default, the CLI looks for a `priv_validator.json` to sign the transaction with,
so this will only work if you are in the `$GOPATH/src/github.com/tendermint/basecoin/data`.
By default, the CLI looks for a `key.json` to sign the transaction with.
To specify a different key, we can use the `--from` flag.
Now if we check the second account, it should have `10` 'mycoin' coins!

142
docs/guide/basecoin-tool.md Normal file
View File

@ -0,0 +1,142 @@
# The Basecoin Tool
In previous tutorials we learned the [basics of the `basecoin` CLI](/docs/guides/basecoin-basics)
and [how to implement a plugin](/docs/guides/example-plugin).
In this tutorial, we provide more details on using the `basecoin` tool.
# Data Directory
By default, `basecoin` works out of `~/.basecoin`. To change this, set the `BCHOME` environment variable:
```
export BCHOME=~/.my_basecoin_data
basecoin init
basecoin start
```
or
```
BCHOME=~/.my_basecoin_data basecoin init
BCHOME=~/.my_basecoin_data basecoin start
```
# ABCI Server
So far we have run Basecoin and Tendermint in a single process.
However, since we use ABCI, we can actually run them in different processes.
First, initialize them:
```
basecoin init
```
This will create a single `genesis.json` file in `~/.basecoin` with the information for both Basecoin and Tendermint.
Now, In one window, run
```
basecoin start --without-tendermint
```
and in another,
```
TMROOT=~/.basecoin tendermint node
```
You should see Tendermint start making blocks!
Alternatively, you could ignore the Tendermint details in `~/.basecoin/genesis.json` and use a separate directory by running:
```
tendermint init
tendermint node
```
For more details on using `tendermint`, see [the guide](https://tendermint.com/docs/guides/using-tendermint).
# Keys and Genesis
In previous tutorials we used `basecoin init` to initialize `~/.basecoin` with the default configuration.
This command creates files both for Tendermint and for Basecoin, and a single `genesis.json` file for both of them.
For more information on these files, see the [guide to using tendermint](https://tendermint.com/docs/guides/using-tendermint).
Now let's make our own custom Basecoin data.
First, create a new directory:
```
mkdir example-data
```
We can tell `basecoin` to use this directory by exporting the `BCHOME` environment variable:
```
export BCHOME=$(pwd)/example-data
```
If you're going to be using multiple terminal windows, make sure to add this variable to your shell startup scripts (eg. `~/.bashrc`).
Now, let's create a new private key:
```
basecoin key new > $BCHOME/key.json
```
Here's what my `key.json looks like:
```json
{
"address": "4EGEhnqOw/gX326c7KARUkY1kic=",
"pub_key": {
"type": "ed25519",
"data": "a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
},
"priv_key": {
"type": "ed25519",
"data": "654c845f4b36d1a881deb0ff09381165d3ccd156b4aabb5b51267e91f1d024a5a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
}
}
```
Yours will look different - each key is randomly derrived.
Now we can make a `genesis.json` file and add an account with our public key:
```json
{
"chain_id": "example-chain",
"app_options": {
"accounts": [{
"pub_key": {
"type": "ed25519",
"data": "a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
},
"coins": [
{
"denom": "gold",
"amount": 1000000000
}
]
}]
}
}
```
Here we've granted ourselves `1000000000` units of the `gold` token.
Note that we've also set the `chain_id` to be `example-chain`.
All transactions must therefore include the `--chain_id example-chain` in order to make sure they are valid for this chain.
Previously, we didn't need this flag because we were using the default chain ID ("test_chain_id").
Now that we're using a custom chain, we need to specify the chain explicitly on the command line.
Note we have also left out the details of the tendermint genesis. These are documented in the [tendermint guide](https://tendermint.com/docs/guides/using-tendermint).
# Reset
You can reset all blockchain data by running:
```
basecoin unsafe_reset_all
```

View File

@ -1,9 +1,8 @@
## Deployment
Up until this point, we have only been testing the code as a stand-alone abci app,
which is nice for developing, but it is no blockchain. Just a blockchain-ready application.
Up until this point, we have only been testing the code as a blockchain with a single validator node running locally.
This is nice for developing, but it's not a real distributed application yet.
This section will demonstrate how to launch your basecoin-based application along
with a tendermint testnet and initialize the genesis block for fun and profit.
**TODO** Maybe we link to a blog post for this???
We do this using the [mintnet-kubernetes tool](https://github.com/tendermint/mintnet-kubernetes).

View File

@ -19,6 +19,8 @@ main.go
plugin.go
```
### main.go
The `main.go` is very simple and does not need to be changed:
```golang
@ -45,7 +47,7 @@ In addition, if we want to send transactions to our plugin,
we need to add a new command to the CLI.
This is where the `cmd.go` comes in.
## Commands
### cmd.go
First, we register the plugin:
@ -157,7 +159,7 @@ All plugin data must be serialized (ie. encoded as a byte-array)
and sent as data in an `AppTx`. The `commands.AppTx` function does this for us -
it creates an `AppTx` with the corresponding data, signs it, and sends it on to the blockchain.
## RunTx
### plugin.go
Ok, now we're ready to actually look at the implementation of the plugin in `plugin.go`.
Note I'll leave out some of the methods as they don't serve any purpose for this example,
@ -296,94 +298,42 @@ And that's it! Now that we have a simple plugin, let's see how to run it.
## Running your plugin
In the [previous tutorial](basecoin-basics.md),
we used a pre-generated `genesis.json` and `priv_validator.json` for the application.
This time, let's make our own.
First, let's create a new directory and change into it:
First, initialize the new blockchain with
```
mkdir example-data
cd example-data
basecoin init
```
Now, let's create a new private key:
If you've already run a basecoin blockchain, reset the data with
```
example-plugin key new > key.json
basecoin unsafe_reset_all
```
Here's what my `key.json looks like:
```json
{
"address": "15F591CA434CFCCBDEC1D206F3ED3EBA207BFE7D",
"priv_key": [
1,
"737C629667A9EAADBB8E7CF792D5A8F63AA4BB51E06457DDD7FDCC6D7412AAAD43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"
],
"pub_key": [
1,
"43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"
]
}
```
Now we can make a `genesis.json` file and add an account with out public key:
```json
[
"base/chainID", "example-chain",
"base/account", {
"pub_key": [1, "43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"],
"coins": [
{
"denom": "gold",
"amount": 1000000000,
}
]
}
]
```
Here we've granted ourselves `1000000000` units of the `gold` token.
Before we can start the blockchain, we must initialize and/or reset the Tendermint state for a new blockchain:
To start the blockchain with your new plugin, simply run
```
tendermint init
tendermint unsafe_reset_all
```
Great, now we're ready to go.
To start the blockchain, simply run
```
example-plugin start --in-proc
example-plugin start
```
In another window, we can try sending some transactions:
```
example-plugin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --amount 100gold --chain_id example-chain
example-plugin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 100mycoin
```
Note the `--chain_id` flag. In the [previous tutorial](basecoin-basics.md),
we didn't include it because we were using the default chain ID ("test_chain_id").
Now that we're using a custom chain, we need to specify the chain explicitly on the command line.
Ok, so that's how we can send a `SendTx` transaction using our `example-plugin` CLI,
but we were already able to do that with the `basecoin` CLI.
With our new CLI, however, we can also send an `ExamplePluginTx`:
```
example-plugin tx example --amount 1gold --chain_id example-chain
example-plugin tx example --amount 1mycoin
```
The transaction is invalid! That's because we didn't specify the `--valid` flag:
```
example-plugin tx example --valid --amount 1gold --chain_id example-chain
example-plugin tx example --valid --amount 1mycoin
```
Tada! We successfuly created, signed, broadcast, and processed our custom transaction type.
@ -403,13 +353,13 @@ which contains only an integer.
If we send another transaction, and then query again, we'll see the value increment:
```
example-plugin tx example --valid --amount 1gold --chain_id example-chain
example-plugin tx example --valid --amount 1mycoin
example-plugin query ExamplePlugin.State
```
Neat, right? Notice how the result of the query comes with a proof.
This is a Merkle proof that the state is what we say it is.
In a latter [tutorial on Interblockchain Communication](ibc.md),
In a latter [tutorial on InterBlockchain Communication](ibc.md),
we'll put this proof to work!
## Next Steps
@ -419,5 +369,5 @@ basecoin CLI to activate the plugin on the blockchain and to send transactions t
Hopefully by now you have some ideas for your own plugin, and feel comfortable implementing them.
In the [next tutorial](more-examples.md), we tour through some other plugin examples,
adding features for minting new coins, voting, and changin the Tendermint validator set.
adding features for minting new coins, voting, and changing the Tendermint validator set.
But first, you may want to learn a bit more about [the design of the plugin system](plugin-design.md)

View File

@ -194,15 +194,15 @@ The relevant data is now in the `data` directory.
We can start the two chains as follows:
```
TMROOT=./data/chain1/tendermint tendermint node &> chain1_tendermint.log &
basecoin start --dir ./data/chain1/basecoin &> chain1_basecoin.log &
TMROOT=./data/chain1 tendermint node &> chain1_tendermint.log &
BCHOME=./data/chain1 basecoin start --without-tendermint &> chain1_basecoin.log &
```
and
```
TMROOT=./data/chain2/tendermint tendermint node --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> chain2_tendermint.log &
basecoin start --address tcp://localhost:36658 --dir ./data/chain2/basecoin &> chain2_basecoin.log &
TMROOT=./data/chain2 tendermint node --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> chain2_tendermint.log &
BCHOME=./data/chain2 basecoin start --without-tendermint --address tcp://localhost:36658 &> chain2_basecoin.log &
```
Note how we refer to the relevant data directories. Also note how we have to set the various addresses for the second node so as not to conflict with the first.
@ -224,14 +224,16 @@ For the sake of convenience, let's first set some environment variables:
export CHAIN_ID1=test_chain_1
export CHAIN_ID2=test_chain_2
export CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/basecoin/key.json"
export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/key.json --node tcp://localhost:36657"
export CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/key.json"
export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/key.json --node tcp://localhost:36657"
export BCHOME="."
```
Let's start by registering `test_chain_1` on `test_chain_2`:
```
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
```
Now we can create the outgoing packet on `test_chain_1`:
@ -265,7 +267,7 @@ The former is used as input for later commands; the latter is human-readable, so
Let's send this updated information about `test_chain_1` to `test_chain_2`:
```
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 update --header 0x<header>--commit 0x<commit>
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 update --header 0x<header> --commit 0x<commit>
```
where `<header>` and `<commit>` are the hex-encoded header and commit returned by the previous `block` command.
@ -275,10 +277,10 @@ along with proof the packet was committed on `test_chain_1`. Since `test_chain_2
of `test_chain_1`, it will be able to verify the proof!
```
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height + 1> --packet 0x<packet> --proof 0x<proof>
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height> --packet 0x<packet> --proof 0x<proof>
```
Here, `<height + 1>` is one greater than the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
Here, `<height>` is the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
`value` and `proof` returned in that same query.
Tada!

View File

@ -8,16 +8,17 @@ go get -u github.com/tendermint/basecoin/cmd/basecoin
In some cases, if that fails, or if another branch is required,
we use `glide` for dependency management.
The correct way of compiling from source, assuming you've already
run `go get` or otherwise cloned the repo, is:
Thus, assuming you've already run `go get` or otherwise cloned the repo,
the correct way to install is:
```
cd $GOPATH/src/github.com/tendermint/basecoin
git checkout develop # (until we release v0.9)
make get_vendor_deps
make install
```
This will create the `basecoin` binary in `$GOPATH/bin`.
Note the `make get_vendor_deps` command will install `glide` and the correct version of all dependencies.
If you need another branch, make sure to run `git checkout <branch>` before the `make` commands.

View File

@ -1,19 +1,14 @@
# Plugin Examples
Now that we've seen [how to write a simple plugin](example-plugin.md)
and taken a look at [how the plugin system is designed](plugin-design.md),
Now that we've seen [how to write a simple plugin](/docs/guide/example-plugin.md)
and taken a look at [how the plugin system is designed](/docs/guide/plugin-design.md),
it's time for some more advanced examples.
For now, most examples are contained in the `github.com/tendermint/basecoin-examples` repository.
In particular, we have the following:
1. [Mintcoin][0] - a plugin for issuing new Basecoin tokens
2. [Trader][1] - a plugin for adding escrow and options features to Basecoin
3. [Stakecoin][2] - a plugin for bonding and unbonding Tendermint validators and updating the validator set accordingly
4. [PayToVote][3] - a plugin for creating issues and voting on them
5. [IBC][4] - a plugin for facilitating InterBlockchain Communication
[0]: https://github.com/tendermint/basecoin-examples/tree/develop/mintcoin
[1]: https://github.com/tendermint/basecoin-examples/tree/develop/trader
[2]: https://github.com/tendermint/basecoin-examples/tree/develop/stake
[3]: https://github.com/tendermint/basecoin-examples/tree/develop/paytovote
[4]: ibc.md
1. [Mintcoin](https://github.com/tendermint/basecoin-examples/tree/develop/mintcoin) - a plugin for issuing new Basecoin tokens
2. [Trader](https://github.com/tendermint/basecoin-examples/tree/develop/trader) - a plugin for adding escrow and options features to Basecoin
3. [Stakecoin](https://github.com/tendermint/basecoin-examples/tree/develop/stake) - a plugin for bonding and unbonding Tendermint validators and updating the validator set accordingly
4. [PayToVote](https://github.com/tendermint/basecoin-examples/tree/develop/paytovote) - a plugin for creating issues and voting on them
5. [IBC](/docs/guide/ibc.md) - a plugin for facilitating InterBlockchain Communication

33
glide.lock generated
View File

@ -1,34 +1,34 @@
hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348
updated: 2017-03-06T05:37:03.828355251-05:00
hash: c71c0d6c409bfddb4c4b471d8445f59cebd2cd41e1635a90d6facd81bd09a5e0
updated: 2017-03-14T17:02:44.512359631-04:00
imports:
- name: github.com/btcsuite/btcd
version: d06c0bb181529331be8f8d9350288c420d9e60e4
version: 583684b21bfbde9b5fc4403916fd7c807feb0289
subpackages:
- btcec
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
version: e643e9ef00b049d75de26e61109c5ea01885cd21
- name: github.com/ebuchman/fail-test
version: 13f91f14c826314205cdbed1ec8ac8bf08e03381
version: 95f809107225be108efcf10a3509e4ea6ceef3c4
- name: github.com/go-stack/stack
version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82
- name: github.com/golang/protobuf
version: 8ee79997227bf9b34611aee7946ae64735e6fd93
version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
subpackages:
- proto
- name: github.com/golang/snappy
version: d9eb7a3d35ec988b8585d4a0068e462c27d28380
version: 553a641470496b2327abcac10b36396bd98e45c9
- name: github.com/gorilla/websocket
version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
- name: github.com/jmhodges/levigo
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
- name: github.com/mattn/go-colorable
version: d228849504861217f796da67fae4f6e347643f15
version: a392f450ea64cee2b268dfaacdc2502b50a22b18
- name: github.com/mattn/go-isatty
version: 30a891c33c7cde7b02a981314b4228ec99380cca
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
- name: github.com/pkg/errors
version: 645ef00459ed84a119197bfb8d8205042c6df63d
version: bfd5150e4e41705ded2129ec33379de1cb90b513
- name: github.com/syndtr/goleveldb
version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65
version: 3c5717caf1475fd25964109a0fc640bd150fce43
subpackages:
- leveldb
- leveldb/cache
@ -43,7 +43,7 @@ imports:
- leveldb/table
- leveldb/util
- name: github.com/tendermint/abci
version: 1236e8fb6eee3a63909f4014a8e84385ead7933d
version: af792eac777de757cd496349a5f6b5313738fcbc
subpackages:
- client
- example/dummy
@ -117,7 +117,7 @@ imports:
- name: github.com/urfave/cli
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
- name: golang.org/x/crypto
version: 7c6cc321c680f03b9ef0764448e780704f486b51
version: 728b753d0135da6801d45a38e6f43ff55779c5c2
subpackages:
- curve25519
- nacl/box
@ -128,7 +128,7 @@ imports:
- ripemd160
- salsa20/salsa
- name: golang.org/x/net
version: 61557ac0112b576429a0df080e1c2cef5dfbb642
version: a6577fac2d73be281a500b310739095313165611
subpackages:
- context
- http2
@ -138,16 +138,17 @@ imports:
- lex/httplex
- trace
- name: golang.org/x/sys
version: d75a52659825e75fff6158388dddc6a5b04f9ba5
version: 99f16d856c9836c42d24e7ab64ea72916925fa97
subpackages:
- unix
- name: google.golang.org/grpc
version: cbcceb2942a489498cf22b2f918536e819d33f0a
version: 0713829b980f4ddd276689a36235c5fcc82a21bf
subpackages:
- codes
- credentials
- grpclog
- internal
- keepalive
- metadata
- naming
- peer

View File

@ -1,22 +1,22 @@
package: github.com/tendermint/basecoin
import:
- package: github.com/tendermint/go-common
version: develop
version: master
- package: github.com/tendermint/go-crypto
version: develop
version: master
- package: github.com/tendermint/go-events
version: develop
version: master
- package: github.com/tendermint/go-logger
version: develop
version: master
- package: github.com/tendermint/go-rpc
version: develop
version: master
- package: github.com/tendermint/go-wire
version: develop
version: master
- package: github.com/tendermint/merkleeyes
version: develop
version: master
- package: github.com/tendermint/tendermint
version: develop
version: master
- package: github.com/tendermint/abci
version: develop
version: master
- package: github.com/gorilla/websocket
version: v1.1.0

View File

@ -20,7 +20,7 @@ func TestCounterPlugin(t *testing.T) {
eyesCli := eyescli.NewLocalClient("", 0)
chainID := "test_chain_id"
bcApp := app.NewBasecoin(eyesCli)
bcApp.SetOption("base/chainID", chainID)
bcApp.SetOption("base/chain_id", chainID)
// t.Log(bcApp.Info())
// Add Counter plugin

View File

@ -28,12 +28,14 @@ func NewState(store types.KVStore) *State {
func (s *State) SetChainID(chainID string) {
s.chainID = chainID
s.store.Set([]byte("base/chain_id"), []byte(chainID))
}
func (s *State) GetChainID() string {
if s.chainID == "" {
PanicSanity("Expected to have set SetChainID")
if s.chainID != "" {
return s.chainID
}
s.chainID = string(s.store.Get([]byte("base/chain_id")))
return s.chainID
}

View File

@ -18,7 +18,7 @@ func TestSendTx(t *testing.T) {
eyesCli := eyescli.NewLocalClient("", 0)
chainID := "test_chain_id"
bcApp := app.NewBasecoin(eyesCli)
bcApp.SetOption("base/chainID", chainID)
bcApp.SetOption("base/chain_id", chainID)
// t.Log(bcApp.Info())
test1PrivAcc := types.PrivAccountFromSecret("test1")
@ -64,7 +64,7 @@ func TestSequence(t *testing.T) {
eyesCli := eyescli.NewLocalClient("", 0)
chainID := "test_chain_id"
bcApp := app.NewBasecoin(eyesCli)
bcApp.SetOption("base/chainID", chainID)
bcApp.SetOption("base/chain_id", chainID)
// t.Log(bcApp.Info())
// Get the test account

View File

@ -152,7 +152,7 @@ func (tx *SendTx) SignBytes(chainID string) []byte {
signBytes := wire.BinaryBytes(chainID)
sigz := make([]crypto.Signature, len(tx.Inputs))
for i, input := range tx.Inputs {
sigz[i] = input.Signature
sigz[i] = input.Signature.Signature
tx.Inputs[i].Signature.Signature = nil
}
signBytes = append(signBytes, wire.BinaryBytes(tx)...)

View File

@ -1,7 +1,7 @@
package version
const Maj = "0"
const Min = "2"
const Min = "3"
const Fix = "0"
const Version = Maj + "." + Min + "." + Fix