Prepare and process proposal excecution

This commit is contained in:
Sam Ricotta
2022-10-28 16:20:59 +02:00
parent b8162782c3
commit 1f6a6176c0
8 changed files with 349 additions and 140 deletions
+158 -68
View File
@@ -20,12 +20,13 @@ type StateMachine struct {
db dbm.DB
// in-memory state
accounts map[uint64]*Account
accounts map[uint64]*Account
// ephemeral state (not used for the app hash) but for
// convienience
pairs map[string]struct{} // lookup pairs
commodity map[string]struct{} // lookup commodities
pairs map[string]struct{} // lookup pairs
commodities map[string]struct{} // lookup commodities
publicKeys map[string]struct{} // lookup existence of an account
// app-side mempool (also emphemeral)
markets map[string]*Market // i.e. ATOM/USDC
@@ -51,15 +52,14 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx
// validations for each msg below
switch m := msg.Sum.(type) {
case *Msg_MsgRegisterPair:
// mustnt already have the same pair (also the reverse pairing)
// inbound can also be outbound for pair
if err := m.MsgRegisterPair.ValidateBasic(); err != nil {
return types.ResponseCheckTx{Code: 3}
}
case *Msg_MsgCreateAccount:
if m.MsgCreateAccount.ValidateBasic(); err != nil {
if err := m.MsgCreateAccount.ValidateBasic(); err != nil {
return types.ResponseCheckTx{Code: 3}
}
//check there is no other account with the same public key
case *Msg_MsgBid:
@@ -77,8 +77,6 @@ func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx
return types.ResponseCheckTx{Code: 4}
}
// check that the account has enough funds to support the bid (quantity * max_price)
case *Msg_MsgAsk:
if err := m.MsgAsk.ValidateBasic(); err != nil {
@@ -142,12 +140,9 @@ func (sm *StateMachine) BeginBlock(req types.RequestBeginBlock) types.ResponseBe
func (sm *StateMachine) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
tradeSet := new(TradeSet)
if err := proto.Unmarshal(req.Tx, tradeSet); err != nil {
panic(fmt.Sprintf("unmarshalling tx: %w", err))
panic(fmt.Sprintf("unmarshalling tx: %v", err))
}
return types.ResponseDeliverTx{Code: 0}
}
@@ -172,82 +167,177 @@ func (sm *StateMachine) ApplySnapshotChunk(req types.RequestApplySnapshotChunk)
}
func (sm *StateMachine) PrepareProposal(req types.RequestPrepareProposal) types.ResponsePrepareProposal {
// declare transaction with the size of 0
txs := make([][]byte, 0)
// fetch and match all the bids and asks for each market
for _, market := range sm.markets {
TradeSet := market.Match();
tradeSet := market.Match()
// tradesets into bytes and bytes into a transaction
if TradeSet == nil {
if tradeSet == nil {
continue
}
bz, err := proto.Marshal(TradeSet)
tradeSet = sm.validateTradeSetAgainstState(tradeSet)
if tradeSet == nil || len(tradeSet.MatchedOrders) == 0 {
continue
}
// wrap this as a message typ
msgTradeSet := &MsgTradeSet{TradeSet: tradeSet}
bz, err := proto.Marshal(msgTradeSet)
if err != nil {
return err
panic(err)
}
// check to see that we don't over populate the block
if len(txs)+len(bz) > int(req.MaxTxBytes) {
return types.ResponsePrepareProposal{Txs: txs}
}
txs = append(txs, bz)
}
for _, tx := range req.Txs {
var msg = new(Msg)
err := proto.Unmarshal(tx, msg)
if err != nil {
panic(err)
}
switch m := msg.Sum.(type) {
case *Msg_MsgRegisterPair:
// run the validation checks to see if duplicates within the pairs
pair := m.MsgRegisterPair.Pair
if _, ok := sm.pairs[pair.String()]; ok {
// this pair already exists so we skip over the message
// garbage collection should pick it up
continue
}
reversePair := &Pair{BuyersDenomination: pair.SellersDenomination, SellersDenomination: pair.BuyersDenomination}
if _, ok := sm.pairs[reversePair.String()]; ok {
// the reverse pair already exists so we skip over it
continue
}
// check to see that we don't over populate the block
if len(txs)+len(tx) > int(req.MaxTxBytes) {
return types.ResponsePrepareProposal{Txs: txs}
}
txs = append(txs, tx)
case *Msg_MsgCreateAccount:
// check for duplicate accounts in sm
if _, ok := sm.publicKeys[string(m.MsgCreateAccount.PublicKey)]; ok {
continue
}
// check to see that we don't over populate the block
if len(txs)+len(tx) > int(req.MaxTxBytes) {
return types.ResponsePrepareProposal{Txs: txs}
}
txs = append(txs, tx)
case *Msg_MsgAsk, *Msg_MsgBid:
// Already have these in the market and are paring together so not necessary to include here
default:
panic(fmt.Sprintf("unknown msg type in prepare proposal %T", m))
}
}
// pull in for every single pair
// does the buyer and seller have sufficient funds
for _, matchedOrder := range tradeSet.MatchedOrders {
bidOwner := sm.accounts[matchedOrder.OrderBid.OwnerId]
askOwner := sm.accounts[matchedOrder.OrderAsk.OwnerId]
askCommodities := askOwner.Commodities[tradeSet.Pairs.SellersDenomination]
buyCommodities := askOwner.Commodities[tradeSet.Pairs.BuyersDenomination]
// if bidowner commodities quantity - askowner commodities quantity != 0 then continue
if bidOwner.Commodities[askCommodities.String()]
}
// // validate the trade:
//
// // add it to the set of txs
// }
//
// }
// loop through the transactions provided by tendermint and look out for register pair and create account.
// those should still be added.
return types.ResponsePrepareProposal{Txs: req.Txs}
}
// Validate matched order
// Process Proposal either rejects or accepts transactions
func (sm *StateMachine) ProcessProposal(req types.RequestProcessProposal) types.ResponseProcessProposal {
var msg = new(Msg)
for _, tx := range req.Txs {
var msg = new(Msg)
err := proto.Unmarshal(tx, msg)
if err != nil {
panic(err)
}
err := proto.Unmarshal(req.Txs[], msg)
if err != nil {
return types.ResponseCheckTx{Code: 1} // decoding error
switch m := msg.Sum.(type) {
case *Msg_MsgRegisterPair:
if err := m.MsgRegisterPair.ValidateBasic(); err != nil {
return rejectProposal()
}
pair := m.MsgRegisterPair.Pair
if _, ok := sm.pairs[pair.String()]; ok {
return rejectProposal()
}
reversePair := &Pair{BuyersDenomination: pair.SellersDenomination, SellersDenomination: pair.BuyersDenomination}
if _, ok := sm.pairs[reversePair.String()]; ok {
return rejectProposal()
}
case *Msg_MsgAsk, *Msg_MsgBid:
return rejectProposal()
case *Msg_MsgCreateAccount:
if err := m.MsgCreateAccount.ValidateBasic(); err != nil {
return rejectProposal()
}
// check for duplicate accounts in sm
if _, ok := sm.publicKeys[string(m.MsgCreateAccount.PublicKey)]; ok {
return rejectProposal()
}
case *Msg_MsgTradeSet:
if err := m.MsgTradeSet.TradeSet.ValidateBasic(); err != nil {
return rejectProposal()
}
// for each matched order
// check the accounts exist, that the signatures are valid and that they have the available funds to make the swap
default:
return rejectProposal()
}
}
// check if there is more than one account
if ok := len(sm.accounts) >= 1; !ok {
return types.ResponseProcessProposal{Code: 4}
}
return acceptProposal()
}
func (sm *StateMachine) validateTradeSetAgainstState(tradeSet *TradeSet) *TradeSet {
output := &TradeSet{Pair: tradeSet.Pair}
for _, matchedOrder := range tradeSet.MatchedOrders {
bidOwner := sm.accounts[matchedOrder.OrderBid.OwnerId]
askOwner := sm.accounts[matchedOrder.OrderAsk.OwnerId]
askCommodities := askOwner.FindCommidity(tradeSet.Pair.SellersDenomination)
if askCommodities == nil {
continue
}
buyCommodities := bidOwner.FindCommidity(tradeSet.Pair.BuyersDenomination)
if buyCommodities == nil {
continue
}
// Seller has enough of the commodity
if askCommodities.Quantity-matchedOrder.OrderAsk.Quantity < 0 {
continue
}
// Buyer has enough of the buying commodity
if buyCommodities.Quantity-(matchedOrder.OrderAsk.AskPrice*matchedOrder.OrderAsk.Quantity) < 0 {
continue
}
// check if there is more than one commodity
if ok := len(sm.commodities) >= 1; !ok {
return types.ResponseProcessProposal{Code: 4}
// yayy! this matched order is still valid and can be executed
output.MatchedOrders = append(output.MatchedOrders, matchedOrder)
}
// check if there is more than one pair
if ok := len(sm.pairs) >= 1; !ok {
return types.ResponseProcessProposal{Code: 4}
}
return output
}
// check if there is a market
if ok := len(sm.markets) >= 1; !ok {
return types.ResponseProcessProposal{Code: 4}
}
func rejectProposal() types.ResponseProcessProposal {
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}
}
return types.ResponseProcessProposal{
Status: types.ResponseProcessProposal_ACCEPT}
func acceptProposal() types.ResponseProcessProposal {
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}
}
+16
View File
@@ -0,0 +1,16 @@
package orderbook_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/abci/example/orderbook"
)
func TestPrepareProposal(t *testing.T) {
// check to see if the market collected all of the pairs
market := orderbook.NewMarket(testPair)
require.EqualValues(t, )
}
+13 -14
View File
@@ -72,7 +72,6 @@ func TestSimpleOrderMatching(t *testing.T) {
ask: testAsk(40, 10),
match: true,
},
}
for idx, tc := range testcases {
@@ -90,10 +89,10 @@ func TestSimpleOrderMatching(t *testing.T) {
func TestMultiOrderMatching(t *testing.T) {
testcases := []struct {
bids []*orderbook.OrderBid
asks []*orderbook.OrderAsk
expected []*orderbook.MatchedOrder
expectedLowestAsk float64
bids []*orderbook.OrderBid
asks []*orderbook.OrderAsk
expected []*orderbook.MatchedOrder
expectedLowestAsk float64
expectedHighestBid float64
}{
{
@@ -115,8 +114,8 @@ func TestMultiOrderMatching(t *testing.T) {
OrderAsk: testAsk(30, 15),
OrderBid: testBid(50, 20),
},
},
expectedLowestAsk: 0,
},
expectedLowestAsk: 0,
expectedHighestBid: 40,
},
{
@@ -134,8 +133,8 @@ func TestMultiOrderMatching(t *testing.T) {
OrderAsk: testAsk(60, 15),
OrderBid: testBid(60, 20),
},
},
expectedLowestAsk: 50,
},
expectedLowestAsk: 50,
expectedHighestBid: 80,
},
{
@@ -143,9 +142,9 @@ func TestMultiOrderMatching(t *testing.T) {
testBid(60, 20),
testBid(80, 5),
},
asks: []*orderbook.OrderAsk{},
expected: []*orderbook.MatchedOrder{},
expectedLowestAsk: 0,
asks: []*orderbook.OrderAsk{},
expected: []*orderbook.MatchedOrder{},
expectedLowestAsk: 0,
expectedHighestBid: 80,
},
{
@@ -154,8 +153,8 @@ func TestMultiOrderMatching(t *testing.T) {
testAsk(70, 10),
testAsk(50, 20),
},
expected: []*orderbook.MatchedOrder{},
expectedLowestAsk: 50,
expected: []*orderbook.MatchedOrder{},
expectedLowestAsk: 50,
expectedHighestBid: 0,
},
}
+138 -51
View File
@@ -135,7 +135,7 @@ type MsgCreateAccount struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PublicKey [][]byte `protobuf:"bytes,1,rep,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
Commodities []*Commodity `protobuf:"bytes,2,rep,name=commodities,proto3" json:"commodities,omitempty"`
}
@@ -171,7 +171,7 @@ func (*MsgCreateAccount) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{2}
}
func (x *MsgCreateAccount) GetPublicKey() [][]byte {
func (x *MsgCreateAccount) GetPublicKey() []byte {
if x != nil {
return x.PublicKey
}
@@ -232,25 +232,74 @@ func (x *MsgRegisterPair) GetPair() *Pair {
return nil
}
type MsgTradeSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
TradeSet *TradeSet `protobuf:"bytes,1,opt,name=trade_set,json=tradeSet,proto3" json:"trade_set,omitempty"`
}
func (x *MsgTradeSet) Reset() {
*x = MsgTradeSet{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MsgTradeSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MsgTradeSet) ProtoMessage() {}
func (x *MsgTradeSet) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MsgTradeSet.ProtoReflect.Descriptor instead.
func (*MsgTradeSet) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{4}
}
func (x *MsgTradeSet) GetTradeSet() *TradeSet {
if x != nil {
return x.TradeSet
}
return nil
}
type Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
//a Msg has to be one of the below
// a Msg has to be one of the below
//
// Types that are assignable to Sum:
//
// *Msg_MsgBid
// *Msg_MsgAsk
// *Msg_MsgRegisterPair
// *Msg_MsgCreateAccount
// *Msg_MsgTradeSet
Sum isMsg_Sum `protobuf_oneof:"sum"`
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[4]
mi := &file_msgs_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -263,7 +312,7 @@ func (x *Msg) String() string {
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[4]
mi := &file_msgs_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -276,7 +325,7 @@ func (x *Msg) ProtoReflect() protoreflect.Message {
// Deprecated: Use Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{4}
return file_msgs_proto_rawDescGZIP(), []int{5}
}
func (m *Msg) GetSum() isMsg_Sum {
@@ -314,6 +363,13 @@ func (x *Msg) GetMsgCreateAccount() *MsgCreateAccount {
return nil
}
func (x *Msg) GetMsgTradeSet() *MsgTradeSet {
if x, ok := x.GetSum().(*Msg_MsgTradeSet); ok {
return x.MsgTradeSet
}
return nil
}
type isMsg_Sum interface {
isMsg_Sum()
}
@@ -334,6 +390,10 @@ type Msg_MsgCreateAccount struct {
MsgCreateAccount *MsgCreateAccount `protobuf:"bytes,4,opt,name=msg_create_account,json=msgCreateAccount,proto3,oneof"`
}
type Msg_MsgTradeSet struct {
MsgTradeSet *MsgTradeSet `protobuf:"bytes,5,opt,name=msg_trade_set,json=msgTradeSet,proto3,oneof"`
}
func (*Msg_MsgBid) isMsg_Sum() {}
func (*Msg_MsgAsk) isMsg_Sum() {}
@@ -342,6 +402,8 @@ func (*Msg_MsgRegisterPair) isMsg_Sum() {}
func (*Msg_MsgCreateAccount) isMsg_Sum() {}
func (*Msg_MsgTradeSet) isMsg_Sum() {}
var File_msgs_proto protoreflect.FileDescriptor
var file_msgs_proto_rawDesc = []byte{
@@ -361,7 +423,7 @@ var file_msgs_proto_rawDesc = []byte{
0x6f, 0x6b, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x73, 0x6b, 0x52, 0x08, 0x61, 0x73, 0x6b,
0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x69, 0x0a, 0x10, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x70,
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x64, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64,
@@ -369,27 +431,35 @@ var file_msgs_proto_rawDesc = []byte{
0x22, 0x36, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50,
0x61, 0x69, 0x72, 0x12, 0x23, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x50, 0x61,
0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x22, 0xff, 0x01, 0x0a, 0x03, 0x4d, 0x73, 0x67,
0x12, 0x2c, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x11, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73,
0x67, 0x42, 0x69, 0x64, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x73, 0x67, 0x42, 0x69, 0x64, 0x12, 0x2c,
0x0a, 0x07, 0x6d, 0x73, 0x67, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x11, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67, 0x41,
0x73, 0x6b, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x73, 0x67, 0x41, 0x73, 0x6b, 0x12, 0x48, 0x0a, 0x11,
0x6d, 0x73, 0x67, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x69,
0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62,
0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50,
0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x4b, 0x0a, 0x12, 0x6d, 0x73, 0x67, 0x5f, 0x63, 0x72,
0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d,
0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x48,
0x00, 0x52, 0x10, 0x6d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d,
0x69, 0x6e, 0x74, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x61,
0x62, 0x63, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x6f, 0x72, 0x64, 0x65,
0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x22, 0x3f, 0x0a, 0x0b, 0x4d, 0x73, 0x67, 0x54,
0x72, 0x61, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x64, 0x65,
0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6f, 0x72, 0x64,
0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x54, 0x72, 0x61, 0x64, 0x65, 0x53, 0x65, 0x74, 0x52,
0x08, 0x74, 0x72, 0x61, 0x64, 0x65, 0x53, 0x65, 0x74, 0x22, 0xbd, 0x02, 0x0a, 0x03, 0x4d, 0x73,
0x67, 0x12, 0x2c, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x5f, 0x62, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d,
0x73, 0x67, 0x42, 0x69, 0x64, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x73, 0x67, 0x42, 0x69, 0x64, 0x12,
0x2c, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x5f, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x11, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67,
0x41, 0x73, 0x6b, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x73, 0x67, 0x41, 0x73, 0x6b, 0x12, 0x48, 0x0a,
0x11, 0x6d, 0x73, 0x67, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x61,
0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72,
0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x50, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x4b, 0x0a, 0x12, 0x6d, 0x73, 0x67, 0x5f, 0x63,
0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e,
0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x48, 0x00, 0x52, 0x10, 0x6d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0d, 0x6d, 0x73, 0x67, 0x5f, 0x74, 0x72, 0x61, 0x64,
0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x72, 0x61, 0x64, 0x65,
0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x73, 0x67, 0x54, 0x72, 0x61, 0x64, 0x65, 0x53,
0x65, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69,
0x6e, 0x74, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x61, 0x62,
0x63, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72,
0x62, 0x6f, 0x6f, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -404,34 +474,38 @@ func file_msgs_proto_rawDescGZIP() []byte {
return file_msgs_proto_rawDescData
}
var file_msgs_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_msgs_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_msgs_proto_goTypes = []interface{}{
(*MsgBid)(nil), // 0: orderbook.MsgBid
(*MsgAsk)(nil), // 1: orderbook.MsgAsk
(*MsgCreateAccount)(nil), // 2: orderbook.MsgCreateAccount
(*MsgRegisterPair)(nil), // 3: orderbook.MsgRegisterPair
(*Msg)(nil), // 4: orderbook.Msg
(*Pair)(nil), // 5: orderbook.Pair
(*OrderBid)(nil), // 6: orderbook.OrderBid
(*OrderAsk)(nil), // 7: orderbook.OrderAsk
(*Commodity)(nil), // 8: orderbook.Commodity
(*MsgTradeSet)(nil), // 4: orderbook.MsgTradeSet
(*Msg)(nil), // 5: orderbook.Msg
(*Pair)(nil), // 6: orderbook.Pair
(*OrderBid)(nil), // 7: orderbook.OrderBid
(*OrderAsk)(nil), // 8: orderbook.OrderAsk
(*Commodity)(nil), // 9: orderbook.Commodity
(*TradeSet)(nil), // 10: orderbook.TradeSet
}
var file_msgs_proto_depIdxs = []int32{
5, // 0: orderbook.MsgBid.pair:type_name -> orderbook.Pair
6, // 1: orderbook.MsgBid.bid_order:type_name -> orderbook.OrderBid
5, // 2: orderbook.MsgAsk.pair:type_name -> orderbook.Pair
7, // 3: orderbook.MsgAsk.ask_order:type_name -> orderbook.OrderAsk
8, // 4: orderbook.MsgCreateAccount.commodities:type_name -> orderbook.Commodity
5, // 5: orderbook.MsgRegisterPair.pair:type_name -> orderbook.Pair
0, // 6: orderbook.Msg.msg_bid:type_name -> orderbook.MsgBid
1, // 7: orderbook.Msg.msg_ask:type_name -> orderbook.MsgAsk
3, // 8: orderbook.Msg.msg_register_pair:type_name -> orderbook.MsgRegisterPair
2, // 9: orderbook.Msg.msg_create_account:type_name -> orderbook.MsgCreateAccount
10, // [10:10] is the sub-list for method output_type
10, // [10:10] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
10, // [10:10] is the sub-list for extension extendee
0, // [0:10] is the sub-list for field type_name
6, // 0: orderbook.MsgBid.pair:type_name -> orderbook.Pair
7, // 1: orderbook.MsgBid.bid_order:type_name -> orderbook.OrderBid
6, // 2: orderbook.MsgAsk.pair:type_name -> orderbook.Pair
8, // 3: orderbook.MsgAsk.ask_order:type_name -> orderbook.OrderAsk
9, // 4: orderbook.MsgCreateAccount.commodities:type_name -> orderbook.Commodity
6, // 5: orderbook.MsgRegisterPair.pair:type_name -> orderbook.Pair
10, // 6: orderbook.MsgTradeSet.trade_set:type_name -> orderbook.TradeSet
0, // 7: orderbook.Msg.msg_bid:type_name -> orderbook.MsgBid
1, // 8: orderbook.Msg.msg_ask:type_name -> orderbook.MsgAsk
3, // 9: orderbook.Msg.msg_register_pair:type_name -> orderbook.MsgRegisterPair
2, // 10: orderbook.Msg.msg_create_account:type_name -> orderbook.MsgCreateAccount
4, // 11: orderbook.Msg.msg_trade_set:type_name -> orderbook.MsgTradeSet
12, // [12:12] is the sub-list for method output_type
12, // [12:12] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_msgs_proto_init() }
@@ -490,6 +564,18 @@ func file_msgs_proto_init() {
}
}
file_msgs_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MsgTradeSet); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_msgs_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); i {
case 0:
return &v.state
@@ -502,11 +588,12 @@ func file_msgs_proto_init() {
}
}
}
file_msgs_proto_msgTypes[4].OneofWrappers = []interface{}{
file_msgs_proto_msgTypes[5].OneofWrappers = []interface{}{
(*Msg_MsgBid)(nil),
(*Msg_MsgAsk)(nil),
(*Msg_MsgRegisterPair)(nil),
(*Msg_MsgCreateAccount)(nil),
(*Msg_MsgTradeSet)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -514,7 +601,7 @@ func file_msgs_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_msgs_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
+6 -1
View File
@@ -16,7 +16,7 @@ message MsgAsk {
}
message MsgCreateAccount {
repeated bytes public_key = 1;
bytes public_key = 1;
repeated Commodity commodities = 2;
}
@@ -24,6 +24,10 @@ message MsgRegisterPair {
Pair pair = 1;
}
message MsgTradeSet {
TradeSet trade_set = 1;
}
message Msg {
//a Msg has to be one of the below
oneof sum {
@@ -31,5 +35,6 @@ message Msg {
MsgAsk msg_ask = 2;
MsgRegisterPair msg_register_pair = 3;
MsgCreateAccount msg_create_account = 4;
MsgTradeSet msg_trade_set = 5;
}
}
+13 -1
View File
@@ -98,10 +98,22 @@ func (o *OrderBid) ValidateBasic() error {
if o.MaxPrice <= 0 {
return errors.New("min price must be greater than 0")
}
return nil
}
func (m *MatchedOrder) ValidateBasic() error {
if len(m.OrderAsk.Signature) != ed25519.SignatureSize {
return errors.New("invalid signature size")
}
}
func (t *TradeSet) ValidateBasic() error {
return t.Pair.ValidateBasic()
return t.MatchedOrders.ValidateBasic()
}
func (o *OrderAsk) ValidateBasic() error {
if o.Quantity == 0 {
return errors.New("quantity outbound must be non zero")
+4 -4
View File
@@ -279,8 +279,8 @@ type Account struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
PublicKey [][]byte `protobuf:"bytes,2,rep,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
// the set of commodities that the account has
Commodities []*Commodity `protobuf:"bytes,3,rep,name=commodities,proto3" json:"commodities,omitempty"`
}
@@ -324,7 +324,7 @@ func (x *Account) GetIndex() uint64 {
return 0
}
func (x *Account) GetPublicKey() [][]byte {
func (x *Account) GetPublicKey() []byte {
if x != nil {
return x.PublicKey
}
@@ -485,7 +485,7 @@ var file_wire_proto_rawDesc = []byte{
0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x76, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62,
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64,
0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74,
+1 -1
View File
@@ -32,7 +32,7 @@ message Commodity {
message Account {
uint64 index = 1;
repeated bytes public_key = 2;
bytes public_key = 2;
// the set of commodities that the account has
repeated Commodity commodities = 3;
}