diff --git a/cmd/api/handler/constant_test.go b/cmd/api/handler/constant_test.go index 396f7f6..19ee263 100644 --- a/cmd/api/handler/constant_test.go +++ b/cmd/api/handler/constant_test.go @@ -58,7 +58,7 @@ func (s *ConstantTestSuite) TestEnums() { var enums responses.Enums err := json.NewDecoder(rec.Body).Decode(&enums) s.Require().NoError(err) - s.Require().Len(enums.ActionType, 13) + s.Require().Len(enums.ActionType, 14) s.Require().Len(enums.Status, 2) } diff --git a/go.mod b/go.mod index a99a18b..3da51f2 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/celenium-io/astria-indexer go 1.23 require ( - buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2 - buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2 + buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240911152449-eeebd3decdce.2 + buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240925140414-60292a6c635a.2 github.com/cometbft/cometbft v0.38.12 github.com/dipdup-io/workerpool v0.0.4 github.com/dipdup-net/go-lib v0.3.6 diff --git a/go.sum b/go.sum index 0469ea6..df48697 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2 h1:bCHvCYyvhCPWGc3tpl164ONADbH+nKPSc6KhOWb9tfk= buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240911152449-eeebd3decdce.2 h1:/0WgnbNMJ+M5bs1vHE52VMz7SfmNVjxOXkNbCAnguMc= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240911152449-eeebd3decdce.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2 h1:+ihOgxxuevFtaVi7C86TVHg8Nusp1J6ARLqR0pEnR04= buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2/go.mod h1:Ko8az8QN6eXRnIJUUTjTLJUw4htfXfhGxBONXyJPy60= +buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240925140414-60292a6c635a.2 h1:W3G0kaW9pQoyAwaA5zY/ACu7Nw8Ua8Ba+vKkj+m5eTs= +buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240925140414-60292a6c635a.2/go.mod h1:QhdZCN3ol1WttbaK/8j3SKlisGdX6g038qWctKCBwdQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= diff --git a/internal/storage/types/action_type.go b/internal/storage/types/action_type.go index f93a867..0194ded 100644 --- a/internal/storage/types/action_type.go +++ b/internal/storage/types/action_type.go @@ -18,7 +18,8 @@ package types bridge_lock, bridge_unlock, bridge_sudo_change_action, - fee_change + fee_change, + ibc_sudo_change_action ) */ //go:generate go-enum --marshal --sql --values --names diff --git a/internal/storage/types/action_type_enum.go b/internal/storage/types/action_type_enum.go index 047d050..8cf3607 100644 --- a/internal/storage/types/action_type_enum.go +++ b/internal/storage/types/action_type_enum.go @@ -43,6 +43,8 @@ const ( ActionTypeBridgeSudoChangeAction ActionType = "bridge_sudo_change_action" // ActionTypeFeeChange is a ActionType of type fee_change. ActionTypeFeeChange ActionType = "fee_change" + // ActionTypeIbcSudoChangeAction is a ActionType of type ibc_sudo_change_action. + ActionTypeIbcSudoChangeAction ActionType = "ibc_sudo_change_action" ) var ErrInvalidActionType = fmt.Errorf("not a valid ActionType, try [%s]", strings.Join(_ActionTypeNames, ", ")) @@ -61,6 +63,7 @@ var _ActionTypeNames = []string{ string(ActionTypeBridgeUnlock), string(ActionTypeBridgeSudoChangeAction), string(ActionTypeFeeChange), + string(ActionTypeIbcSudoChangeAction), } // ActionTypeNames returns a list of possible string values of ActionType. @@ -86,6 +89,7 @@ func ActionTypeValues() []ActionType { ActionTypeBridgeUnlock, ActionTypeBridgeSudoChangeAction, ActionTypeFeeChange, + ActionTypeIbcSudoChangeAction, } } @@ -115,6 +119,7 @@ var _ActionTypeValue = map[string]ActionType{ "bridge_unlock": ActionTypeBridgeUnlock, "bridge_sudo_change_action": ActionTypeBridgeSudoChangeAction, "fee_change": ActionTypeFeeChange, + "ibc_sudo_change_action": ActionTypeIbcSudoChangeAction, } // ParseActionType attempts to convert a string to a ActionType. diff --git a/internal/storage/types/action_type_mask.go b/internal/storage/types/action_type_mask.go index e5722b5..f879892 100644 --- a/internal/storage/types/action_type_mask.go +++ b/internal/storage/types/action_type_mask.go @@ -17,6 +17,7 @@ const ( ActionTypeBridgeUnlockBits ActionTypeBridgeSudoChangeBits ActionTypeFeeChangeBits + ActionTypeIbcSudoChangeBits ) var ( @@ -34,6 +35,7 @@ var ( ActionTypeBridgeUnlock: ActionTypeBridgeUnlockBits, ActionTypeBridgeSudoChangeAction: ActionTypeBridgeSudoChangeBits, ActionTypeFeeChange: ActionTypeFeeChangeBits, + ActionTypeIbcSudoChangeAction: ActionTypeIbcSudoChangeBits, } ) @@ -71,6 +73,8 @@ func NewActionTypeMask(vals ...string) ActionTypeMask { mask.Set(ActionTypeBridgeSudoChangeBits) case string(ActionTypeFeeChange): mask.Set(ActionTypeFeeChangeBits) + case string(ActionTypeIbcSudoChangeAction): + mask.Set(ActionTypeIbcSudoChangeBits) } } @@ -87,7 +91,7 @@ func (mask ActionTypeMask) Strings() []string { } vals := make([]string, 0) - for val := ActionTypeTransferBits; val <= ActionTypeFeeChangeBits; val <<= 1 { + for val := ActionTypeTransferBits; val <= ActionTypeIbcSudoChangeBits; val <<= 1 { if !mask.Has(val) { continue } @@ -118,6 +122,8 @@ func (mask ActionTypeMask) Strings() []string { vals = append(vals, string(ActionTypeBridgeUnlock)) case ActionTypeFeeChangeBits: vals = append(vals, string(ActionTypeFeeChange)) + case ActionTypeIbcSudoChangeBits: + vals = append(vals, string(ActionTypeIbcSudoChangeAction)) } } diff --git a/internal/storage/types/action_type_mask_test.go b/internal/storage/types/action_type_mask_test.go index 5c948f2..3161b6f 100644 --- a/internal/storage/types/action_type_mask_test.go +++ b/internal/storage/types/action_type_mask_test.go @@ -100,6 +100,13 @@ func TestActionTypeMask(t *testing.T) { require.Equal(t, arr, mask.Strings()) }) + t.Run("ibc sudo change", func(t *testing.T) { + arr := []string{string(ActionTypeIbcSudoChangeAction)} + + mask := NewActionTypeMask(arr...) + require.Equal(t, arr, mask.Strings()) + }) + t.Run("unknown", func(t *testing.T) { arr := []string{"unknown"} diff --git a/pkg/indexer/decode/actions.go b/pkg/indexer/decode/actions.go index f85480d..a8c41a4 100644 --- a/pkg/indexer/decode/actions.go +++ b/pkg/indexer/decode/actions.go @@ -5,7 +5,6 @@ package decode import ( "encoding/base64" - "encoding/hex" "time" astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transactions/v1alpha1" @@ -57,7 +56,7 @@ func parseActions(height types.Level, blockTime time.Time, from string, tx *Deco case *astria.Action_SudoAddressChangeAction: tx.ActionTypes.Set(storageTypes.ActionTypeSudoAddressChangeBits) - err = parseSudoAddressChangeAction(val, height, ctx, &actions[i]) + err = parseSudoAddressChangeAction(val, ctx, &actions[i]) feeType = "astria.protocol.transactions.v1alpha1.SudoAddressChangeAction" case *astria.Action_TransferAction: @@ -105,6 +104,11 @@ func parseActions(height types.Level, blockTime time.Time, from string, tx *Deco err = parseFeeChange(val, ctx, &actions[i]) feeType = "astria.protocol.transactions.v1alpha1.FeeChangeAction" + case *astria.Action_IbcSudoChangeAction: + tx.ActionTypes.Set(storageTypes.ActionTypeIbcSudoChangeBits) + err = parseIbcSudoChangeAction(val, ctx, &actions[i]) + feeType = "astria.protocol.transactions.v1alpha1.IbcSudoChangeAction" + default: return nil, errors.Errorf( "unknown action type | position = %d | block = %d: %##v", @@ -172,6 +176,7 @@ func parseIcs20Withdrawal(body *astria.Action_Ics20Withdrawal, from string, heig action.Data["destination_address"] = body.Ics20Withdrawal.GetDestinationChainAddress() action.Data["return_address"] = body.Ics20Withdrawal.GetReturnAddress().GetBech32M() action.Data["source_channel"] = body.Ics20Withdrawal.GetSourceChannel() + action.Data["use_compat_address"] = body.Ics20Withdrawal.GetUseCompatAddress() decAmount := decimal.RequireFromString(amount) @@ -308,14 +313,14 @@ func parseSequenceAction(body *astria.Action_SequenceAction, from string, height return nil } -func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChangeAction, height types.Level, ctx *Context, action *storage.Action) error { +func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChangeAction, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeSudoAddressChange action.Data = make(map[string]any) if body.SudoAddressChangeAction != nil { address := body.SudoAddressChangeAction.GetNewAddress().GetBech32M() action.Data["address"] = address - addr := ctx.Addresses.Set(address, height, decimal.Zero, "", 1, 0) + addr := ctx.Addresses.Set(address, action.Height, decimal.Zero, "", 1, 0) action.Addresses = append(action.Addresses, &storage.AddressAction{ Address: addr, Action: action, @@ -323,6 +328,7 @@ func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChangeAction, h Height: action.Height, ActionType: action.Type, }) + ctx.AddGenericConstant("authority_sudo_address", address) } return nil } @@ -685,8 +691,11 @@ func parseBridgeUnlock(body *astria.Action_BridgeUnlockAction, from string, heig action.Data["to"] = toAddress action.Data["fee_asset"] = feeAsset action.Data["amount"] = amount + action.Data["rollup_block_number"] = body.BridgeUnlockAction.GetRollupBlockNumber() + action.Data["rollup_withdrawal_event_id"] = body.BridgeUnlockAction.GetRollupWithdrawalEventId() + if memo := body.BridgeUnlockAction.GetMemo(); len(memo) > 0 { - action.Data["memo"] = hex.EncodeToString(memo) + action.Data["memo"] = memo } if bridge != "" { action.Data["bridge"] = bridge @@ -805,3 +814,25 @@ func parseFeeChange(body *astria.Action_FeeChangeAction, ctx *Context, action *s } return nil } + +func parseIbcSudoChangeAction(body *astria.Action_IbcSudoChangeAction, ctx *Context, action *storage.Action) error { + action.Type = storageTypes.ActionTypeIbcSudoChangeAction + action.Data = make(map[string]any) + if body.IbcSudoChangeAction != nil { + address := body.IbcSudoChangeAction.GetNewAddress().GetBech32M() + action.Data["address"] = address + + addr := ctx.Addresses.Set(address, action.Height, decimal.Zero, "", 1, 0) + action.Addresses = append(action.Addresses, &storage.AddressAction{ + Address: addr, + Action: action, + Time: action.Time, + Height: action.Height, + ActionType: action.Type, + }) + + ctx.AddGenericConstant("ibc_sudo_change", address) + } + + return nil +} diff --git a/pkg/indexer/decode/actions_test.go b/pkg/indexer/decode/actions_test.go index f72b0cb..1636dc4 100644 --- a/pkg/indexer/decode/actions_test.go +++ b/pkg/indexer/decode/actions_test.go @@ -83,6 +83,7 @@ func TestDecodeActions(t *testing.T) { BridgeAddress: &primitivev1.Address{ Bech32M: from, }, + UseCompatAddress: true, }, } @@ -99,10 +100,11 @@ func TestDecodeActions(t *testing.T) { "revision_number": uint64(1000), "revision_height": uint64(1001), }, - "timeout_time": uint64(1000), - "fee_asset": feeAssetId, - "memo": "memo", - "bridge": from, + "timeout_time": uint64(1000), + "fee_asset": feeAssetId, + "memo": "memo", + "bridge": from, + "use_compat_address": true, }, Addresses: []*storage.AddressAction{}, BalanceUpdates: []storage.BalanceUpdate{ @@ -253,7 +255,7 @@ func TestDecodeActions(t *testing.T) { action := storage.Action{ Height: 1000, } - err := parseSudoAddressChangeAction(message, 1000, &decodeContext, &action) + err := parseSudoAddressChangeAction(message, &decodeContext, &action) require.NoError(t, err) require.Equal(t, wantAction, action) }) @@ -672,11 +674,13 @@ func TestDecodeActions(t *testing.T) { FeeAsset: feeAssetId, To: &primitivev1.Address{Bech32M: to}, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, - Memo: []byte("memo"), + Memo: "memo", Amount: &primitivev1.Uint128{ Lo: 10, Hi: 0, }, + RollupBlockNumber: 101, + RollupWithdrawalEventId: "event_id", }, } @@ -709,11 +713,13 @@ func TestDecodeActions(t *testing.T) { Height: 1000, Type: types.ActionTypeBridgeUnlock, Data: map[string]any{ - "fee_asset": feeAssetId, - "to": to, - "bridge": bridge, - "amount": "10", - "memo": "6d656d6f", + "fee_asset": feeAssetId, + "to": to, + "bridge": bridge, + "amount": "10", + "memo": "memo", + "rollup_block_number": uint64(101), + "rollup_withdrawal_event_id": "event_id", }, Addresses: make([]*storage.AddressAction, 0), BalanceUpdates: []storage.BalanceUpdate{ @@ -1490,4 +1496,44 @@ func TestDecodeActions(t *testing.T) { require.NoError(t, err) require.Equal(t, wantAction, action) }) + + t.Run("ibc sudo change", func(t *testing.T) { + decodeContext := NewContext(map[string]string{}) + + newAddress := testsuite.RandomAddress() + message := &astria.Action_IbcSudoChangeAction{ + IbcSudoChangeAction: &astria.IbcSudoChangeAction{ + NewAddress: &primitivev1.Address{Bech32M: newAddress}, + }, + } + + wantAction := storage.Action{ + Height: 1000, + Type: types.ActionTypeIbcSudoChangeAction, + Data: map[string]any{ + "address": newAddress, + }, + Addresses: make([]*storage.AddressAction, 0), + } + balance := storage.EmptyBalance() + addressAction := storage.AddressAction{ + Height: 1000, + Address: &storage.Address{ + Height: 1000, + ActionsCount: 1, + Hash: newAddress, + Balance: []*storage.Balance{&balance}, + }, + ActionType: types.ActionTypeIbcSudoChangeAction, + Action: &wantAction, + } + wantAction.Addresses = append(wantAction.Addresses, &addressAction) + + action := storage.Action{ + Height: 1000, + } + err := parseIbcSudoChangeAction(message, &decodeContext, &action) + require.NoError(t, err) + require.Equal(t, wantAction, action) + }) }