diff --git a/abci/example/orderbook/app.go b/abci/example/orderbook/app.go index 5678bfa08..9b22929cf 100644 --- a/abci/example/orderbook/app.go +++ b/abci/example/orderbook/app.go @@ -7,6 +7,7 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" ) var _ types.Application = (*StateMachine)(nil) @@ -21,6 +22,7 @@ const ( ErrValidateBasic ErrNoAccount ErrNoPair + ErrInvalidSignature ) type StateMachine struct { @@ -83,7 +85,8 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx } // check if account exists - if _, ok := sm.accounts[m.MsgBid.BidOrder.OwnerId]; !ok { + account, ok := sm.accounts[m.MsgBid.BidOrder.OwnerId] + if !ok { return types.ResponseCheckTx{Code: ErrNoAccount} } @@ -92,6 +95,11 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx return types.ResponseCheckTx{Code: ErrNoPair} } + // verify signature + if !m.MsgBid.BidOrder.ValidateSignature(ed25519.PubKey(account.PublicKey), m.MsgBid.Pair) { + return types.ResponseCheckTx{Code: ErrInvalidSignature} + } + case *Msg_MsgAsk: if err := m.MsgAsk.ValidateBasic(); err != nil { @@ -99,7 +107,7 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx } // check if account exists - _, ok := sm.accounts[m.MsgAsk.AskOrder.OwnerId] + account, ok := sm.accounts[m.MsgAsk.AskOrder.OwnerId] if !ok { return types.ResponseCheckTx{Code: ErrNoAccount} } @@ -109,6 +117,11 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx return types.ResponseCheckTx{Code: ErrNoPair} } + // verify signature + if !m.MsgAsk.AskOrder.ValidateSignature(ed25519.PubKey(account.PublicKey), m.MsgAsk.Pair) { + return types.ResponseCheckTx{Code: ErrInvalidSignature} + } + default: return types.ResponseCheckTx{Code: ErrUnknownMessage} // unknown message type } @@ -267,8 +280,6 @@ func (sm *StateMachine) ProcessProposal(req types.RequestProcessProposal) types. return rejectProposal() } - // TODO: verify the signature - case *Msg_MsgAsk, *Msg_MsgBid: // MsgAsk and MsgBid are not allowed individually - they need to be matched as a TradeSet return rejectProposal() @@ -282,8 +293,6 @@ func (sm *StateMachine) ProcessProposal(req types.RequestProcessProposal) types. return rejectProposal() } - // TODO: verify the signature - case *Msg_MsgTradeSet: // for each matched order // check the accounts exist, that the signatures are valid and that they have the available funds to make the swap @@ -297,14 +306,20 @@ func (sm *StateMachine) ProcessProposal(req types.RequestProcessProposal) types. } for _, order := range m.MsgTradeSet.TradeSet.MatchedOrders { + // validate matched order i.e. users have funds if !sm.isMatchedOrderValid(order, m.MsgTradeSet.TradeSet.Pair) { return rejectProposal() } - // bidOwner := sm.accounts[order.OrderBid.OwnerId] - // askOwner := sm.accounts[order.OrderAsk.OwnerId] - - // ed25519.Verify(bidOwner.PublicKey, ) + // verify signatures + bidOwner := sm.accounts[order.OrderBid.OwnerId] + askOwner := sm.accounts[order.OrderAsk.OwnerId] + if !order.OrderAsk.ValidateSignature(ed25519.PubKey(askOwner.PublicKey), m.MsgTradeSet.TradeSet.Pair) { + return rejectProposal() + } + if !order.OrderBid.ValidateSignature(ed25519.PubKey(bidOwner.PublicKey), m.MsgTradeSet.TradeSet.Pair) { + return rejectProposal() + } } default: diff --git a/abci/example/orderbook/app_test.go b/abci/example/orderbook/app_test.go index 4e2dd4ba2..83017dd68 100644 --- a/abci/example/orderbook/app_test.go +++ b/abci/example/orderbook/app_test.go @@ -27,7 +27,7 @@ func TestCheckTx(t *testing.T) { { name: "test msg ask", msg: &orderbook.Msg{Sum: &orderbook.Msg_MsgAsk{MsgAsk: &orderbook.MsgAsk{ - Pair: testPair, + Pair: &testPair, AskOrder: &orderbook.OrderAsk{ Quantity: 10, AskPrice: 1, @@ -40,21 +40,21 @@ func TestCheckTx(t *testing.T) { { name: "test msg bid", msg: &orderbook.Msg{Sum: &orderbook.Msg_MsgBid{MsgBid: &orderbook.MsgBid{ - Pair: testPair, - OrderBid: &orderbook.OrderBid{ + Pair: &testPair, + BidOrder: &orderbook.OrderBid{ MaxQuantity: 15, MaxPrice: 5, OwnerId: 1, Signature: []byte("signature"), }, - }}, + }}}, responseCode: orderbook.StatusOK, }, { name: "test msg register pair", msg: &orderbook.Msg{Sum: &orderbook.Msg_MsgRegisterPair{MsgRegisterPair: &orderbook.MsgRegisterPair{ - Pair: testPair, - }}, + Pair: &testPair, + }}}, responseCode: orderbook.StatusOK, }, }