Skip to content

Commit

Permalink
feat: make batch market instruction errors usable
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy Letang <[email protected]>
  • Loading branch information
jeremyletang committed Aug 7, 2024
1 parent d725830 commit b9c8159
Show file tree
Hide file tree
Showing 6 changed files with 893 additions and 583 deletions.
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@

### 🛠 Improvements

- [11428](https://github.com/vegaprotocol/vega/issues/11428) - Add buy back and treasury fee and separate discount/reward factors.
- [11428](https://github.com/vegaprotocol/vega/issues/11428) - Add buy back and treasury fee and separate discount/reward factors.
- [11468](https://github.com/vegaprotocol/vega/issues/11468) - Added support for volume rebate program.
- [11523](https://github.com/vegaprotocol/vega/issues/11523) - Change method of caching to improve `AMM` snapshot performance.
- [11426](https://github.com/vegaprotocol/vega/issues/11426) - `EstimateAMMBounds` now reports issues with commitment.
- [11459](https://github.com/vegaprotocol/vega/issues/11459) - Deprecate time weight position reward metric and replace it with time weighted notional.
- [11459](https://github.com/vegaprotocol/vega/issues/11459) - Deprecate time weight position reward metric and replace it with time weighted notional.
- [11372](https://github.com/vegaprotocol/vega/issues/11372) - Support combined filters for the `AMM` API.
- [11459](https://github.com/vegaprotocol/vega/issues/11459) - Deprecate time weight position reward metric and replace it with time weighted notional.
- [11536](https://github.com/vegaprotocol/vega/issues/11536) - Make the batch market instructions errors programmatically usable.


### 🐛 Fixes

Expand All @@ -30,7 +33,7 @@
### 🐛 Fixes

- [11513](https://github.com/vegaprotocol/vega/issues/11513) - Rollback CometBFT to version `v0.38.8`.
- [11516](https://github.com/vegaprotocol/vega/issues/11516) - Fix order spam check for amends.
- [11516](https://github.com/vegaprotocol/vega/issues/11516) - Fix order spam check for amends.

## 0.77.4

Expand Down
66 changes: 57 additions & 9 deletions core/events/transaction_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package events
import (
"context"
"fmt"
"sort"

commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
Expand Down Expand Up @@ -48,15 +49,63 @@ func NewTransactionResultEventSuccess(
evt := &TransactionResult{
Base: newBase(ctx, TransactionResultEvent),
evt: &eventspb.TransactionResult{
PartyId: party,
Hash: hash,
Status: true,
PartyId: party,
Hash: hash,
Status: true,
StatusDetail: eventspb.TransactionResult_STATUS_SUCCESS,
},
}

return evt.setTx(tx)
}

type RawErrors interface {
GetRawErrors() map[string][]error
}

func makeFailureDetails(err error) *eventspb.TransactionResult_FailureDetails {
if rawErr, isRawErr := err.(RawErrors); isRawErr {
keyErrors := []*eventspb.TransactionResult_KeyErrors{}
for k, v := range rawErr.GetRawErrors() {
e := &eventspb.TransactionResult_KeyErrors{
Key: k,
}

for _, ve := range v {
e.Errors = append(e.Errors, ve.Error())
}

keyErrors = append(keyErrors, e)
}

sort.Slice(keyErrors, func(i, j int) bool {
return keyErrors[i].Key < keyErrors[j].Key
})

return &eventspb.TransactionResult_FailureDetails{
Errors: keyErrors,
}
}

return &eventspb.TransactionResult_FailureDetails{
Error: err.Error(),
}
}

type PartialError interface {
IsPartial() bool
}

func getErrorStatus(err error) eventspb.TransactionResult_Status {
if partialErr, isPartialErr := err.(PartialError); isPartialErr {
if partialErr.IsPartial() {
return eventspb.TransactionResult_STATUS_PARTIAL_SUCCESS
}
}

return eventspb.TransactionResult_STATUS_FAILURE
}

func NewTransactionResultEventFailure(
ctx context.Context,
hash, party string,
Expand All @@ -66,13 +115,12 @@ func NewTransactionResultEventFailure(
evt := &TransactionResult{
Base: newBase(ctx, TransactionResultEvent),
evt: &eventspb.TransactionResult{
PartyId: party,
Hash: hash,
Status: false,
PartyId: party,
Hash: hash,
Status: false,
StatusDetail: getErrorStatus(err),
Extra: &eventspb.TransactionResult_Failure{
Failure: &eventspb.TransactionResult_FailureDetails{
Error: err.Error(),
},
Failure: makeFailureDetails(err),
},
},
}
Expand Down
10 changes: 7 additions & 3 deletions core/processor/batch_market_instructions_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,15 @@ func NewBMIProcessor(
// BMIError implements blockchain/abci.MaybePartialError.
type BMIError struct {
commands.Errors
isPartial bool
Partial bool
}

func (e *BMIError) GetRawErrors() map[string][]error {
return e.Errors
}

func (e *BMIError) IsPartial() bool {
return e.isPartial
return e.Partial
}

func (e *BMIError) Error() string {
Expand Down Expand Up @@ -326,7 +330,7 @@ func (p *BMIProcessor) ProcessBatch(
idx++
}

errs.isPartial = errCnt != len(batch.UpdateMarginMode)+len(batch.Submissions)+len(batch.Amendments)+len(batch.Cancellations)+len(batch.StopOrdersCancellation)+len(batch.StopOrdersSubmission)
errs.Partial = errCnt != len(batch.UpdateMarginMode)+len(batch.Submissions)+len(batch.Amendments)+len(batch.Cancellations)+len(batch.StopOrdersCancellation)+len(batch.StopOrdersSubmission)

return errs.ErrorOrNil()
}
73 changes: 73 additions & 0 deletions core/processor/batch_market_instructions_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ import (
"errors"
"testing"

"code.vegaprotocol.io/vega/commands"
"code.vegaprotocol.io/vega/core/blockchain/abci"
"code.vegaprotocol.io/vega/core/events"
"code.vegaprotocol.io/vega/core/execution/common"
"code.vegaprotocol.io/vega/core/processor"
"code.vegaprotocol.io/vega/core/processor/mocks"
"code.vegaprotocol.io/vega/core/stats"
"code.vegaprotocol.io/vega/core/types"
"code.vegaprotocol.io/vega/libs/ptr"
"code.vegaprotocol.io/vega/logging"
"code.vegaprotocol.io/vega/protos/vega"
commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -503,3 +507,72 @@ func TestBatchMarketInstructionInvalidStopOrder(t *testing.T) {
assert.True(t, perr.IsPartial())
assert.Equal(t, 1, stopCnt)
}

func TestConvertProto(t *testing.T) {
t.Run("with success", func(t *testing.T) {
txResult := events.NewTransactionResultEventSuccess(context.Background(), "0xDEADBEEF", "p1", &commandspb.BatchMarketInstructions{})
assert.Nil(t, ptr.From(txResult.Proto()).GetFailure())
assert.Equal(t, txResult.Proto().StatusDetail, eventspb.TransactionResult_STATUS_SUCCESS)
})

t.Run("with a normal error", func(t *testing.T) {
err := errors.New("not a bmi error")

txResult := events.NewTransactionResultEventFailure(context.Background(), "0xDEADBEEF", "p1", err, &commandspb.BatchMarketInstructions{})
assert.Nil(t, ptr.From(txResult.Proto()).GetSuccess())
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure())
assert.Nil(t, ptr.From(txResult.Proto()).GetFailure().Errors)
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure().Error)
assert.False(t, txResult.Proto().Status)
assert.Equal(t, txResult.Proto().StatusDetail, eventspb.TransactionResult_STATUS_FAILURE)

Check failure on line 528 in core/processor/batch_market_instructions_processor_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed (gofumpt)
})

t.Run("with a partial BMI error", func(t *testing.T) {
errs := &processor.BMIError{
Errors: commands.NewErrors(),
}

errs.AddForProperty("1", errors.New("some error"))
errs.AddForProperty("1", errors.New("some other error"))
errs.AddForProperty("2", errors.New("another error again"))

errs.Partial = true

txResult := events.NewTransactionResultEventFailure(context.Background(), "0xDEADBEEF", "p1", errs, &commandspb.BatchMarketInstructions{})
assert.Nil(t, ptr.From(txResult.Proto()).GetSuccess())
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure())
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure().Errors)
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Error, "")
assert.False(t, txResult.Proto().Status)
assert.Equal(t, txResult.Proto().StatusDetail, eventspb.TransactionResult_STATUS_PARTIAL_SUCCESS)
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[0].Key, "1")
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[0].Errors, []string{"some error", "some other error"})
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[1].Key, "2")
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[1].Errors, []string{"another error again"})
})

t.Run("with a full BMI error", func(t *testing.T) {
errs := &processor.BMIError{
Errors: commands.NewErrors(),
}

errs.AddForProperty("1", errors.New("some error"))
errs.AddForProperty("1", errors.New("some other error"))
errs.AddForProperty("2", errors.New("another error again"))

errs.Partial = false

txResult := events.NewTransactionResultEventFailure(context.Background(), "0xDEADBEEF", "p1", errs, &commandspb.BatchMarketInstructions{})
assert.Nil(t, ptr.From(txResult.Proto()).GetSuccess())
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure())
assert.NotNil(t, ptr.From(txResult.Proto()).GetFailure().Errors)
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Error, "")
assert.False(t, txResult.Proto().Status)
assert.Equal(t, txResult.Proto().StatusDetail, eventspb.TransactionResult_STATUS_FAILURE)
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[0].Key, "1")
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[0].Errors, []string{"some error", "some other error"})
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[1].Key, "2")
assert.Equal(t, ptr.From(txResult.Proto()).GetFailure().Errors[1].Errors, []string{"another error again"})
})
}
20 changes: 19 additions & 1 deletion protos/sources/vega/events/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -588,14 +588,30 @@ message TransferFeesDiscount {
}

message TransactionResult {
enum Status {
// Default value, always invalid
STATUS_UNSPECIFIED = 0;
STATUS_SUCCESS = 1;
STATUS_PARTIAL_SUCCESS = 2;
STATUS_FAILURE = 3;
}

message KeyErrors {
string key = 1;
repeated string errors = 2;
}

// Unique party ID for the related party
string party_id = 1;
// Status of the transaction, did it succeed or an error was raised.
bool status = 2;
// Hash of the transaction
string hash = 3;
// Transaction itself as received by the network
// Status of the transaction
// will be 0 on previous version which is fine
Status statusDetail = 4;

// Transaction itself as received by the network
oneof transaction {
commands.v1.OrderSubmission order_submission = 101;
commands.v1.OrderAmendment order_amendment = 102;
Expand Down Expand Up @@ -644,6 +660,8 @@ message TransactionResult {
message FailureDetails {
// Error message explaining the reason for the transaction failing processing
string error = 1;
// a map of the detailed errors if any
repeated KeyErrors errors = 2;
}
}

Expand Down
Loading

0 comments on commit b9c8159

Please sign in to comment.