-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Description This PR adds a `ModuleDB` interface which can be used directly by Cosmos SDK modules. A simplified bank example with Mint/Send/Burn functionality against Balance and Supply tables is included in the tests. This PR also: * adds simplified `Get` and `Has` methods to `Table` which use the primary key values in the message instead of `...interface{}` * adds a stable deterministic proto JSON marshaler and updates the `Entry.String` methods to use it because the golden tests are not deterministic without this. This code is currently internal but can be extracted to a public `codec` or `cosmos-proto` package eventually. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
- Loading branch information
Showing
21 changed files
with
2,346 additions
and
323 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package stablejson | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
|
||
"google.golang.org/protobuf/proto" | ||
"google.golang.org/protobuf/reflect/protopath" | ||
"google.golang.org/protobuf/reflect/protorange" | ||
"google.golang.org/protobuf/reflect/protoreflect" | ||
) | ||
|
||
// Marshal marshals the provided message to JSON with a stable ordering based | ||
// on ascending field numbers. | ||
func Marshal(message proto.Message) ([]byte, error) { | ||
buf := &bytes.Buffer{} | ||
firstStack := []bool{true} | ||
err := protorange.Options{ | ||
Stable: true, | ||
}.Range(message.ProtoReflect(), | ||
func(p protopath.Values) error { | ||
// Starting printing the value. | ||
if !firstStack[len(firstStack)-1] { | ||
_, _ = fmt.Fprintf(buf, ",") | ||
} | ||
firstStack[len(firstStack)-1] = false | ||
|
||
// Print the key. | ||
var fd protoreflect.FieldDescriptor | ||
last := p.Index(-1) | ||
beforeLast := p.Index(-2) | ||
switch last.Step.Kind() { | ||
case protopath.FieldAccessStep: | ||
fd = last.Step.FieldDescriptor() | ||
_, _ = fmt.Fprintf(buf, "%q:", fd.Name()) | ||
case protopath.ListIndexStep: | ||
fd = beforeLast.Step.FieldDescriptor() // lists always appear in the context of a repeated field | ||
case protopath.MapIndexStep: | ||
fd = beforeLast.Step.FieldDescriptor() // maps always appear in the context of a repeated field | ||
_, _ = fmt.Fprintf(buf, "%v:", last.Step.MapIndex().Interface()) | ||
case protopath.AnyExpandStep: | ||
_, _ = fmt.Fprintf(buf, `"@type":%q`, last.Value.Message().Descriptor().FullName()) | ||
return nil | ||
case protopath.UnknownAccessStep: | ||
_, _ = fmt.Fprintf(buf, "?: ") | ||
} | ||
|
||
switch v := last.Value.Interface().(type) { | ||
case protoreflect.Message: | ||
_, _ = fmt.Fprintf(buf, "{") | ||
firstStack = append(firstStack, true) | ||
case protoreflect.List: | ||
_, _ = fmt.Fprintf(buf, "[") | ||
firstStack = append(firstStack, true) | ||
case protoreflect.Map: | ||
_, _ = fmt.Fprintf(buf, "{") | ||
firstStack = append(firstStack, true) | ||
case protoreflect.EnumNumber: | ||
var ev protoreflect.EnumValueDescriptor | ||
if fd != nil { | ||
ev = fd.Enum().Values().ByNumber(v) | ||
} | ||
if ev != nil { | ||
_, _ = fmt.Fprintf(buf, "%v", ev.Name()) | ||
} else { | ||
_, _ = fmt.Fprintf(buf, "%v", v) | ||
} | ||
case string, []byte: | ||
_, _ = fmt.Fprintf(buf, "%q", v) | ||
default: | ||
_, _ = fmt.Fprintf(buf, "%v", v) | ||
} | ||
return nil | ||
}, | ||
func(p protopath.Values) error { | ||
last := p.Index(-1) | ||
switch last.Value.Interface().(type) { | ||
case protoreflect.Message: | ||
if last.Step.Kind() != protopath.AnyExpandStep { | ||
_, _ = fmt.Fprintf(buf, "}") | ||
} | ||
case protoreflect.List: | ||
_, _ = fmt.Fprintf(buf, "]") | ||
firstStack = firstStack[:len(firstStack)-1] | ||
case protoreflect.Map: | ||
_, _ = fmt.Fprintf(buf, "}") | ||
firstStack = firstStack[:len(firstStack)-1] | ||
} | ||
return nil | ||
}, | ||
) | ||
return buf.Bytes(), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package stablejson_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"google.golang.org/protobuf/types/known/anypb" | ||
|
||
bankv1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/bank/v1beta1" | ||
basev1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/base/v1beta1" | ||
txv1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/tx/v1beta1" | ||
"github.com/cosmos/cosmos-sdk/orm/internal/stablejson" | ||
) | ||
|
||
func TestStableJSON(t *testing.T) { | ||
msg, err := anypb.New(&bankv1beta1.MsgSend{ | ||
FromAddress: "foo213325", | ||
ToAddress: "foo32t5sdfh", | ||
Amount: []*basev1beta1.Coin{ | ||
{ | ||
Denom: "bar", | ||
Amount: "1234", | ||
}, | ||
{ | ||
Denom: "baz", | ||
Amount: "321", | ||
}, | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
bz, err := stablejson.Marshal(&txv1beta1.TxBody{Messages: []*anypb.Any{msg}}) | ||
require.NoError(t, err) | ||
require.Equal(t, | ||
`{"messages":[{"@type":"cosmos.bank.v1beta1.MsgSend","from_address":"foo213325","to_address":"foo32t5sdfh","amount":[{"denom":"bar","amount":"1234"},{"denom":"baz","amount":"321"}]}]}`, | ||
string(bz)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.