Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Universal CLI #1662

Merged
merged 61 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
fc00a77
reflect marshaler
containerman17 Sep 27, 2024
09a8367
go mod tidy
containerman17 Sep 27, 2024
ef66086
Merge branch 'main' into reflect-marshaler
containerman17 Sep 28, 2024
ee78c67
nits by ARR4N
containerman17 Sep 30, 2024
f6a144a
lint
containerman17 Sep 30, 2024
6a97f02
Merge branch 'main' into reflect-marshaler
containerman17 Oct 1, 2024
15153e2
some error tests
containerman17 Oct 1, 2024
f350683
Merge branch 'reflect-marshaler' of https://github.com/ava-labs/hyper…
containerman17 Oct 1, 2024
2a28d5a
Merge branch 'main' into reflect-marshaler
containerman17 Oct 8, 2024
e70a7e0
tidy
containerman17 Oct 8, 2024
b67fbae
replace codec.LinearCodec.Unmarshal for UnmarshalFrom
containerman17 Oct 8, 2024
ddb5e6f
format
containerman17 Oct 8, 2024
c4253e7
Merge branch 'main' into reflect-marshaler
containerman17 Oct 10, 2024
cb969a9
nits
containerman17 Oct 10, 2024
d81655d
fix error name
containerman17 Oct 10, 2024
11dd321
working with addresses
containerman17 Oct 14, 2024
48e370e
Merge branch 'main' into cli
containerman17 Oct 14, 2024
1c8581a
ping
containerman17 Oct 14, 2024
ab5d63f
reorganize ping
containerman17 Oct 14, 2024
cb01730
actions
containerman17 Oct 14, 2024
bf3dc64
endpoint command
containerman17 Oct 14, 2024
af035e8
read result
containerman17 Oct 21, 2024
f3f62bf
read result
containerman17 Oct 21, 2024
9c2c631
add support for 0x
containerman17 Oct 21, 2024
36bb8e1
request keys
containerman17 Oct 21, 2024
b3263fb
use hex
containerman17 Oct 21, 2024
4cb50cf
parse int and uint
containerman17 Oct 21, 2024
42ae749
update readme
containerman17 Oct 24, 2024
27a38a3
remove base64
containerman17 Oct 24, 2024
cd15478
update morpheus address
containerman17 Oct 24, 2024
3f0561d
sign tx example
containerman17 Oct 24, 2024
7018f74
sign multi actions
containerman17 Oct 24, 2024
2dd46dc
stuck with txs hanging
containerman17 Oct 24, 2024
adaf68d
readme
containerman17 Oct 24, 2024
e7d292c
Merge branch 'main' into cli
containerman17 Oct 24, 2024
0d9e79c
rename package
containerman17 Oct 24, 2024
6c764e4
update readme
containerman17 Oct 24, 2024
978190a
return uint and linmt
containerman17 Oct 24, 2024
12ccaed
lint
containerman17 Oct 24, 2024
1a073a0
remove extra test
containerman17 Oct 24, 2024
ad6420e
lint
containerman17 Oct 24, 2024
f8cd8e4
Fix code scanning alert no. 114: Incorrect conversion between integer…
containerman17 Oct 24, 2024
135bb9e
lint
containerman17 Oct 24, 2024
2cdcdb8
lint
containerman17 Oct 24, 2024
4656625
simplify Uint function
containerman17 Oct 24, 2024
4510f51
simplify Int
containerman17 Oct 24, 2024
59dcdaa
readme update
containerman17 Oct 24, 2024
20ca2a6
reverse consts
containerman17 Oct 24, 2024
45266e3
lint
containerman17 Oct 24, 2024
fcea895
remove InvalidAddress
containerman17 Oct 24, 2024
4269a1b
bring back the NonExistentAddress test
containerman17 Oct 24, 2024
dfc4900
(optional nit) maybe text instead of human?
containerman17 Oct 25, 2024
5170175
switch from reading the config manually to using cobra/viper to read…
containerman17 Oct 25, 2024
8ad54d5
descriptive variable name
containerman17 Oct 25, 2024
40611e0
unexpected field provided error
containerman17 Oct 25, 2024
c648b25
add TODO for timestamp and max fee
containerman17 Oct 25, 2024
d80ed67
change ws to indexer
containerman17 Oct 25, 2024
1a47159
lint
containerman17 Oct 25, 2024
d100ff0
Merge branch 'main' into cli
containerman17 Oct 25, 2024
0ae0c9a
go mod tidy (viper)
containerman17 Oct 25, 2024
83bd857
move manual tx signing to chain package + nits
aaronbuchwald Oct 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,48 @@ func describeStruct(t reflect.Type) ([]Field, []reflect.Type, error) {

return fields, otherStructsSeen, nil
}

func (a *ABI) FindOutputByID(id uint8) (TypedStruct, bool) {
for _, output := range a.Outputs {
if output.ID == id {
return output, true
}
}
return TypedStruct{}, false
}

func (a *ABI) FindActionByID(id uint8) (TypedStruct, bool) {
for _, action := range a.Actions {
if action.ID == id {
return action, true
}
}
return TypedStruct{}, false
}

func (a *ABI) FindOutputByName(name string) (TypedStruct, bool) {
for _, output := range a.Outputs {
if output.Name == name {
return output, true
}
}
return TypedStruct{}, false
}

func (a *ABI) FindActionByName(name string) (TypedStruct, bool) {
for _, action := range a.Actions {
if action.Name == name {
return action, true
}
}
return TypedStruct{}, false
}

func (a *ABI) FindTypeByName(name string) (Type, bool) {
for _, typ := range a.Types {
if typ.Name == name {
return typ, true
}
}
return Type{}, false
}
60 changes: 45 additions & 15 deletions abi/dynamic/reflect_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
var ErrTypeNotFound = errors.New("type not found in ABI")

func Marshal(inputABI abi.ABI, typeName string, jsonData string) ([]byte, error) {
if _, ok := findABIType(inputABI, typeName); !ok {
if _, ok := inputABI.FindTypeByName(typeName); !ok {
return nil, fmt.Errorf("marshalling %s: %w", typeName, ErrTypeNotFound)
}

Expand All @@ -41,19 +41,57 @@ func Marshal(inputABI abi.ABI, typeName string, jsonData string) ([]byte, error)
return nil, fmt.Errorf("failed to unmarshal JSON data: %w", err)
}

writer := codec.NewWriter(0, consts.NetworkSizeLimit)
var typeID byte
found := false
for _, action := range inputABI.Actions {
if action.Name == typeName {
typeID = action.ID
found = true
break
}
}
if !found {
return nil, fmt.Errorf("action %s not found in ABI", typeName)
}

writer := codec.NewWriter(1, consts.NetworkSizeLimit)
writer.PackByte(typeID)
if err := codec.LinearCodec.MarshalInto(value, writer.Packer); err != nil {
return nil, fmt.Errorf("failed to marshal struct: %w", err)
}

return writer.Bytes(), nil
}

func Unmarshal(inputABI abi.ABI, typeName string, data []byte) (string, error) {
if _, ok := findABIType(inputABI, typeName); !ok {
return "", fmt.Errorf("unmarshalling %s: %w", typeName, ErrTypeNotFound)
func UnmarshalOutput(inputABI abi.ABI, data []byte) (string, error) {
if len(data) == 0 {
return "", nil
}

typeID := data[0]
outputType, ok := inputABI.FindOutputByID(typeID)
if !ok {
return "", fmt.Errorf("output with id %d not found in ABI", typeID)
}

return Unmarshal(inputABI, data[1:], outputType.Name)
}

func UnmarshalAction(inputABI abi.ABI, data []byte) (string, error) {
if len(data) == 0 {
return "", nil
}

typeID := data[0]
actionType, ok := inputABI.FindActionByID(typeID)
if !ok {
return "", fmt.Errorf("action with id %d not found in ABI", typeID)
}

return Unmarshal(inputABI, data[1:], actionType.Name)
}

func Unmarshal(inputABI abi.ABI, data []byte, typeName string) (string, error) {
typeCache := make(map[string]reflect.Type)

typ, err := getReflectType(typeName, inputABI, typeCache)
Expand Down Expand Up @@ -134,13 +172,14 @@ func getReflectType(abiTypeName string, inputABI abi.ABI, typeCache map[string]r
return cachedType, nil
}

abiType, ok := findABIType(inputABI, abiTypeName)
abiType, ok := inputABI.FindTypeByName(abiTypeName)
if !ok {
return nil, fmt.Errorf("type %s not found in ABI", abiTypeName)
}

// It is a struct, as we don't support anything else as custom types
fields := make([]reflect.StructField, len(abiType.Fields))

for i, field := range abiType.Fields {
fieldType, err := getReflectType(field.Type, inputABI, typeCache)
if err != nil {
Expand All @@ -159,12 +198,3 @@ func getReflectType(abiTypeName string, inputABI abi.ABI, typeCache map[string]r
return structType, nil
}
}

func findABIType(inputABI abi.ABI, typeName string) (abi.Type, bool) {
for _, typ := range inputABI.Types {
if typ.Name == typeName {
return typ, true
}
}
return abi.Type{}, false
}
8 changes: 5 additions & 3 deletions abi/dynamic/reflect_marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ func TestDynamicMarshal(t *testing.T) {
require.NoError(err)

// Compare with expected hex
expectedHex := string(mustReadFile(t, "../testdata/"+tc.name+".hex"))
expectedHex = strings.TrimSpace(expectedHex)
expectedTypeID, found := abi.FindActionByName(tc.typeName)
require.True(found, "action %s not found in ABI", tc.typeName)

expectedHex := hex.EncodeToString([]byte{expectedTypeID.ID}) + strings.TrimSpace(string(mustReadFile(t, "../testdata/"+tc.name+".hex")))
require.Equal(expectedHex, hex.EncodeToString(objectBytes))

unmarshaledJSON, err := Unmarshal(abi, tc.typeName, objectBytes)
unmarshaledJSON, err := UnmarshalAction(abi, objectBytes)
require.NoError(err)

// Compare with expected JSON
Expand Down
16 changes: 10 additions & 6 deletions api/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func (i *Indexer) storeTransactions(blk *chain.ExecutedBlock) error {
result.Units,
result.Fee,
result.Outputs,
string(result.Error),
); err != nil {
return err
}
Expand All @@ -190,6 +191,7 @@ func (*Indexer) storeTransaction(
units fees.Dimensions,
fee uint64,
outputs [][]byte,
errorStr string,
) error {
outputLength := consts.ByteLen // Single byte containing number of outputs
for _, output := range outputs {
Expand All @@ -206,19 +208,20 @@ func (*Indexer) storeTransaction(
for _, output := range outputs {
writer.PackBytes(output)
}
writer.PackString(errorStr)
if err := writer.Err(); err != nil {
return err
}
return batch.Put(txID[:], writer.Bytes())
}

func (i *Indexer) GetTransaction(txID ids.ID) (bool, int64, bool, fees.Dimensions, uint64, [][]byte, error) {
func (i *Indexer) GetTransaction(txID ids.ID) (bool, int64, bool, fees.Dimensions, uint64, [][]byte, string, error) {
v, err := i.txDB.Get(txID[:])
if errors.Is(err, database.ErrNotFound) {
return false, 0, false, fees.Dimensions{}, 0, nil, nil
return false, 0, false, fees.Dimensions{}, 0, nil, "", nil
}
if err != nil {
return false, 0, false, fees.Dimensions{}, 0, nil, err
return false, 0, false, fees.Dimensions{}, 0, nil, "", err
}
reader := codec.NewReader(v, consts.NetworkSizeLimit)
timestamp := reader.UnpackUint64(true)
Expand All @@ -231,14 +234,15 @@ func (i *Indexer) GetTransaction(txID ids.ID) (bool, int64, bool, fees.Dimension
for i := range outputs {
outputs[i] = reader.UnpackLimitedBytes(consts.NetworkSizeLimit)
}
errorStr := reader.UnpackString(false)
if err := reader.Err(); err != nil {
return false, 0, false, fees.Dimensions{}, 0, nil, err
return false, 0, false, fees.Dimensions{}, 0, nil, "", err
}
dimensions, err := fees.UnpackDimensions(dimensionsBytes)
if err != nil {
return false, 0, false, fees.Dimensions{}, 0, nil, err
return false, 0, false, fees.Dimensions{}, 0, nil, "", err
}
return true, int64(timestamp), success, dimensions, fee, outputs, nil
return true, int64(timestamp), success, dimensions, fee, outputs, errorStr, nil
}

func (i *Indexer) Close() error {
Expand Down
4 changes: 3 additions & 1 deletion api/indexer/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type GetTxResponse struct {
Units fees.Dimensions `json:"units"`
Fee uint64 `json:"fee"`
Outputs []codec.Bytes `json:"result"`
ErrorStr string `json:"errorStr"`
}

type Server struct {
Expand All @@ -122,7 +123,7 @@ func (s *Server) GetTx(req *http.Request, args *GetTxRequest, reply *GetTxRespon
_, span := s.tracer.Start(req.Context(), "Indexer.GetTx")
defer span.End()

found, t, success, units, fee, outputs, err := s.indexer.GetTransaction(args.TxID)
found, t, success, units, fee, outputs, errorStr, err := s.indexer.GetTransaction(args.TxID)
if err != nil {
return err
}
Expand All @@ -139,5 +140,6 @@ func (s *Server) GetTx(req *http.Request, args *GetTxRequest, reply *GetTxRespon
wrappedOutputs[i] = codec.Bytes(output)
}
reply.Outputs = wrappedOutputs
reply.ErrorStr = errorStr
return nil
}
13 changes: 2 additions & 11 deletions api/jsonrpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,10 @@ func (cli *JSONRPCClient) GetABI(ctx context.Context) (abi.ABI, error) {
return resp.ABI, err
}

func (cli *JSONRPCClient) ExecuteActions(ctx context.Context, actor codec.Address, actions []chain.Action) ([][]byte, error) {
actionsMarshaled := make([][]byte, 0, len(actions))
for _, action := range actions {
actionBytes, err := chain.MarshalTyped(action)
if err != nil {
return nil, fmt.Errorf("failed to marshal action: %w", err)
}
actionsMarshaled = append(actionsMarshaled, actionBytes)
}

func (cli *JSONRPCClient) ExecuteActions(ctx context.Context, actor codec.Address, actionsBytes [][]byte) ([][]byte, error) {
args := &ExecuteActionArgs{
Actor: actor,
Actions: actionsMarshaled,
Actions: actionsBytes,
}

resp := new(ExecuteActionReply)
Expand Down
6 changes: 5 additions & 1 deletion api/ws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,14 @@ func (c *WebSocketClient) ListenBlock(

// IssueTx sends [tx] to the streaming rpc server.
func (c *WebSocketClient) RegisterTx(tx *chain.Transaction) error {
return c.RegisterRawTx(tx.Bytes())
}

func (c *WebSocketClient) RegisterRawTx(txBytes []byte) error {
if c.closed {
return ErrClosed
}
return c.mb.Send(append([]byte{TxMode}, tx.Bytes()...))
return c.mb.Send(append([]byte{TxMode}, txBytes...))
}

// ListenTx listens for responses from the streamingServer.
Expand Down
22 changes: 20 additions & 2 deletions chain/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ func (t *TransactionData) Sign(
return UnmarshalTx(p, actionCodec, authCodec)
}

func SignRawActionBytesTx(
base *Base,
rawActionsBytes []byte,
authFactory AuthFactory,
) ([]byte, error) {
p := codec.NewWriter(base.Size(), consts.NetworkSizeLimit)
base.Marshal(p)
p.PackFixedBytes(rawActionsBytes)

auth, err := authFactory.Sign(p.Bytes())
if err != nil {
return nil, err
}
p.PackByte(auth.GetTypeID())
auth.Marshal(p)
return p.Bytes(), p.Err()
}

func (t *TransactionData) Expiry() int64 { return t.Base.Timestamp }

func (t *TransactionData) MaxFee() uint64 { return t.Base.MaxFee }
Expand All @@ -116,7 +134,7 @@ func (t *TransactionData) Marshal(p *codec.Packer) error {

func (t *TransactionData) marshal(p *codec.Packer) error {
t.Base.Marshal(p)
return t.Actions.marshalInto(p)
return t.Actions.MarshalInto(p)
}

type Actions []Action
Expand All @@ -133,7 +151,7 @@ func (a Actions) Size() (int, error) {
return size, nil
}

func (a Actions) marshalInto(p *codec.Packer) error {
func (a Actions) MarshalInto(p *codec.Packer) error {
p.PackByte(uint8(len(a)))
for _, action := range a {
p.PackByte(action.GetTypeID())
Expand Down
Loading
Loading