Merge pull request #36 from tendermint/fix-ibc

Fix ibc
This commit is contained in:
Ethan Buchman 2017-02-21 16:56:16 -05:00 committed by GitHub
commit 8a59315d59
13 changed files with 106 additions and 71 deletions

View File

@ -51,14 +51,15 @@ func (app *Basecoin) RegisterPlugin(plugin types.Plugin) {
}
// ABCI::SetOption
func (app *Basecoin) SetOption(key string, value string) (log string) {
PluginName, key := splitKey(key)
if PluginName != PluginNameBase {
func (app *Basecoin) SetOption(key string, value string) string {
pluginName, key := splitKey(key)
if pluginName != PluginNameBase {
// Set option on plugin
plugin := app.plugins.GetByName(PluginName)
plugin := app.plugins.GetByName(pluginName)
if plugin == nil {
return "Invalid plugin name: " + PluginName
return "Invalid plugin name: " + pluginName
}
log.Info("SetOption on plugin", "plugin", pluginName, "key", key, "value", value)
return plugin.SetOption(app.state, key, value)
} else {
// Set option on basecoin
@ -74,6 +75,7 @@ func (app *Basecoin) SetOption(key string, value string) (log string) {
return "Error decoding acc message: " + err.Error()
}
app.state.SetAccount(acc.PubKey.Address(), acc)
log.Info("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
return "Success"
}
return "Unrecognized option key " + key
@ -194,9 +196,3 @@ func splitKey(key string) (prefix string, suffix string) {
}
return key, ""
}
// (not meant to be called)
// assert that Basecoin implements `abci.Application` at compile-time
func _assertABCIApplication(basecoin *Basecoin) abci.Application {
return basecoin
}

View File

@ -17,7 +17,7 @@ func (app *Basecoin) LoadGenesis(path string) error {
for _, kv := range kvz {
log := app.SetOption(kv.Key, kv.Value)
// TODO: remove debug output
fmt.Printf("Set %v=%v. Log: %v", kv.Key, kv.Value, log)
fmt.Printf("Set %v=%v. Log: %v\n", kv.Key, kv.Value, log)
}
return nil
}

7
app/log.go Normal file
View File

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

View File

@ -17,8 +17,8 @@ func main() {
commands.TxCmd,
commands.QueryCmd,
commands.KeyCmd,
commands.VerifyCmd, // TODO: move to merkleeyes?
commands.BlockCmd, // TODO: move to adam?
commands.VerifyCmd,
commands.BlockCmd,
commands.AccountCmd,
}
app.Run(os.Args)

View File

@ -9,7 +9,6 @@ import (
"github.com/urfave/cli"
"github.com/tendermint/basecoin/plugins/ibc"
"github.com/tendermint/basecoin/types"
cmn "github.com/tendermint/go-common"
"github.com/tendermint/go-merkle"
@ -17,10 +16,9 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
// Register the IBC plugin at start and for transactions
func RegisterIBC() {
RegisterTxSubcommand(IbcCmd)
RegisterStartPlugin("ibc", func() types.Plugin { return ibc.New() })
// returns a new IBC plugin to be registered with Basecoin
func NewIBCPlugin() *ibc.IBCPlugin {
return ibc.New()
}
//---------------------------------------------------------------------
@ -104,9 +102,9 @@ var (
// ibc commands
var (
IbcCmd = cli.Command{
IbcTxCmd = cli.Command{
Name: "ibc",
Usage: "Send a transaction to the interblockchain (ibc) plugin",
Usage: "an IBC transaction, for InterBlockchain Communication",
Flags: TxFlags,
Subcommands: []cli.Command{
IbcRegisterTxCmd,

View File

@ -138,11 +138,7 @@ func cmdBlock(c *cli.Context) error {
return errors.New(cmn.Fmt("Height must be an int, got %v: %v", heightString, err))
}
/*block, err := getBlock(c, height)
if err != nil {
return err
}*/
nextBlock, err := getBlock(c, height+1)
header, commit, err := getHeaderAndCommit(c, height)
if err != nil {
return err
}
@ -152,12 +148,12 @@ func cmdBlock(c *cli.Context) error {
JSON BlockJSON `json:"json"`
}{
BlockHex{
Header: wire.BinaryBytes(nextBlock.Header),
Commit: wire.BinaryBytes(nextBlock.LastCommit),
Header: wire.BinaryBytes(header),
Commit: wire.BinaryBytes(commit),
},
BlockJSON{
Header: nextBlock.Header,
Commit: nextBlock.LastCommit,
Header: header,
Commit: commit,
},
})))

View File

@ -72,7 +72,10 @@ func cmdStart(c *cli.Context) error {
// Create Basecoin app
basecoinApp := app.NewBasecoin(eyesCli)
// register all plugins
// register IBC plugn
basecoinApp.RegisterPlugin(NewIBCPlugin())
// register all other plugins
for _, p := range plugins {
basecoinApp.RegisterPlugin(p.newPlugin())
}
@ -91,7 +94,9 @@ func cmdStart(c *cli.Context) error {
if c.Bool("in-proc") {
startTendermint(c, basecoinApp)
} else {
startBasecoinABCI(c, basecoinApp)
if err := startBasecoinABCI(c, basecoinApp); err != nil {
return err
}
}
return nil

View File

@ -36,12 +36,13 @@ var (
Subcommands: []cli.Command{
SendTxCmd,
AppTxCmd,
IbcTxCmd,
},
}
SendTxCmd = cli.Command{
Name: "send",
Usage: "Create, sign, and broadcast a SendTx transaction",
Usage: "a SendTx transaction, for sending tokens around",
ArgsUsage: "",
Action: func(c *cli.Context) error {
return cmdSendTx(c)
@ -51,7 +52,7 @@ var (
AppTxCmd = cli.Command{
Name: "app",
Usage: "Create, sign, and broadcast a raw AppTx transaction",
Usage: "an AppTx transaction, for sending raw data to plugins",
ArgsUsage: "",
Action: func(c *cli.Context) error {
return cmdAppTx(c)

View File

@ -122,15 +122,19 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) {
return acc, nil
}
func getBlock(c *cli.Context, height int) (*tmtypes.Block, error) {
func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) {
tmResult := new(ctypes.TMResult)
tmAddr := c.String("node")
clientURI := client.NewClientURI(tmAddr)
_, err := clientURI.Call("block", map[string]interface{}{"height": height}, tmResult)
method := "commit"
_, err := clientURI.Call(method, map[string]interface{}{"height": height}, tmResult)
if err != nil {
return nil, errors.New(cmn.Fmt("Error on broadcast tx: %v", err))
return nil, nil, errors.New(cmn.Fmt("Error on %s: %v", method, err))
}
res := (*tmResult).(*ctypes.ResultBlock)
return res.Block, nil
resCommit := (*tmResult).(*ctypes.ResultCommit)
header := resCommit.Header
commit := resCommit.Commit
return header, commit, nil
}

View File

@ -9,6 +9,32 @@ function removeQuotes() {
echo "$temp"
}
function waitForNode() {
addr=$1
set +e
curl -s $addr/status > /dev/null
ERR=$?
while [ "$ERR" != 0 ]; do
sleep 1
curl -s $addr/status > /dev/null
ERR=$?
done
set -e
echo "... node $addr is up"
}
function waitForBlock() {
addr=$1
b1=`curl -s $addr/status | jq .result[1].latest_block_height`
b2=$b1
while [ "$b2" == "$b1" ]; do
echo "Waiting for node $addr to commit a block ..."
sleep 1
b2=`curl -s $addr/status | jq .result[1].latest_block_height`
done
}
# grab the chain ids
CHAIN_ID1=$(cat ./data/chain1/basecoin/genesis.json | jq .[1])
CHAIN_ID1=$(removeQuotes $CHAIN_ID1)
@ -35,7 +61,9 @@ basecoin start --address tcp://localhost:36658 --dir ./data/chain2/basecoin &> c
echo ""
echo "... waiting for chains to start"
echo ""
sleep 10
waitForNode localhost:46657
waitForNode localhost:36657
echo "... registering chain1 on chain2"
echo ""
@ -66,10 +94,14 @@ echo "PACKET: $PACKET"
echo "PROOF: $PROOF"
# the query returns the height of the next block, which contains the app hash
# but which may not be committed yet, so we have to wait for it to query the commit
echo ""
echo "... waiting for some blocks to be mined"
echo "... waiting for a block to be committed"
echo ""
sleep 5
waitForBlock localhost:46657
waitForBlock localhost:36657
echo ""
echo "... querying for block data"
@ -95,12 +127,12 @@ echo ""
echo "... posting packet from chain1 on chain2"
echo ""
# post the packet from chain1 to chain2
basecoin tx ibc --amount 10 $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height $((HEIGHT + 1)) --packet 0x$PACKET --proof 0x$PROOF
basecoin tx ibc --amount 10 $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF
echo ""
echo "... checking if the packet is present on chain2"
echo ""
# query for the packet on chain2 !
# query for the packet on chain2
basecoin query --node tcp://localhost:36657 ibc,ingress,test_chain_2,test_chain_1,1
echo ""

23
glide.lock generated
View File

@ -1,12 +1,10 @@
hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348
updated: 2017-02-17T13:24:05.234809983+01:00
updated: 2017-02-17T09:41:20.209551862-05:00
imports:
- name: github.com/btcsuite/btcd
version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8
version: d06c0bb181529331be8f8d9350288c420d9e60e4
subpackages:
- btcec
- name: github.com/btcsuite/fastsha256
version: 637e656429416087660c84436a2a035d69d54e2e
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/ebuchman/fail-test
@ -18,7 +16,7 @@ imports:
subpackages:
- proto
- name: github.com/golang/snappy
version: 7db9049039a047d955fe8c19b83c8ff5abd765c7
version: 553a641470496b2327abcac10b36396bd98e45c9
- name: github.com/gorilla/websocket
version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
- name: github.com/jmhodges/levigo
@ -26,7 +24,7 @@ imports:
- name: github.com/mattn/go-colorable
version: 5411d3eea5978e6cdc258b30de592b60df6aba96
- name: github.com/mattn/go-isatty
version: 281032e84ae07510239465db46bf442aa44b953a
version: dda3de49cbfcec471bd7a70e6cc01fcc3ff90109
- name: github.com/pkg/errors
version: 248dadf4e9068a0b3e79f02ed0a610d935de5302
- name: github.com/syndtr/goleveldb
@ -115,7 +113,7 @@ imports:
- types
- version
- name: github.com/urfave/cli
version: 347a9884a87374d000eec7e6445a34487c1f4a2b
version: 2526b57c56f30b50466c96c4133b1a4ad0f0191f
- name: golang.org/x/crypto
version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8
subpackages:
@ -128,7 +126,7 @@ imports:
- ripemd160
- salsa20/salsa
- name: golang.org/x/net
version: 61557ac0112b576429a0df080e1c2cef5dfbb642
version: b4690f45fa1cafc47b1c280c2e75116efe40cc13
subpackages:
- context
- http2
@ -138,11 +136,11 @@ imports:
- lex/httplex
- trace
- name: golang.org/x/sys
version: e24f485414aeafb646f6fca458b0bf869c0880a1
version: 075e574b89e4c2d22f2286a7e2b919519c6f3547
subpackages:
- unix
- name: google.golang.org/grpc
version: cbcceb2942a489498cf22b2f918536e819d33f0a
version: d0c32ee6a441117d49856d6120ca9552af413ee0
subpackages:
- codes
- credentials
@ -156,14 +154,15 @@ imports:
- transport
testImports:
- name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
version: 346938d642f2ec3594ed81d874461961cd0faa76
subpackages:
- spew
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
version: 792786c7400a136282c1664665ae0a8db921c6c2
subpackages:
- difflib
- name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages:
- assert
- require

View File

@ -1,6 +1,7 @@
package ibc
import (
"bytes"
"errors"
"net/url"
"strings"
@ -329,6 +330,7 @@ func (sm *IBCStateMachine) runPacketPostTx(tx IBCPacketPostTx) {
save(sm.store, packetKeyIngress, packet)
// Load Header and make sure it exists
// If it exists, we already checked a valid commit for it in UpdateChainTx
var header tm.Header
exists, err := load(sm.store, headerKey, &header)
if err != nil {
@ -341,16 +343,6 @@ func (sm *IBCStateMachine) runPacketPostTx(tx IBCPacketPostTx) {
return
}
/*
// Read Proof
var proof *merkle.IAVLProof
err = wire.ReadBinaryBytes(tx.Proof, &proof)
if err != nil {
sm.res.Code = IBCEncodingError
sm.res.Log = cmn.Fmt("Reading Proof: %v", err.Error())
return
}
*/
proof := tx.Proof
if proof == nil {
sm.res.Code = IBCCodeInvalidProof
@ -368,7 +360,6 @@ func (sm *IBCStateMachine) runPacketPostTx(tx IBCPacketPostTx) {
}
return
}
func (ibc *IBCPlugin) InitChain(store types.KVStore, vals []*abci.Validator) {
@ -432,6 +423,7 @@ func verifyCommit(chainState BlockchainState, header *tm.Header, commit *tm.Comm
if chainState.ChainID != header.ChainID {
return errors.New(cmn.Fmt("Expected header.ChainID %v, got %v", chainState.ChainID, header.ChainID))
}
// Ensure things aren't empty
if len(chainState.Validators) == 0 {
return errors.New(cmn.Fmt("Blockchain has no validators")) // NOTE: Why would this happen?
}
@ -439,18 +431,23 @@ func verifyCommit(chainState BlockchainState, header *tm.Header, commit *tm.Comm
return errors.New(cmn.Fmt("Commit has no signatures"))
}
chainID := chainState.ChainID
vote0 := commit.Precommits[0]
vals := chainState.Validators
valSet := tm.NewValidatorSet(vals)
blockID := commit.Precommits[0].BlockID // XXX: incorrect
// NOTE: Currently this only works with the exact same validator set.
// Not this, but perhaps "ValidatorSet.VerifyCommitAny" should expose
// the functionality to verify commits even after validator changes.
err := valSet.VerifyCommit(chainID, vote0.BlockID, vote0.Height, commit)
err := valSet.VerifyCommit(chainID, blockID, header.Height, commit)
if err != nil {
return err
}
// Ensure the committed blockID matches the header
if !bytes.Equal(header.Hash(), blockID.Hash) {
return errors.New(cmn.Fmt("blockID.Hash (%X) does not match header.Hash (%X)", blockID.Hash, header.Hash()))
}
// All ok!
return nil
}

View File

@ -95,7 +95,7 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
}
if !tx.Input.Coins.IsGTE(types.Coins{tx.Fee}) {
log.Info(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
return abci.ErrBaseInsufficientFunds
return abci.ErrBaseInsufficientFunds.AppendLog(Fmt("input coins is %d, but fee is %d", tx.Input.Coins, types.Coins{tx.Fee}))
}
// Validate call address
@ -238,7 +238,7 @@ func validateInputAdvanced(acc *types.Account, signBytes []byte, in types.TxInpu
}
// Check amount
if !balance.IsGTE(in.Coins) {
return abci.ErrBaseInsufficientFunds
return abci.ErrBaseInsufficientFunds.AppendLog(Fmt("balance is %d, tried to send %d", balance, in.Coins))
}
// Check signatures
if !acc.PubKey.VerifyBytes(signBytes, in.Signature) {