diff --git a/protocol/localtxsubmission/client.go b/protocol/localtxsubmission/client.go index 04b01796..04b0f8c2 100644 --- a/protocol/localtxsubmission/client.go +++ b/protocol/localtxsubmission/client.go @@ -7,6 +7,7 @@ import ( "sync" ) +// Client implements the LocalTxSubmission client type Client struct { *protocol.Protocol config *Config @@ -14,6 +15,7 @@ type Client struct { submitResultChan chan error } +// NewClient returns a new LocalTxSubmission client object func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client { if cfg == nil { tmpCfg := NewConfig() @@ -25,14 +27,14 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client { } // Update state map with timeout stateMap := StateMap.Copy() - if entry, ok := stateMap[STATE_BUSY]; ok { + if entry, ok := stateMap[stateBusy]; ok { entry.Timeout = c.config.Timeout - stateMap[STATE_BUSY] = entry + stateMap[stateBusy] = entry } // Configure underlying Protocol protoConfig := protocol.ProtocolConfig{ - Name: PROTOCOL_NAME, - ProtocolId: PROTOCOL_ID, + Name: protocolName, + ProtocolId: protocolId, Muxer: protoOptions.Muxer, ErrorChan: protoOptions.ErrorChan, Mode: protoOptions.Mode, @@ -40,7 +42,7 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client { MessageHandlerFunc: c.messageHandler, MessageFromCborFunc: NewMsgFromCbor, StateMap: stateMap, - InitialState: STATE_IDLE, + InitialState: stateIdle, } c.Protocol = protocol.New(protoConfig) // Start goroutine to cleanup resources on protocol shutdown @@ -54,16 +56,17 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client { func (c *Client) messageHandler(msg protocol.Message, isResponse bool) error { var err error switch msg.Type() { - case MESSAGE_TYPE_ACCEPT_TX: + case MessageTypeAcceptTx: err = c.handleAcceptTx() - case MESSAGE_TYPE_REJECT_TX: + case MessageTypeRejectTx: err = c.handleRejectTx(msg) default: - err = fmt.Errorf("%s: received unexpected message type %d", PROTOCOL_NAME, msg.Type()) + err = fmt.Errorf("%s: received unexpected message type %d", protocolName, msg.Type()) } return err } +// SubmitTx submits a transaction using the specified transaction era ID and TX payload func (c *Client) SubmitTx(eraId uint16, tx []byte) error { c.busyMutex.Lock() defer c.busyMutex.Unlock() @@ -75,6 +78,7 @@ func (c *Client) SubmitTx(eraId uint16, tx []byte) error { return err } +// Stop transations the protocol to the Done state. No more operations will be possible func (c *Client) Stop() error { c.busyMutex.Lock() defer c.busyMutex.Unlock() diff --git a/protocol/localtxsubmission/error.go b/protocol/localtxsubmission/error.go index e3c1b517..79dfba64 100644 --- a/protocol/localtxsubmission/error.go +++ b/protocol/localtxsubmission/error.go @@ -4,6 +4,7 @@ import ( "fmt" ) +// TransactionRejectedError represents an explicit transaction rejection type TransactionRejectedError struct { ReasonCbor []byte Reason error diff --git a/protocol/localtxsubmission/localtxsubmission.go b/protocol/localtxsubmission/localtxsubmission.go index 78e67784..10f25a95 100644 --- a/protocol/localtxsubmission/localtxsubmission.go +++ b/protocol/localtxsubmission/localtxsubmission.go @@ -1,3 +1,4 @@ +// Package localtxsubmission implements the Ouroboros local-tx-submission protocol package localtxsubmission import ( @@ -6,50 +7,54 @@ import ( "github.com/cloudstruct/go-ouroboros-network/protocol" ) +// Protocol identifiers const ( - PROTOCOL_NAME = "local-tx-submission" - PROTOCOL_ID uint16 = 6 + protocolName = "local-tx-submission" + protocolId uint16 = 6 ) var ( - STATE_IDLE = protocol.NewState(1, "Idle") - STATE_BUSY = protocol.NewState(2, "Busy") - STATE_DONE = protocol.NewState(3, "Done") + stateIdle = protocol.NewState(1, "Idle") + stateBusy = protocol.NewState(2, "Busy") + stateDone = protocol.NewState(3, "Done") ) +// LocalTxSubmission protocol state machine var StateMap = protocol.StateMap{ - STATE_IDLE: protocol.StateMapEntry{ + stateIdle: protocol.StateMapEntry{ Agency: protocol.AgencyClient, Transitions: []protocol.StateTransition{ { - MsgType: MESSAGE_TYPE_SUBMIT_TX, - NewState: STATE_BUSY, + MsgType: MessageTypeSubmitTx, + NewState: stateBusy, }, }, }, - STATE_BUSY: protocol.StateMapEntry{ + stateBusy: protocol.StateMapEntry{ Agency: protocol.AgencyServer, Transitions: []protocol.StateTransition{ { - MsgType: MESSAGE_TYPE_ACCEPT_TX, - NewState: STATE_IDLE, + MsgType: MessageTypeAcceptTx, + NewState: stateIdle, }, { - MsgType: MESSAGE_TYPE_REJECT_TX, - NewState: STATE_IDLE, + MsgType: MessageTypeRejectTx, + NewState: stateIdle, }, }, }, - STATE_DONE: protocol.StateMapEntry{ + stateDone: protocol.StateMapEntry{ Agency: protocol.AgencyNone, }, } +// LocalTxSubmission is a wrapper object that holds the client and server instances type LocalTxSubmission struct { Client *Client Server *Server } +// Config is used to configure the LocalTxSubmission protocol instance type Config struct { SubmitTxFunc SubmitTxFunc Timeout time.Duration @@ -58,6 +63,7 @@ type Config struct { // Callback function types type SubmitTxFunc func(interface{}) error +// New returns a new LocalTxSubmission object func New(protoOptions protocol.ProtocolOptions, cfg *Config) *LocalTxSubmission { l := &LocalTxSubmission{ Client: NewClient(protoOptions, cfg), @@ -66,8 +72,10 @@ func New(protoOptions protocol.ProtocolOptions, cfg *Config) *LocalTxSubmission return l } +// LocalTxSubmissionOptionFunc represents a function used to modify the LocalTxSubmission protocol config type LocalTxSubmissionOptionFunc func(*Config) +// NewConfig returns a new LocalTxSubmission config object with the provided options func NewConfig(options ...LocalTxSubmissionOptionFunc) Config { c := Config{ Timeout: 30 * time.Second, @@ -79,12 +87,14 @@ func NewConfig(options ...LocalTxSubmissionOptionFunc) Config { return c } +// WithSubmitTxFunc specifies the callback function when a TX is submitted when acting as a server func WithSubmitTxFunc(submitTxFunc SubmitTxFunc) LocalTxSubmissionOptionFunc { return func(c *Config) { c.SubmitTxFunc = submitTxFunc } } +// WithTimeout specifies the timeout for a TX submit operation when acting as a client func WithTimeout(timeout time.Duration) LocalTxSubmissionOptionFunc { return func(c *Config) { c.Timeout = timeout diff --git a/protocol/localtxsubmission/messages.go b/protocol/localtxsubmission/messages.go index e143cc71..c77d46b5 100644 --- a/protocol/localtxsubmission/messages.go +++ b/protocol/localtxsubmission/messages.go @@ -2,32 +2,35 @@ package localtxsubmission import ( "fmt" + "github.com/cloudstruct/go-ouroboros-network/protocol" "github.com/cloudstruct/go-ouroboros-network/utils" "github.com/fxamacker/cbor/v2" ) +// Message types const ( - MESSAGE_TYPE_SUBMIT_TX = 0 - MESSAGE_TYPE_ACCEPT_TX = 1 - MESSAGE_TYPE_REJECT_TX = 2 - MESSAGE_TYPE_DONE = 3 + MessageTypeSubmitTx = 0 + MessageTypeAcceptTx = 1 + MessageTypeRejectTx = 2 + MessageTypeDone = 3 ) +// NewMsgFromCbor parses a LocalTxSubmission message from CBOR func NewMsgFromCbor(msgType uint, data []byte) (protocol.Message, error) { var ret protocol.Message switch msgType { - case MESSAGE_TYPE_SUBMIT_TX: + case MessageTypeSubmitTx: ret = &MsgSubmitTx{} - case MESSAGE_TYPE_ACCEPT_TX: + case MessageTypeAcceptTx: ret = &MsgAcceptTx{} - case MESSAGE_TYPE_REJECT_TX: + case MessageTypeRejectTx: ret = &MsgRejectTx{} - case MESSAGE_TYPE_DONE: + case MessageTypeDone: ret = &MsgDone{} } if _, err := utils.CborDecode(data, ret); err != nil { - return nil, fmt.Errorf("%s: decode error: %s", PROTOCOL_NAME, err) + return nil, fmt.Errorf("%s: decode error: %s", protocolName, err) } if ret != nil { // Store the raw message CBOR @@ -51,7 +54,7 @@ type MsgSubmitTxTransaction struct { func NewMsgSubmitTx(eraId uint16, tx []byte) *MsgSubmitTx { m := &MsgSubmitTx{ MessageBase: protocol.MessageBase{ - MessageType: MESSAGE_TYPE_SUBMIT_TX, + MessageType: MessageTypeSubmitTx, }, Transaction: MsgSubmitTxTransaction{ EraId: eraId, @@ -72,7 +75,7 @@ type MsgAcceptTx struct { func NewMsgAcceptTx() *MsgAcceptTx { m := &MsgAcceptTx{ MessageBase: protocol.MessageBase{ - MessageType: MESSAGE_TYPE_ACCEPT_TX, + MessageType: MessageTypeAcceptTx, }, } return m @@ -88,7 +91,7 @@ type MsgRejectTx struct { func NewMsgRejectTx(reasonCbor []byte) *MsgRejectTx { m := &MsgRejectTx{ MessageBase: protocol.MessageBase{ - MessageType: MESSAGE_TYPE_REJECT_TX, + MessageType: MessageTypeRejectTx, }, Reason: cbor.RawMessage(reasonCbor), } @@ -102,7 +105,7 @@ type MsgDone struct { func NewMsgDone() *MsgDone { m := &MsgDone{ MessageBase: protocol.MessageBase{ - MessageType: MESSAGE_TYPE_DONE, + MessageType: MessageTypeDone, }, } return m diff --git a/protocol/localtxsubmission/messages_test.go b/protocol/localtxsubmission/messages_test.go index 81369a59..3b225d2a 100644 --- a/protocol/localtxsubmission/messages_test.go +++ b/protocol/localtxsubmission/messages_test.go @@ -39,23 +39,23 @@ var placeholderRejectError = hexDecode("820204") var tests = []testDefinition{ { CborHex: fmt.Sprintf("82008204d81846%x", placeholderTx), - MessageType: MESSAGE_TYPE_SUBMIT_TX, + MessageType: MessageTypeSubmitTx, Message: NewMsgSubmitTx(ledger.TX_TYPE_ALONZO, placeholderTx), }, { CborHex: "8101", Message: NewMsgAcceptTx(), - MessageType: MESSAGE_TYPE_ACCEPT_TX, + MessageType: MessageTypeAcceptTx, }, { CborHex: fmt.Sprintf("8202%x", placeholderRejectError), - MessageType: MESSAGE_TYPE_REJECT_TX, + MessageType: MessageTypeRejectTx, Message: NewMsgRejectTx(placeholderRejectError), }, { CborHex: "8103", Message: NewMsgDone(), - MessageType: MESSAGE_TYPE_DONE, + MessageType: MessageTypeDone, }, } diff --git a/protocol/localtxsubmission/server.go b/protocol/localtxsubmission/server.go index b2536473..ac7e1b4f 100644 --- a/protocol/localtxsubmission/server.go +++ b/protocol/localtxsubmission/server.go @@ -5,18 +5,20 @@ import ( "github.com/cloudstruct/go-ouroboros-network/protocol" ) +// Server implements the LocalTxSubmission server type Server struct { *protocol.Protocol config *Config } +// NewServer returns a new Server object func NewServer(protoOptions protocol.ProtocolOptions, cfg *Config) *Server { s := &Server{ config: cfg, } protoConfig := protocol.ProtocolConfig{ - Name: PROTOCOL_NAME, - ProtocolId: PROTOCOL_ID, + Name: protocolName, + ProtocolId: protocolId, Muxer: protoOptions.Muxer, ErrorChan: protoOptions.ErrorChan, Mode: protoOptions.Mode, @@ -24,7 +26,7 @@ func NewServer(protoOptions protocol.ProtocolOptions, cfg *Config) *Server { MessageHandlerFunc: s.messageHandler, MessageFromCborFunc: NewMsgFromCbor, StateMap: StateMap, - InitialState: STATE_IDLE, + InitialState: stateIdle, } s.Protocol = protocol.New(protoConfig) return s @@ -33,12 +35,12 @@ func NewServer(protoOptions protocol.ProtocolOptions, cfg *Config) *Server { func (s *Server) messageHandler(msg protocol.Message, isResponse bool) error { var err error switch msg.Type() { - case MESSAGE_TYPE_SUBMIT_TX: + case MessageTypeSubmitTx: err = s.handleSubmitTx(msg) - case MESSAGE_TYPE_DONE: + case MessageTypeDone: err = s.handleDone() default: - err = fmt.Errorf("%s: received unexpected message type %d", PROTOCOL_NAME, msg.Type()) + err = fmt.Errorf("%s: received unexpected message type %d", protocolName, msg.Type()) } return err }