Skip to content

Commit 14f98c8

Browse files
authored
Related ops checks (#355)
* throw warning * add related ops to validation file * rename relatedops var * fix lint errors * reduce complexity
1 parent 98ca852 commit 14f98c8

7 files changed

+94
-11
lines changed

asserter/asserter.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ type Asserter struct {
4646
// on the transaction. Fore more details please refer to
4747
// https://github.com/coinbase/rosetta-sdk-go/tree/master/asserter#readme
4848
type Validations struct {
49-
Enabled bool `json:"enabled"`
50-
ChainType ChainType `json:"chain_type"`
51-
Payment *ValidationOperation `json:"payment"`
52-
Fee *ValidationOperation `json:"fee"`
49+
Enabled bool `json:"enabled"`
50+
RelatedOpsExists bool `json:"related_ops_exists"`
51+
ChainType ChainType `json:"chain_type"`
52+
Payment *ValidationOperation `json:"payment"`
53+
Fee *ValidationOperation `json:"fee"`
5354
}
5455

5556
type ValidationOperation struct {

asserter/block.go

+12
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ func (a *Asserter) Operations(
297297
feeTotal := big.NewInt(0)
298298
paymentCount := 0
299299
feeCount := 0
300+
relatedOpsExists := false
300301
for i, op := range operations {
301302
// Ensure operations are sorted
302303
if err := a.Operation(op, int64(i), construction); err != nil {
@@ -322,6 +323,7 @@ func (a *Asserter) Operations(
322323
// and that there are no duplicates.
323324
relatedIndexes := []int64{}
324325
for _, relatedOp := range op.RelatedOperations {
326+
relatedOpsExists = true
325327
if relatedOp.Index >= op.OperationIdentifier.Index {
326328
return fmt.Errorf(
327329
"%w: related operation index %d >= operation index %d",
@@ -342,6 +344,16 @@ func (a *Asserter) Operations(
342344
relatedIndexes = append(relatedIndexes, relatedOp.Index)
343345
}
344346
}
347+
// throw an error if relatedOps is not implemented and relatedOps is supported
348+
// otherwise print a warning
349+
if !relatedOpsExists {
350+
if a.validations.Enabled && a.validations.RelatedOpsExists {
351+
return ErrRelatedOperationMissing
352+
}
353+
fmt.Println("Related Operations key is not implemented. " +
354+
"This is fine as long as there is a distinction between " +
355+
"sends and receives and no multiple outputs")
356+
}
345357

346358
// only account based validation
347359
if a.validations.Enabled && a.validations.ChainType == Account {

asserter/block_test.go

+52-5
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,42 @@ func TestBlock(t *testing.T) {
948948
},
949949
},
950950
}
951+
relatedMissingTransaction := &types.Transaction{
952+
TransactionIdentifier: &types.TransactionIdentifier{
953+
Hash: "blah",
954+
},
955+
Operations: []*types.Operation{
956+
{
957+
OperationIdentifier: &types.OperationIdentifier{
958+
Index: int64(0),
959+
},
960+
Type: "PAYMENT",
961+
Status: types.String("SUCCESS"),
962+
Account: validAccount,
963+
Amount: validAmount,
964+
},
965+
{
966+
OperationIdentifier: &types.OperationIdentifier{
967+
Index: int64(1),
968+
},
969+
RelatedOperations: []*types.OperationIdentifier{},
970+
Type: "PAYMENT",
971+
Status: types.String("SUCCESS"),
972+
Account: validAccount,
973+
Amount: validAmount,
974+
},
975+
{
976+
OperationIdentifier: &types.OperationIdentifier{
977+
Index: int64(2),
978+
},
979+
RelatedOperations: []*types.OperationIdentifier{},
980+
Type: "PAYMENT",
981+
Status: types.String("SUCCESS"),
982+
Account: validAccount,
983+
Amount: validAmount,
984+
},
985+
},
986+
}
951987
invalidRelatedTransaction := &types.Transaction{
952988
TransactionIdentifier: &types.TransactionIdentifier{
953989
Hash: "blah",
@@ -1044,10 +1080,11 @@ func TestBlock(t *testing.T) {
10441080
}
10451081

10461082
var tests = map[string]struct {
1047-
block *types.Block
1048-
genesisIndex int64
1049-
startIndex *int64
1050-
err error
1083+
block *types.Block
1084+
validationFilePath string
1085+
genesisIndex int64
1086+
startIndex *int64
1087+
err error
10511088
}{
10521089
"valid block": {
10531090
block: &types.Block{
@@ -1132,6 +1169,16 @@ func TestBlock(t *testing.T) {
11321169
},
11331170
err: ErrRelatedOperationIndexDuplicate,
11341171
},
1172+
"missing related transaction operations": {
1173+
block: &types.Block{
1174+
BlockIdentifier: validBlockIdentifier,
1175+
ParentBlockIdentifier: validParentBlockIdentifier,
1176+
Timestamp: MinUnixEpoch + 1,
1177+
Transactions: []*types.Transaction{relatedMissingTransaction},
1178+
},
1179+
err: ErrRelatedOperationMissing,
1180+
validationFilePath: "data/validation_balanced_related_ops.json",
1181+
},
11351182
"nil block": {
11361183
block: nil,
11371184
err: ErrBlockIsNil,
@@ -1280,7 +1327,7 @@ func TestBlock(t *testing.T) {
12801327
TimestampStartIndex: test.startIndex,
12811328
},
12821329
},
1283-
"",
1330+
test.validationFilePath,
12841331
)
12851332
assert.NotNil(t, asserter)
12861333
assert.NoError(t, err)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"enabled": true,
3+
"related_ops_exists": true,
4+
"chain_type": "account",
5+
"payment": {
6+
"name": "PAYMENT",
7+
"operation": {
8+
"count": 2,
9+
"should_balance": true
10+
}
11+
},
12+
"fee": {
13+
"name": "FEE",
14+
"operation": {
15+
"count": 1,
16+
"should_balance": false
17+
}
18+
}
19+
}

asserter/data/validation_fee_and_payment_balanced.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"enabled": true,
3+
"related_ops_exists": false,
34
"chain_type": "account",
45
"payment": {
56
"name": "PAYMENT",
@@ -15,4 +16,4 @@
1516
"should_balance": false
1617
}
1718
}
18-
}
19+
}

asserter/data/validation_fee_and_payment_unbalanced.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"enabled": true,
3+
"related_ops_exists": false,
34
"chain_type": "account",
45
"payment": {
56
"name": "PAYMENT",
@@ -15,4 +16,4 @@
1516
"should_balance": false
1617
}
1718
}
18-
}
19+
}

asserter/errors.go

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ var (
7171
"related operation has index greater than operation",
7272
)
7373
ErrRelatedOperationIndexDuplicate = errors.New("found duplicate related operation index")
74+
ErrRelatedOperationMissing = errors.New("related operations key is missing")
7475
ErrBlockIdentifierIsNil = errors.New("BlockIdentifier is nil")
7576
ErrBlockIdentifierHashMissing = errors.New("BlockIdentifier.Hash is missing")
7677
ErrBlockIdentifierIndexIsNeg = errors.New("BlockIdentifier.Index is negative")
@@ -119,6 +120,7 @@ var (
119120
ErrOperationStatusNotEmptyForConstruction,
120121
ErrRelatedOperationIndexOutOfOrder,
121122
ErrRelatedOperationIndexDuplicate,
123+
ErrRelatedOperationMissing,
122124
ErrBlockIdentifierIsNil,
123125
ErrBlockIdentifierHashMissing,
124126
ErrBlockIdentifierIndexIsNeg,

0 commit comments

Comments
 (0)