diff --git a/actors/account.go b/actors/account.go index 92b4ec47..8166c831 100644 --- a/actors/account.go +++ b/actors/account.go @@ -3,10 +3,11 @@ package actors import ( "bytes" "encoding/base64" - "github.com/zondax/fil-parser/parser" "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/builtin/v11/account" + "github.com/filecoin-project/go-state-types/builtin/v9/account" + "github.com/zondax/fil-parser/parser" + typegen "github.com/whyrusleeping/cbor-gen" ) diff --git a/actors/account/account.go b/actors/account/account.go new file mode 100644 index 00000000..81932cde --- /dev/null +++ b/actors/account/account.go @@ -0,0 +1,55 @@ +package account + +import ( + "bytes" + "encoding/base64" + "fmt" + + "github.com/filecoin-project/go-address" + accountv10 "github.com/filecoin-project/go-state-types/builtin/v10/account" + accountv11 "github.com/filecoin-project/go-state-types/builtin/v11/account" + accountv9 "github.com/filecoin-project/go-state-types/builtin/v11/account" + accountv12 "github.com/filecoin-project/go-state-types/builtin/v12/account" + accountv13 "github.com/filecoin-project/go-state-types/builtin/v13/account" + accountv14 "github.com/filecoin-project/go-state-types/builtin/v14/account" + typegen "github.com/whyrusleeping/cbor-gen" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" +) + +type Account struct{} + +func (a *Account) PubkeyAddress(network string, raw, rawReturn []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + metadata[parser.ParamsKey] = base64.StdEncoding.EncodeToString(raw) + reader := bytes.NewReader(rawReturn) + var r address.Address + err := r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r.String() + return metadata, nil +} + +func (a *Account) AuthenticateMessage(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + // all versions before V17 + case tools.AnyIsSupported(network, height, tools.VersionsBefore(tools.V16)...): + return map[string]interface{}{}, nil // method did not exist + case tools.V17.IsSupported(network, height): + return authenticateMessageGeneric[*accountv9.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv9.AuthenticateMessageParams{}) + case tools.V18.IsSupported(network, height): + return authenticateMessageGeneric[*accountv10.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv10.AuthenticateMessageParams{}) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return authenticateMessageGeneric[*accountv11.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv11.AuthenticateMessageParams{}) + case tools.V21.IsSupported(network, height): + return authenticateMessageGeneric[*accountv12.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv12.AuthenticateMessageParams{}) + case tools.V22.IsSupported(network, height): + return authenticateMessageGeneric[*accountv13.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv13.AuthenticateMessageParams{}) + case tools.V23.IsSupported(network, height): + return authenticateMessageGeneric[*accountv14.AuthenticateMessageParams, *typegen.CborBool](raw, rawReturn, &accountv14.AuthenticateMessageParams{}) + default: + return nil, fmt.Errorf("not supported") + } +} diff --git a/actors/account/account_test.go b/actors/account/account_test.go new file mode 100644 index 00000000..0cdc1561 --- /dev/null +++ b/actors/account/account_test.go @@ -0,0 +1,87 @@ +package account_test + +import ( + _ "embed" + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/account" + "github.com/zondax/fil-parser/tools" + rosettaFilecoinLib "github.com/zondax/rosetta-filecoin-lib" + + // typesV1 "github.com/zondax/fil-parser/parser/v1/types" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any +var lib *rosettaFilecoinLib.RosettaConstructionFilecoin + +var network string + +func TestMain(m *testing.M) { + var err error + network = "mainnet" + lib, err = tools.GetLib(tools.NodeUrl) + if err != nil { + panic(err) + } + + err = json.Unmarshal(expectedData, &expected) + if err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +func TestAuthenticateMessage(t *testing.T) { + + tests, err := tools.LoadTestData[map[string]any](network, "AuthenticateMessage", expected) + require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + account := &account.Account{} + result, err := account.AuthenticateMessage(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + data, err := json.Marshal(result) + require.NoError(t, err) + fmt.Println(string(data)) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func TestPubkeyAddress(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "PubkeyAddress", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + account := &account.Account{} + result, err := account.PubkeyAddress(tt.Network, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + + }) + } +} diff --git a/actors/account/expected.json b/actors/account/expected.json new file mode 100644 index 00000000..e8374bce --- /dev/null +++ b/actors/account/expected.json @@ -0,0 +1,98 @@ +{ + "V1": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V2": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V3": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V4": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V5": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V6": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V7": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V8": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V9": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V10": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V11": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V12": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V13": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V14": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V15": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V16": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V17": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V18": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V19": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V20": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V21": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V22": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V23": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + }, + "V24": { + "PubkeyAddress": {}, + "AuthenticateMessage": {} + } +} diff --git a/actors/account/generic.go b/actors/account/generic.go new file mode 100644 index 00000000..56548a59 --- /dev/null +++ b/actors/account/generic.go @@ -0,0 +1,25 @@ +package account + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func authenticateMessageGeneric[P authenticateMessageParams, R authenticateMessageReturn](raw, rawReturn []byte, params P) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} diff --git a/actors/account/types.go b/actors/account/types.go new file mode 100644 index 00000000..965a227f --- /dev/null +++ b/actors/account/types.go @@ -0,0 +1,13 @@ +package account + +import ( + "io" +) + +type authenticateMessageParams interface { + UnmarshalCBOR(r io.Reader) error +} + +type authenticateMessageReturn interface { + UnmarshalCBOR(r io.Reader) error +} diff --git a/actors/cron/cron.go b/actors/cron/cron.go new file mode 100644 index 00000000..de236d82 --- /dev/null +++ b/actors/cron/cron.go @@ -0,0 +1,34 @@ +package cron + +import ( + cronv2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/cron" + cronv3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/cron" + cronv4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/cron" + cronv5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/cron" + cronv6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/cron" + cronv7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/cron" + cronv8 "github.com/filecoin-project/specs-actors/v8/actors/builtin/cron" + "github.com/zondax/fil-parser/tools" +) + +type Cron struct{} + +func (c *Cron) CronConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return cronConstructorGeneric[*cronv8.ConstructorParams](raw, &cronv8.ConstructorParams{}) + case tools.V15.IsSupported(network, height): + return cronConstructorGeneric[*cronv7.ConstructorParams](raw, &cronv7.ConstructorParams{}) + case tools.V14.IsSupported(network, height): + return cronConstructorGeneric[*cronv6.ConstructorParams](raw, &cronv6.ConstructorParams{}) + case tools.V13.IsSupported(network, height): + return cronConstructorGeneric[*cronv5.ConstructorParams](raw, &cronv5.ConstructorParams{}) + case tools.V12.IsSupported(network, height): + return cronConstructorGeneric[*cronv4.ConstructorParams](raw, &cronv4.ConstructorParams{}) + case tools.V10.IsSupported(network, height) || tools.V11.IsSupported(network, height): + return cronConstructorGeneric[*cronv3.ConstructorParams](raw, &cronv3.ConstructorParams{}) + case tools.V9.IsSupported(network, height): + return cronConstructorGeneric[*cronv2.ConstructorParams](raw, &cronv2.ConstructorParams{}) + } + return nil, nil +} diff --git a/actors/cron/cron_test.go b/actors/cron/cron_test.go new file mode 100644 index 00000000..5d8082a4 --- /dev/null +++ b/actors/cron/cron_test.go @@ -0,0 +1,60 @@ +package cron_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/cron" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +type testFn func(network string, height int64, raw []byte) (map[string]interface{}, error) + +func TestCron(t *testing.T) { + cron := &cron.Cron{} + testFns := map[string]testFn{ + "CronConstructor": cron.CronConstructor, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/cron/expected.json b/actors/cron/expected.json new file mode 100644 index 00000000..e25cf19a --- /dev/null +++ b/actors/cron/expected.json @@ -0,0 +1,5 @@ +{ + "V1": { + "CronConstructor": {} + } +} \ No newline at end of file diff --git a/actors/cron/generic.go b/actors/cron/generic.go new file mode 100644 index 00000000..276e7d9c --- /dev/null +++ b/actors/cron/generic.go @@ -0,0 +1,18 @@ +package cron + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func cronConstructorGeneric[P cronConstructorParams](raw []byte, params P) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + return metadata, nil +} diff --git a/actors/cron/types.go b/actors/cron/types.go new file mode 100644 index 00000000..25a99a64 --- /dev/null +++ b/actors/cron/types.go @@ -0,0 +1,9 @@ +package cron + +import ( + "io" +) + +type cronConstructorParams interface { + UnmarshalCBOR(r io.Reader) error +} diff --git a/actors/datacap/allowance.go b/actors/datacap/allowance.go new file mode 100644 index 00000000..8ed1bc00 --- /dev/null +++ b/actors/datacap/allowance.go @@ -0,0 +1,93 @@ +package datacap + +import ( + "fmt" + + "github.com/filecoin-project/go-state-types/abi" + datacapv10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap" + datacapv11 "github.com/filecoin-project/go-state-types/builtin/v11/datacap" + datacapv14 "github.com/filecoin-project/go-state-types/builtin/v14/datacap" + datacapv15 "github.com/filecoin-project/go-state-types/builtin/v15/datacap" + datacapv9 "github.com/filecoin-project/go-state-types/builtin/v9/datacap" + "github.com/zondax/fil-parser/tools" +) + +func (*Datacap) IncreaseAllowance(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.IncreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} + +func (*Datacap) DecreaseAllowance(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.DecreaseAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} + +func (*Datacap) RevokeAllowance(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.RevokeAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} + +func (*Datacap) GetAllowance(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.GetAllowanceParams, *abi.TokenAmount](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} diff --git a/actors/datacap/burn.go b/actors/datacap/burn.go new file mode 100644 index 00000000..26a963f7 --- /dev/null +++ b/actors/datacap/burn.go @@ -0,0 +1,72 @@ +package datacap + +import ( + "fmt" + + datacapv10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap" + datacapv11 "github.com/filecoin-project/go-state-types/builtin/v11/datacap" + datacapv14 "github.com/filecoin-project/go-state-types/builtin/v14/datacap" + datacapv15 "github.com/filecoin-project/go-state-types/builtin/v15/datacap" + datacapv9 "github.com/filecoin-project/go-state-types/builtin/v9/datacap" + "github.com/zondax/fil-parser/tools" +) + +func (*Datacap) BurnExported(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.BurnParams, *datacapv9.BurnReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.BurnParams, *datacapv10.BurnReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.BurnParams, *datacapv11.BurnReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.BurnParams, *datacapv11.BurnReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.BurnParams, *datacapv14.BurnReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.BurnParams, *datacapv15.BurnReturn](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} + +func (*Datacap) BurnFromExported(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.BurnFromParams, *datacapv9.BurnFromReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.BurnFromParams, *datacapv10.BurnFromReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.BurnFromParams, *datacapv11.BurnFromReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.BurnFromParams, *datacapv11.BurnFromReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.BurnFromParams, *datacapv14.BurnFromReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.BurnFromParams, *datacapv15.BurnFromReturn](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} + +func (*Datacap) DestroyExported(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.DestroyParams, *datacapv9.BurnReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.DestroyParams, *datacapv10.BurnReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.DestroyParams, *datacapv11.BurnReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv11.DestroyParams, *datacapv11.BurnReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.DestroyParams, *datacapv14.BurnReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.DestroyParams, *datacapv15.BurnReturn](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} diff --git a/actors/datacap/datacap.go b/actors/datacap/datacap.go new file mode 100644 index 00000000..316c41bc --- /dev/null +++ b/actors/datacap/datacap.go @@ -0,0 +1,35 @@ +package datacap + +import ( + "github.com/filecoin-project/go-state-types/abi" + "github.com/zondax/fil-parser/parser" +) + +type Datacap struct{} + +func (d *Datacap) NameExported(rawReturn []byte) (map[string]interface{}, error) { + data, err := parse[*abi.CborString, *abi.CborString](nil, rawReturn, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil +} + +func (d *Datacap) SymbolExported(rawReturn []byte) (map[string]interface{}, error) { + data, err := parse[*abi.CborString, *abi.CborString](nil, rawReturn, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil +} + +func (d *Datacap) TotalSupplyExported(rawReturn []byte) (map[string]interface{}, error) { + data, err := parse[*abi.TokenAmount, *abi.TokenAmount](nil, rawReturn, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil +} diff --git a/actors/datacap/datacap_test.go b/actors/datacap/datacap_test.go new file mode 100644 index 00000000..dd2800e2 --- /dev/null +++ b/actors/datacap/datacap_test.go @@ -0,0 +1,125 @@ +package datacap_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/datacap" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +type testFn func(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +func TestDatacap(t *testing.T) { + datacap := &datacap.Datacap{} + testFns := map[string]func(rawReturn []byte) (map[string]interface{}, error){ + "NameExported": datacap.NameExported, + "SymbolExported": datacap.SymbolExported, + "TotalSupplyExported": datacap.TotalSupplyExported, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runDatacapTest(t, fn, tests) + }) + } +} + +func TestBurn(t *testing.T) { + datacap := &datacap.Datacap{} + testFns := map[string]testFn{ + "BurnExported": datacap.BurnExported, + "BurnFromExported": datacap.BurnFromExported, + "DestroyExported": datacap.DestroyExported, + "MintExported": datacap.MintExported, + "TransferExported": datacap.TransferExported, + "IncreaseAllowance": datacap.IncreaseAllowance, + "DecreaseAllowance": datacap.DecreaseAllowance, + "RevokeAllowance": datacap.RevokeAllowance, + "GetAllowance": datacap.GetAllowance, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestGranularityExported(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "GranularityExported", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + datacap := &datacap.Datacap{} + result, err := datacap.GranularityExported(tt.Network, tt.Height, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runDatacapTest(t *testing.T, fn func(rawReturn []byte) (map[string]interface{}, error), tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + result, err := fn(trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + result, err := fn(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/datacap/expected.json b/actors/datacap/expected.json new file mode 100644 index 00000000..4553d23e --- /dev/null +++ b/actors/datacap/expected.json @@ -0,0 +1,17 @@ +{ + "V1": { + "BurnExported": {}, + "BurnFromExported": {}, + "DestroyExported": {}, + "GranularityExported": {}, + "IncreaseAllowance": {}, + "DecreaseAllowance": {}, + "RevokeAllowance": {}, + "GetAllowance": {}, + "MintExported": {}, + "NameExported": {}, + "SymbolExported": {}, + "TotalSupplyExported": {}, + "TransferExported": {} + } +} \ No newline at end of file diff --git a/actors/datacap/generic.go b/actors/datacap/generic.go new file mode 100644 index 00000000..16b0858e --- /dev/null +++ b/actors/datacap/generic.go @@ -0,0 +1,31 @@ +package datacap + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parse[T datacapParams, R datacapReturn](raw, rawReturn []byte, customReturn bool) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + + if !customReturn { + return metadata, nil + } + + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} diff --git a/actors/datacap/granularity.go b/actors/datacap/granularity.go new file mode 100644 index 00000000..a2fb7fa8 --- /dev/null +++ b/actors/datacap/granularity.go @@ -0,0 +1,56 @@ +package datacap + +import ( + "fmt" + + datacapv10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap" + datacapv11 "github.com/filecoin-project/go-state-types/builtin/v11/datacap" + datacapv12 "github.com/filecoin-project/go-state-types/builtin/v12/datacap" + datacapv14 "github.com/filecoin-project/go-state-types/builtin/v14/datacap" + datacapv15 "github.com/filecoin-project/go-state-types/builtin/v15/datacap" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" +) + +func (*Datacap) GranularityExported(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + data, err := parse[*datacapv10.GranularityReturn, *datacapv10.GranularityReturn](rawReturn, nil, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + data, err := parse[*datacapv11.GranularityReturn, *datacapv11.GranularityReturn](rawReturn, nil, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V21.IsSupported(network, height): + data, err := parse[*datacapv12.GranularityReturn, *datacapv12.GranularityReturn](rawReturn, nil, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V23.IsSupported(network, height): + data, err := parse[*datacapv14.GranularityReturn, *datacapv14.GranularityReturn](rawReturn, nil, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V24.IsSupported(network, height): + data, err := parse[*datacapv15.GranularityReturn, *datacapv15.GranularityReturn](rawReturn, nil, false) + if err != nil { + return nil, err + } + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + } + return nil, fmt.Errorf("not supported") +} diff --git a/actors/datacap/mint.go b/actors/datacap/mint.go new file mode 100644 index 00000000..0bfd85e7 --- /dev/null +++ b/actors/datacap/mint.go @@ -0,0 +1,40 @@ +package datacap + +import ( + "fmt" + + datacapv10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap" + datacapv11 "github.com/filecoin-project/go-state-types/builtin/v11/datacap" + datacapv12 "github.com/filecoin-project/go-state-types/builtin/v12/datacap" + datacapv14 "github.com/filecoin-project/go-state-types/builtin/v14/datacap" + datacapv15 "github.com/filecoin-project/go-state-types/builtin/v15/datacap" + datacapv9 "github.com/filecoin-project/go-state-types/builtin/v9/datacap" + "github.com/zondax/fil-parser/tools" +) + +type ( + mintParams = unmarshalCBOR + mintReturn = unmarshalCBOR +) + +func (*Datacap) MintExported(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.MintParams, *datacapv9.MintReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.MintParams, *datacapv10.MintReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.MintParams, *datacapv11.MintReturn](raw, rawReturn, true) + case tools.V12.IsSupported(network, height): + return parse[*datacapv12.MintParams, *datacapv12.MintReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv12.MintParams, *datacapv12.MintReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.MintParams, *datacapv14.MintReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.MintParams, *datacapv15.MintReturn](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} diff --git a/actors/datacap/transfer.go b/actors/datacap/transfer.go new file mode 100644 index 00000000..54768244 --- /dev/null +++ b/actors/datacap/transfer.go @@ -0,0 +1,35 @@ +package datacap + +import ( + "fmt" + + datacapv10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap" + datacapv11 "github.com/filecoin-project/go-state-types/builtin/v11/datacap" + datacapv12 "github.com/filecoin-project/go-state-types/builtin/v12/datacap" + datacapv14 "github.com/filecoin-project/go-state-types/builtin/v14/datacap" + datacapv15 "github.com/filecoin-project/go-state-types/builtin/v15/datacap" + datacapv9 "github.com/filecoin-project/go-state-types/builtin/v9/datacap" + "github.com/zondax/fil-parser/tools" +) + +func (*Datacap) TransferExported(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V8.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*datacapv9.TransferParams, *datacapv9.TransferReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*datacapv10.TransferParams, *datacapv10.TransferReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parse[*datacapv11.TransferParams, *datacapv11.TransferReturn](raw, rawReturn, true) + case tools.V12.IsSupported(network, height): + return parse[*datacapv12.TransferParams, *datacapv12.TransferReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*datacapv12.TransferParams, *datacapv12.TransferReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*datacapv14.TransferParams, *datacapv14.TransferReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*datacapv15.TransferParams, *datacapv15.TransferReturn](raw, rawReturn, true) + } + return nil, fmt.Errorf("not supported") +} diff --git a/actors/datacap/transfer_test.go b/actors/datacap/transfer_test.go new file mode 100644 index 00000000..345c5cfa --- /dev/null +++ b/actors/datacap/transfer_test.go @@ -0,0 +1,16 @@ +package datacap_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/datacap" + "github.com/zondax/fil-parser/tools" +) + +func TestTransferExported(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "TransferExported", expected) + require.NoError(t, err) + datacap := &datacap.Datacap{} + runTest(t, datacap.TransferExported, tests) +} diff --git a/actors/datacap/types.go b/actors/datacap/types.go new file mode 100644 index 00000000..b6b24c1f --- /dev/null +++ b/actors/datacap/types.go @@ -0,0 +1,15 @@ +package datacap + +import "io" + +type unmarshalCBOR interface { + UnmarshalCBOR(io.Reader) error +} + +type datacapParams interface { + unmarshalCBOR +} + +type datacapReturn interface { + unmarshalCBOR +} diff --git a/actors/eam/create.go b/actors/eam/create.go new file mode 100644 index 00000000..3321d2aa --- /dev/null +++ b/actors/eam/create.go @@ -0,0 +1,79 @@ +package eam + +import ( + "fmt" + + eamv10 "github.com/filecoin-project/go-state-types/builtin/v10/eam" + eamv11 "github.com/filecoin-project/go-state-types/builtin/v11/eam" + eamv12 "github.com/filecoin-project/go-state-types/builtin/v12/eam" + eamv13 "github.com/filecoin-project/go-state-types/builtin/v13/eam" + eamv14 "github.com/filecoin-project/go-state-types/builtin/v14/eam" + eamv15 "github.com/filecoin-project/go-state-types/builtin/v15/eam" + + "github.com/ipfs/go-cid" + "github.com/zondax/fil-parser/tools" + "github.com/zondax/fil-parser/types" +) + +func (*Eam) ParseCreateExternal(network string, height int64, rawParams, rawReturn []byte, msgCid cid.Cid) (map[string]interface{}, *types.AddressInfo, error) { + external := true + switch { + case tools.V24.IsSupported(network, height): + return parseCreate[*eamv15.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V23.IsSupported(network, height): + return parseCreate[*eamv14.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V22.IsSupported(network, height): + return parseCreate[*eamv13.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V21.IsSupported(network, height): + return parseCreate[*eamv12.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parseCreate[*eamv13.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V18.IsSupported(network, height): + return parseCreate[*eamv10.CreateExternalReturn](rawParams, rawReturn, msgCid, external) + case tools.V17.IsSupported(network, height): + return nil, nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Eam) ParseCreate(network string, height int64, rawParams, rawReturn []byte, msgCid cid.Cid) (map[string]interface{}, *types.AddressInfo, error) { + external := false + switch { + case tools.V24.IsSupported(network, height): + return parseCreate[*eamv15.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V23.IsSupported(network, height): + return parseCreate[*eamv14.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V22.IsSupported(network, height): + return parseCreate[*eamv13.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V21.IsSupported(network, height): + return parseCreate[*eamv12.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parseCreate[*eamv11.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V18.IsSupported(network, height): + return parseCreate[*eamv10.CreateReturn](rawParams, rawReturn, msgCid, external) + case tools.V17.IsSupported(network, height): + return nil, nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Eam) ParseCreate2(network string, height int64, rawParams, rawReturn []byte, msgCid cid.Cid) (map[string]interface{}, *types.AddressInfo, error) { + external := false + switch { + case tools.V24.IsSupported(network, height): + return parseCreate[*eamv15.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V23.IsSupported(network, height): + return parseCreate[*eamv14.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V22.IsSupported(network, height): + return parseCreate[*eamv13.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V21.IsSupported(network, height): + return parseCreate[*eamv12.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V19.IsSupported(network, height) || tools.V20.IsSupported(network, height): + return parseCreate[*eamv11.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V18.IsSupported(network, height): + return parseCreate[*eamv10.Create2Return](rawParams, rawReturn, msgCid, external) + case tools.V17.IsSupported(network, height): + return nil, nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/eam/eam.go b/actors/eam/eam.go new file mode 100644 index 00000000..34888849 --- /dev/null +++ b/actors/eam/eam.go @@ -0,0 +1,95 @@ +package eam + +import ( + "encoding/hex" + "fmt" + + "github.com/filecoin-project/go-address" + eamv10 "github.com/filecoin-project/go-state-types/builtin/v10/eam" + eamv11 "github.com/filecoin-project/go-state-types/builtin/v11/eam" + eamv12 "github.com/filecoin-project/go-state-types/builtin/v12/eam" + eamv13 "github.com/filecoin-project/go-state-types/builtin/v13/eam" + eamv14 "github.com/filecoin-project/go-state-types/builtin/v14/eam" + eamv15 "github.com/filecoin-project/go-state-types/builtin/v15/eam" + + "github.com/zondax/fil-parser/parser" +) + +type Eam struct{} + +func newEamCreate(r createReturn) parser.EamCreateReturn { + switch v := r.(type) { + case *eamv15.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + case *eamv14.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + case *eamv13.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + case *eamv12.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + case *eamv11.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + case *eamv10.CreateReturn: + return parser.EamCreateReturn{ + ActorId: v.ActorID, + RobustAddress: v.RobustAddress, + EthAddress: parser.EthPrefix + hex.EncodeToString(v.EthAddress[:]), + } + + default: + return parser.EamCreateReturn{} + } +} + +func validateEamReturn(ret createReturn) error { + if ret == nil { + return fmt.Errorf("input is nil") + } + + checkAndSetAddress := func(addr **address.Address) error { + if *addr == nil { + emptyAdd, _ := address.NewFromString("") + *addr = &emptyAdd + return fmt.Errorf("RobustAddress field is nil. Replaced with empty address") + } + return nil + } + + switch v := ret.(type) { + case *eamv15.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + case *eamv14.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + case *eamv13.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + case *eamv12.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + case *eamv11.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + case *eamv10.CreateReturn: + return checkAndSetAddress(&v.RobustAddress) + + } + + return nil +} diff --git a/actors/eam/eam_test.go b/actors/eam/eam_test.go new file mode 100644 index 00000000..ae08161f --- /dev/null +++ b/actors/eam/eam_test.go @@ -0,0 +1,66 @@ +package eam_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/ipfs/go-cid" + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/eam" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" + "github.com/zondax/fil-parser/types" +) + +var network string + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +type testFn func(network string, height int64, raw, rawReturn []byte, msgCid cid.Cid) (map[string]interface{}, *types.AddressInfo, error) + +func TestEam(t *testing.T) { + eam := &eam.Eam{} + testFns := map[string]testFn{ + "ParseCreateExternal": eam.ParseCreateExternal, + "ParseCreate": eam.ParseCreate, + "ParseCreate2": eam.ParseCreate2, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + result, addrInfo, err := fn(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return, trace.Msg.Cid()) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + require.Equal(t, addrInfo, tt.Address) + } + }) + } +} diff --git a/actors/eam/expected.json b/actors/eam/expected.json new file mode 100644 index 00000000..7f63b190 --- /dev/null +++ b/actors/eam/expected.json @@ -0,0 +1,8 @@ +{ + "V1": { + "ParseCreate": {}, + "ParseCreate2": {}, + "ParseCreateExternal": {}, + "GetExternal": {} + } +} \ No newline at end of file diff --git a/actors/eam/generic.go b/actors/eam/generic.go new file mode 100644 index 00000000..a256222b --- /dev/null +++ b/actors/eam/generic.go @@ -0,0 +1,79 @@ +package eam + +import ( + "bytes" + "encoding/hex" + "fmt" + "strconv" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/types/ethtypes" + "github.com/ipfs/go-cid" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/types" +) + +func parseEamReturn[R createReturn](rawReturn []byte) (R, error) { + var cr R + + reader := bytes.NewReader(rawReturn) + err := cr.UnmarshalCBOR(reader) + if err != nil { + return cr, err + } + + err = validateEamReturn(cr) + if err != nil { + rawString := hex.EncodeToString(rawReturn) + return cr, fmt.Errorf("[parseEamReturn]- Detected invalid return bytes: %s. Raw: %s", err, rawString) + } + + return cr, nil +} + +func parseCreate[T createReturn](rawParams, rawReturn []byte, msgCid cid.Cid, isExternal bool) (map[string]interface{}, *types.AddressInfo, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + + if isExternal { + metadata[parser.ParamsKey] = parser.EthPrefix + hex.EncodeToString(rawParams) + var params abi.CborBytes + if err := params.UnmarshalCBOR(reader); err != nil { + return metadata, nil, fmt.Errorf("error deserializing rawParams: %s - hex data: %s", err.Error(), hex.EncodeToString(rawParams)) + } + + if reader.Len() == 0 { // This means that the reader has processed all the bytes + metadata[parser.ParamsKey] = parser.EthPrefix + hex.EncodeToString(params) + } + } else { + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, nil, err + } + metadata[parser.ParamsKey] = params + } + + createReturn, err := parseEamReturn[T](rawReturn) + if err != nil { + return metadata, nil, err + } + + metadata[parser.ReturnKey] = newEamCreate(createReturn) + + ethHash, err := ethtypes.EthHashFromCid(msgCid) + if err != nil { + return metadata, nil, err + } + metadata[parser.EthHashKey] = ethHash.String() + + r := newEamCreate(createReturn) + createdEvmActor := &types.AddressInfo{ + Short: parser.FilPrefix + strconv.FormatUint(r.ActorId, 10), + Robust: r.RobustAddress.String(), + EthAddress: parser.EthPrefix + r.EthAddress, + ActorType: "evm", + CreationTxCid: msgCid.String(), + } + return metadata, createdEvmActor, nil +} diff --git a/actors/eam/types.go b/actors/eam/types.go new file mode 100644 index 00000000..86b6084a --- /dev/null +++ b/actors/eam/types.go @@ -0,0 +1,7 @@ +package eam + +import "io" + +type createReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/evm/evm.go b/actors/evm/evm.go new file mode 100644 index 00000000..af04b726 --- /dev/null +++ b/actors/evm/evm.go @@ -0,0 +1,219 @@ +package evm + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/filecoin-project/go-state-types/abi" + evmv10 "github.com/filecoin-project/go-state-types/builtin/v10/evm" + evmv11 "github.com/filecoin-project/go-state-types/builtin/v11/evm" + evmv12 "github.com/filecoin-project/go-state-types/builtin/v12/evm" + evmv13 "github.com/filecoin-project/go-state-types/builtin/v13/evm" + evmv14 "github.com/filecoin-project/go-state-types/builtin/v14/evm" + evmv15 "github.com/filecoin-project/go-state-types/builtin/v15/evm" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" +) + +type Evm struct{} + +func (*Evm) InvokeContract(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + metadata[parser.ParamsKey] = parser.EthPrefix + hex.EncodeToString(rawParams) + metadata[parser.ReturnKey] = parser.EthPrefix + hex.EncodeToString(rawReturn) + + var params abi.CborBytes + if err := params.UnmarshalCBOR(reader); err != nil { + return metadata, fmt.Errorf("error deserializing rawParams: %s - hex data: %s", err.Error(), hex.EncodeToString(rawParams)) + } + + if reader.Len() == 0 { // This means that the reader has processed all the bytes + metadata[parser.ParamsKey] = parser.EthPrefix + hex.EncodeToString(params) + } + + reader = bytes.NewReader(rawReturn) + var returnValue abi.CborBytes + if err := returnValue.UnmarshalCBOR(reader); err != nil { + return metadata, fmt.Errorf("error deserializing rawReturn: %s - hex data: %s", err.Error(), hex.EncodeToString(rawReturn)) + } + + if reader.Len() == 0 { // This means that the reader has processed all the bytes + metadata[parser.ReturnKey] = parser.EthPrefix + hex.EncodeToString(returnValue) + } + + return metadata, nil +} + +func (*Evm) Resurrect(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parse[*evmv15.ResurrectParams, *evmv15.ResurrectParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*evmv14.ResurrectParams, *evmv14.ResurrectParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*evmv13.ResurrectParams, *evmv13.ResurrectParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*evmv12.ResurrectParams, *evmv12.ResurrectParams](raw, nil, false) + case tools.V20.IsSupported(network, height): + return parse[*evmv11.ResurrectParams, *evmv11.ResurrectParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*evmv10.ResurrectParams, *evmv10.ResurrectParams](raw, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Evm) InvokeContractDelegate(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parse[*evmv15.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*evmv14.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*evmv13.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*evmv12.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V20.IsSupported(network, height): + return parse[*evmv11.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*evmv10.DelegateCallParams, *abi.CborBytes](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Evm) GetByteCode(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + data, err := parse[*evmv15.GetBytecodeReturn, *evmv15.GetBytecodeReturn](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V23.IsSupported(network, height): + data, err := parse[*evmv14.GetBytecodeReturn, *evmv14.GetBytecodeReturn](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V22.IsSupported(network, height): + data, err := parse[*evmv13.GetBytecodeReturn, *evmv13.GetBytecodeReturn](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V20.IsSupported(network, height): + data, err := parse[*evmv11.GetBytecodeReturn, *evmv11.GetBytecodeReturn](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V18.IsSupported(network, height): + data, err := parse[*evmv10.GetBytecodeReturn, *evmv10.GetBytecodeReturn](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Evm) GetByteCodeHash(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V23.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V22.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V21.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V20.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + case tools.V18.IsSupported(network, height): + data, err := parse[*abi.CborBytes, *abi.CborBytes](raw, nil, false) + if err != nil { + return nil, err + } + // The return value is the same as the params + data[parser.ReturnKey] = data[parser.ParamsKey] + return data, nil + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Evm) EVMConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parse[*evmv15.ConstructorParams, *evmv15.ConstructorParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*evmv14.ConstructorParams, *evmv14.ConstructorParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*evmv13.ConstructorParams, *evmv13.ConstructorParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*evmv12.ConstructorParams, *evmv12.ConstructorParams](raw, nil, false) + case tools.V20.IsSupported(network, height): + return parse[*evmv11.ConstructorParams, *evmv11.ConstructorParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*evmv10.ConstructorParams, *evmv10.ConstructorParams](raw, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Evm) GetStorageAt(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parse[*evmv15.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*evmv14.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*evmv13.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*evmv12.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V20.IsSupported(network, height): + return parse[*evmv11.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*evmv10.GetStorageAtParams, *abi.CborBytes](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/evm/evm_test.go b/actors/evm/evm_test.go new file mode 100644 index 00000000..f9d3d564 --- /dev/null +++ b/actors/evm/evm_test.go @@ -0,0 +1,141 @@ +package evm_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/evm" + "github.com/zondax/fil-parser/tools" + + typesV2 "github.com/zondax/fil-parser/parser/v2/types" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +type testFn func(network string, height int64, raw []byte) (map[string]interface{}, error) + +func TestResurrect(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "Resurrect", expected) + require.NoError(t, err) + evm := &evm.Evm{} + runTest(t, evm.Resurrect, tests) +} + +func TestGetByteCode(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "GetByteCode", expected) + require.NoError(t, err) + evm := &evm.Evm{} + runTest(t, evm.GetByteCode, tests) +} + +func TestGetByteCodeHash(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "GetByteCodeHash", expected) + require.NoError(t, err) + evm := &evm.Evm{} + runTest(t, evm.GetByteCodeHash, tests) +} + +func TestEVMConstructor(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "EVMConstructor", expected) + require.NoError(t, err) + evm := &evm.Evm{} + runTest(t, evm.EVMConstructor, tests) +} + +func TestGetStorageAt(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "GetStorageAt", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + evm := &evm.Evm{} + result, err := evm.GetStorageAt(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func TestInvokeContract(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "InvokeContract", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + evm := &evm.Evm{} + result, err := evm.InvokeContract(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func TestInvokeContractDelegate(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "InvokeContractDelegate", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + evm := &evm.Evm{} + result, err := evm.InvokeContractDelegate(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + result, err := fn(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/evm/expected.json b/actors/evm/expected.json new file mode 100644 index 00000000..92f98dbe --- /dev/null +++ b/actors/evm/expected.json @@ -0,0 +1,11 @@ +{ + "V1": { + "InvokeContract": {}, + "Resurrect": {}, + "InvokeContractDelegate": {}, + "GetByteCode": {}, + "GetByteCodeHash": {}, + "EVMConstructor": {}, + "GetStorageAt": {} + } +} \ No newline at end of file diff --git a/actors/evm/generic.go b/actors/evm/generic.go new file mode 100644 index 00000000..8e72dd10 --- /dev/null +++ b/actors/evm/generic.go @@ -0,0 +1,80 @@ +package evm + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parse[T evmParams, R evmReturn](rawParams, rawReturn []byte, customReturn bool) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + if !customReturn { + return metadata, nil + } + + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} + +func invokeContractDelegate[T evmParams, R evmReturn](rawParams, rawReturn []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} + +func getByteCode[R evmReturn](key string, raw []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var r R + err := r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[key] = r + return metadata, nil +} + +func getStorageAt[T evmParams, R evmReturn](rawParams, rawReturn []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} diff --git a/actors/evm/types.go b/actors/evm/types.go new file mode 100644 index 00000000..b759cfad --- /dev/null +++ b/actors/evm/types.go @@ -0,0 +1,19 @@ +package evm + +import "io" + +type evmParams interface { + UnmarshalCBOR(io.Reader) error +} + +type evmReturn interface { + UnmarshalCBOR(io.Reader) error +} + +type createReturn interface { + UnmarshalCBOR(io.Reader) error +} + +type createReturnStruct[T any] struct { + CreateReturn T +} diff --git a/actors/init/expected.json b/actors/init/expected.json new file mode 100644 index 00000000..6fa6966a --- /dev/null +++ b/actors/init/expected.json @@ -0,0 +1,7 @@ +{ + "V1": { + "InitConstructor": {}, + "ParseExec": {}, + "ParseExec4": {} + } +} \ No newline at end of file diff --git a/actors/init/generic.go b/actors/init/generic.go new file mode 100644 index 00000000..59074793 --- /dev/null +++ b/actors/init/generic.go @@ -0,0 +1,43 @@ +package init + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/types" +) + +func initConstructor[T constructorParams](raw []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var constructor T + err := constructor.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = constructor + return metadata, nil +} + +func parseExec[T constructorParams, R execReturn](msg *parser.LotusMessage, rawReturn []byte) (map[string]interface{}, *types.AddressInfo, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(msg.Params) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, nil, err + } + tmp := execParams(params) + metadata[parser.ParamsKey] = tmp + + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, nil, err + } + + createdActor := returnParams(msg, tmp.CodeCid, r) + metadata[parser.ReturnKey] = createdActor + return metadata, createdActor, nil +} diff --git a/actors/init/init.go b/actors/init/init.go new file mode 100644 index 00000000..1219429d --- /dev/null +++ b/actors/init/init.go @@ -0,0 +1,86 @@ +package init + +import ( + "fmt" + + builtinInitv10 "github.com/filecoin-project/go-state-types/builtin/v10/init" + builtinInitv11 "github.com/filecoin-project/go-state-types/builtin/v11/init" + builtinInitv12 "github.com/filecoin-project/go-state-types/builtin/v12/init" + builtinInitv13 "github.com/filecoin-project/go-state-types/builtin/v13/init" + builtinInitv14 "github.com/filecoin-project/go-state-types/builtin/v14/init" + builtinInitv15 "github.com/filecoin-project/go-state-types/builtin/v15/init" + builtinInitv8 "github.com/filecoin-project/go-state-types/builtin/v8/init" + builtinInitv9 "github.com/filecoin-project/go-state-types/builtin/v9/init" + + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" + "github.com/zondax/fil-parser/types" +) + +type Init struct{} + +func (*Init) InitConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return initConstructor[*builtinInitv15.ConstructorParams](raw) + case tools.V23.IsSupported(network, height): + return initConstructor[*builtinInitv14.ConstructorParams](raw) + case tools.V22.IsSupported(network, height): + return initConstructor[*builtinInitv13.ConstructorParams](raw) + case tools.V21.IsSupported(network, height): + return initConstructor[*builtinInitv12.ConstructorParams](raw) + case tools.V20.IsSupported(network, height): + return initConstructor[*builtinInitv11.ConstructorParams](raw) + case tools.V18.IsSupported(network, height): + return initConstructor[*builtinInitv10.ConstructorParams](raw) + case tools.V17.IsSupported(network, height): + return initConstructor[*builtinInitv9.ConstructorParams](raw) + case tools.V16.IsSupported(network, height): + return initConstructor[*builtinInitv8.ConstructorParams](raw) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Init) ParseExec(network string, height int64, msg *parser.LotusMessage, raw []byte) (map[string]interface{}, *types.AddressInfo, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseExec[*builtinInitv15.ExecParams, *builtinInitv15.ExecReturn](msg, raw) + case tools.V23.IsSupported(network, height): + return parseExec[*builtinInitv14.ExecParams, *builtinInitv14.ExecReturn](msg, raw) + case tools.V22.IsSupported(network, height): + return parseExec[*builtinInitv13.ExecParams, *builtinInitv13.ExecReturn](msg, raw) + case tools.V21.IsSupported(network, height): + return parseExec[*builtinInitv12.ExecParams, *builtinInitv12.ExecReturn](msg, raw) + case tools.V20.IsSupported(network, height): + return parseExec[*builtinInitv11.ExecParams, *builtinInitv11.ExecReturn](msg, raw) + case tools.V18.IsSupported(network, height): + return parseExec[*builtinInitv10.ExecParams, *builtinInitv10.ExecReturn](msg, raw) + case tools.V17.IsSupported(network, height): + return parseExec[*builtinInitv9.ExecParams, *builtinInitv9.ExecReturn](msg, raw) + case tools.V16.IsSupported(network, height): + return parseExec[*builtinInitv8.ExecParams, *builtinInitv8.ExecReturn](msg, raw) + } + return nil, nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Init) ParseExec4(network string, height int64, msg *parser.LotusMessage, raw []byte) (map[string]interface{}, *types.AddressInfo, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseExec[*builtinInitv15.Exec4Params, *builtinInitv15.Exec4Return](msg, raw) + case tools.V23.IsSupported(network, height): + return parseExec[*builtinInitv14.Exec4Params, *builtinInitv14.Exec4Return](msg, raw) + case tools.V22.IsSupported(network, height): + return parseExec[*builtinInitv13.Exec4Params, *builtinInitv13.Exec4Return](msg, raw) + case tools.V21.IsSupported(network, height): + return parseExec[*builtinInitv12.Exec4Params, *builtinInitv12.Exec4Return](msg, raw) + case tools.V20.IsSupported(network, height): + return parseExec[*builtinInitv11.Exec4Params, *builtinInitv11.Exec4Return](msg, raw) + case tools.V18.IsSupported(network, height): + return parseExec[*builtinInitv10.Exec4Params, *builtinInitv10.Exec4Return](msg, raw) + case tools.V17.IsSupported(network, height): + return nil, nil, fmt.Errorf("unsupported height: %d", height) + case tools.V16.IsSupported(network, height): + return nil, nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/init/int_test.go b/actors/init/int_test.go new file mode 100644 index 00000000..52791d07 --- /dev/null +++ b/actors/init/int_test.go @@ -0,0 +1,94 @@ +package init_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + initActor "github.com/zondax/fil-parser/actors/init" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" + "github.com/zondax/fil-parser/types" + + typesV2 "github.com/zondax/fil-parser/parser/v2/types" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +type testFn func(network string, height int64, msg *parser.LotusMessage, raw []byte) (map[string]interface{}, *types.AddressInfo, error) + +func TestInit(t *testing.T) { + initActor := &initActor.Init{} + testFns := map[string]testFn{ + "ParseExec": initActor.ParseExec, + "ParseExec4": initActor.ParseExec4, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestInitConstructor(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "InitConstructor", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + initActor := &initActor.Init{} + result, err := initActor.InitConstructor(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } + +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + lotusMsg := &parser.LotusMessage{ + To: trace.Msg.To, + From: trace.Msg.From, + Method: trace.Msg.Method, + } + result, address, err := fn(tt.Network, tt.Height, lotusMsg, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + require.Equal(t, address, tt.Address) + } + }) + } +} diff --git a/actors/init/types.go b/actors/init/types.go new file mode 100644 index 00000000..e01a4794 --- /dev/null +++ b/actors/init/types.go @@ -0,0 +1,11 @@ +package init + +import "io" + +type constructorParams interface { + UnmarshalCBOR(io.Reader) error +} + +type execReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/init/utils.go b/actors/init/utils.go new file mode 100644 index 00000000..7c4f3bca --- /dev/null +++ b/actors/init/utils.go @@ -0,0 +1,77 @@ +package init + +import ( + "encoding/base64" + + "github.com/filecoin-project/go-address" + builtinInitv10 "github.com/filecoin-project/go-state-types/builtin/v10/init" + builtinInitv11 "github.com/filecoin-project/go-state-types/builtin/v11/init" + builtinInitv12 "github.com/filecoin-project/go-state-types/builtin/v12/init" + builtinInitv13 "github.com/filecoin-project/go-state-types/builtin/v13/init" + builtinInitv14 "github.com/filecoin-project/go-state-types/builtin/v14/init" + builtinInitv15 "github.com/filecoin-project/go-state-types/builtin/v15/init" + builtinInitv8 "github.com/filecoin-project/go-state-types/builtin/v8/init" + builtinInitv9 "github.com/filecoin-project/go-state-types/builtin/v9/init" + "github.com/ipfs/go-cid" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/types" +) + +func execParams(params constructorParams) parser.ExecParams { + setParams := func(codeCid cid.Cid, constructorParams []byte) parser.ExecParams { + return parser.ExecParams{ + CodeCid: codeCid.String(), + ConstructorParams: base64.StdEncoding.EncodeToString(constructorParams), + } + } + switch v := params.(type) { + case *builtinInitv15.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv14.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv13.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv12.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv11.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv10.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv9.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + case *builtinInitv8.ExecParams: + return setParams(v.CodeCID, v.ConstructorParams) + } + return parser.ExecParams{} +} + +func returnParams(msg *parser.LotusMessage, actorCID string, params execReturn) *types.AddressInfo { + setReturn := func(idAddress, robustAddress address.Address) *types.AddressInfo { + return &types.AddressInfo{ + Short: idAddress.String(), + Robust: robustAddress.String(), + ActorCid: actorCID, + CreationTxCid: msg.Cid.String(), + } + } + switch v := params.(type) { + case *builtinInitv15.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv14.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv13.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv12.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv11.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv10.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv9.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + case *builtinInitv8.ExecReturn: + return setReturn(v.IDAddress, v.RobustAddress) + } + return &types.AddressInfo{} + +} diff --git a/actors/market/expected.json b/actors/market/expected.json new file mode 100644 index 00000000..3d2c843b --- /dev/null +++ b/actors/market/expected.json @@ -0,0 +1,22 @@ +{ + "V1": { + "ParseAddBalance": {}, + "ParseWithdrawBalance": {}, + "PublishStorageDealsParams": {}, + "VerifyDealsForActivationParams": {}, + "ActivateDealsParams": {}, + "OnMinerSectorsTerminateParams": {}, + "ComputeDataCommitmentParams": {}, + "GetBalanceParams": {}, + "GetDealDataCommitmentParams": {}, + "GetDealClientParams": {}, + "GetDealProviderParams": {}, + "GetDealLabelParams": {}, + "GetDealTermParams": {}, + "GetDealTotalPriceParams": {}, + "GetDealClientCollateralParams": {}, + "GetDealProviderCollateralParams": {}, + "GetDealVerifiedParams": {}, + "GetDealActivationParams": {} + } +} \ No newline at end of file diff --git a/actors/market/generic.go b/actors/market/generic.go new file mode 100644 index 00000000..9e2ce257 --- /dev/null +++ b/actors/market/generic.go @@ -0,0 +1,32 @@ +package market + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parseGeneric[T marketParam, R marketReturn](rawParams, rawReturn []byte, returnCustomParam bool) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + + metadata[parser.ParamsKey] = params + if !returnCustomParam { + metadata[parser.ParamsKey] = getAddressAsString(params) + return metadata, nil + } + + reader = bytes.NewReader(rawReturn) + var publishReturn R + err = publishReturn.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = publishReturn + return metadata, nil +} diff --git a/actors/market/market.go b/actors/market/market.go new file mode 100644 index 00000000..5526ee97 --- /dev/null +++ b/actors/market/market.go @@ -0,0 +1,356 @@ +package market + +import ( + "fmt" + + "github.com/filecoin-project/go-address" + v10Market "github.com/filecoin-project/go-state-types/builtin/v10/market" + v11Market "github.com/filecoin-project/go-state-types/builtin/v11/market" + v12Market "github.com/filecoin-project/go-state-types/builtin/v12/market" + v13Market "github.com/filecoin-project/go-state-types/builtin/v13/market" + v14Market "github.com/filecoin-project/go-state-types/builtin/v14/market" + v15Market "github.com/filecoin-project/go-state-types/builtin/v15/market" + v8Market "github.com/filecoin-project/go-state-types/builtin/v8/market" + v9Market "github.com/filecoin-project/go-state-types/builtin/v9/market" + "github.com/zondax/fil-parser/tools" +) + +type Market struct{} + +func (*Market) ParseAddBalance(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) ParseWithdrawBalance(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.WithdrawBalanceParams, *v15Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.WithdrawBalanceParams, *v14Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.WithdrawBalanceParams, *v13Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.WithdrawBalanceParams, *v12Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.WithdrawBalanceParams, *v11Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.WithdrawBalanceParams, *v10Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.WithdrawBalanceParams, *v9Market.WithdrawBalanceParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*v8Market.WithdrawBalanceParams, *v8Market.WithdrawBalanceParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) PublishStorageDealsParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.PublishStorageDealsParams, *v15Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.PublishStorageDealsParams, *v14Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.PublishStorageDealsParams, *v13Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.PublishStorageDealsParams, *v12Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.PublishStorageDealsParams, *v11Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.PublishStorageDealsParams, *v10Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.PublishStorageDealsParams, *v9Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + case tools.V16.IsSupported(network, height): + return parseGeneric[*v8Market.PublishStorageDealsParams, *v8Market.PublishStorageDealsReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) VerifyDealsForActivationParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.VerifyDealsForActivationParams, *v15Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.VerifyDealsForActivationParams, *v14Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.VerifyDealsForActivationParams, *v13Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.VerifyDealsForActivationParams, *v12Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.VerifyDealsForActivationParams, *v11Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.VerifyDealsForActivationParams, *v10Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.VerifyDealsForActivationParams, *v9Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + case tools.V16.IsSupported(network, height): + return parseGeneric[*v8Market.VerifyDealsForActivationParams, *v8Market.VerifyDealsForActivationReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) ActivateDealsParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.ActivateDealsParams, *v15Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.ActivateDealsParams, *v14Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.ActivateDealsParams, *v13Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.ActivateDealsParams, *v12Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.ActivateDealsParams, *v11Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.ActivateDealsParams, *v10Market.ActivateDealsResult](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.ActivateDealsParams, *v9Market.ActivateDealsResult](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) OnMinerSectorsTerminateParams(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.OnMinerSectorsTerminateParams, *v15Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.OnMinerSectorsTerminateParams, *v14Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.OnMinerSectorsTerminateParams, *v13Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.OnMinerSectorsTerminateParams, *v12Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.OnMinerSectorsTerminateParams, *v11Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.OnMinerSectorsTerminateParams, *v10Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.OnMinerSectorsTerminateParams, *v9Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*v8Market.OnMinerSectorsTerminateParams, *v8Market.OnMinerSectorsTerminateParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) ComputeDataCommitmentParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.ComputeDataCommitmentParams, *v11Market.ComputeDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.ComputeDataCommitmentParams, *v10Market.ComputeDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*v9Market.ComputeDataCommitmentParams, *v9Market.ComputeDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V16.IsSupported(network, height): + return parseGeneric[*v8Market.ComputeDataCommitmentParams, *v8Market.ComputeDataCommitmentReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetBalanceParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*address.Address, *v15Market.GetBalanceReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*address.Address, *v14Market.GetBalanceReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*address.Address, *v13Market.GetBalanceReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*address.Address, *v12Market.GetBalanceReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*address.Address, *v11Market.GetBalanceReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*address.Address, *v10Market.GetBalanceReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealDataCommitmentParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealDataCommitmentParams, *v15Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealDataCommitmentParams, *v14Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealDataCommitmentParams, *v13Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealDataCommitmentParams, *v12Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealDataCommitmentParams, *v11Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealDataCommitmentParams, *v10Market.GetDealDataCommitmentReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealClientParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealClientParams, *v15Market.GetDealClientReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealClientParams, *v14Market.GetDealClientReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealClientParams, *v13Market.GetDealClientReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealClientParams, *v12Market.GetDealClientReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealClientParams, *v11Market.GetDealClientReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealClientParams, *v10Market.GetDealClientReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealProviderParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealProviderParams, *v15Market.GetDealProviderReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealProviderParams, *v14Market.GetDealProviderReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealProviderParams, *v13Market.GetDealProviderReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealProviderParams, *v12Market.GetDealProviderReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealProviderParams, *v11Market.GetDealProviderReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealProviderParams, *v10Market.GetDealProviderReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealLabelParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealLabelParams, *v15Market.GetDealLabelReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealLabelParams, *v14Market.GetDealLabelReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealLabelParams, *v13Market.GetDealLabelReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealLabelParams, *v12Market.GetDealLabelReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealLabelParams, *v11Market.GetDealLabelReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealLabelParams, *v10Market.GetDealLabelReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealTermParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealTermParams, *v15Market.GetDealTermReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealTermParams, *v14Market.GetDealTermReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealTermParams, *v13Market.GetDealTermReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealTermParams, *v12Market.GetDealTermReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealTermParams, *v11Market.GetDealTermReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealTermParams, *v10Market.GetDealTermReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealTotalPriceParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealTotalPriceParams, *v15Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealTotalPriceParams, *v14Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealTotalPriceParams, *v13Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealTotalPriceParams, *v12Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealTotalPriceParams, *v11Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealTotalPriceParams, *v10Market.GetDealTotalPriceReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealClientCollateralParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealClientCollateralParams, *v15Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealClientCollateralParams, *v14Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealClientCollateralParams, *v13Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealClientCollateralParams, *v12Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealClientCollateralParams, *v11Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealClientCollateralParams, *v10Market.GetDealClientCollateralReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealProviderCollateralParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealProviderCollateralParams, *v15Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealProviderCollateralParams, *v14Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealProviderCollateralParams, *v13Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealProviderCollateralParams, *v12Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealProviderCollateralParams, *v11Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealProviderCollateralParams, *v10Market.GetDealProviderCollateralReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealVerifiedParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealVerifiedParams, *v15Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealVerifiedParams, *v14Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealVerifiedParams, *v13Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealVerifiedParams, *v12Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealVerifiedParams, *v11Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealVerifiedParams, *v10Market.GetDealVerifiedReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Market) GetDealActivationParams(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*v15Market.GetDealActivationParams, *v15Market.GetDealActivationReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*v14Market.GetDealActivationParams, *v14Market.GetDealActivationReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*v13Market.GetDealActivationParams, *v13Market.GetDealActivationReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*v12Market.GetDealActivationParams, *v12Market.GetDealActivationReturn](rawParams, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parseGeneric[*v11Market.GetDealActivationParams, *v11Market.GetDealActivationReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*v10Market.GetDealActivationParams, *v10Market.GetDealActivationReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/market/market_test.go b/actors/market/market_test.go new file mode 100644 index 00000000..17e1c6f5 --- /dev/null +++ b/actors/market/market_test.go @@ -0,0 +1,143 @@ +package market_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/market" + "github.com/zondax/fil-parser/tools" + + typesV2 "github.com/zondax/fil-parser/parser/v2/types" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +type testFn func(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) + +func TestMarket(t *testing.T) { + market := &market.Market{} + testFns := map[string]testFn{ + "PublishStorageDeals": market.PublishStorageDealsParams, + "VerifyDealsForActivation": market.VerifyDealsForActivationParams, + "ActivateDeals": market.ActivateDealsParams, + "ComputeDataCommitment": market.ComputeDataCommitmentParams, + "GetBalance": market.GetBalanceParams, + "GetDealDataCommitment": market.GetDealDataCommitmentParams, + "GetDealClient": market.GetDealClientParams, + "GetDealProvider": market.GetDealProviderParams, + "GetDealLabel": market.GetDealLabelParams, + "GetDealTerm": market.GetDealTermParams, + "GetDealTotalPrice": market.GetDealTotalPriceParams, + "GetDealClientCollateral": market.GetDealClientCollateralParams, + "GetDealProviderCollateral": market.GetDealProviderCollateralParams, + "GetDealVerified": market.GetDealVerifiedParams, + "GetDealActivation": market.GetDealActivationParams, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestOnMinerSectorsTerminate(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "OnMinerSectorsTerminateParams", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + market := &market.Market{} + result, err := market.OnMinerSectorsTerminateParams(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func TestParseAddBalance(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "ParseAddBalance", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + market := &market.Market{} + result, err := market.ParseAddBalance(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func TestParseWithdrawBalance(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "ParseWithdrawBalance", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + market := &market.Market{} + result, err := market.ParseWithdrawBalance(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/market/types.go b/actors/market/types.go new file mode 100644 index 00000000..f56a08a2 --- /dev/null +++ b/actors/market/types.go @@ -0,0 +1,11 @@ +package market + +import "io" + +type marketParam interface { + UnmarshalCBOR(io.Reader) error +} + +type marketReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/market/utils.go b/actors/market/utils.go new file mode 100644 index 00000000..dee771d1 --- /dev/null +++ b/actors/market/utils.go @@ -0,0 +1,10 @@ +package market + +import "github.com/filecoin-project/go-address" + +func getAddressAsString(addr any) string { + if address, ok := addr.(address.Address); ok { + return address.String() + } + return "" +} diff --git a/actors/miner/address.go b/actors/miner/address.go new file mode 100644 index 00000000..60611891 --- /dev/null +++ b/actors/miner/address.go @@ -0,0 +1,194 @@ +package miner + +import ( + "fmt" + + "github.com/filecoin-project/go-address" + miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner" + miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" + miner12 "github.com/filecoin-project/go-state-types/builtin/v12/miner" + miner13 "github.com/filecoin-project/go-state-types/builtin/v13/miner" + miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner" + miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" + "github.com/zondax/fil-parser/tools" +) + +type Miner struct{} + +func (*Miner) ChangeMultiaddrs(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ChangeMultiaddrsParams, *miner15.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ChangeMultiaddrsParams, *miner14.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ChangeMultiaddrsParams, *miner13.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ChangeMultiaddrsParams, *miner12.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ChangeMultiaddrsParams, *miner11.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ChangeMultiaddrsParams, *miner10.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ChangeMultiaddrsParams, *miner9.ChangeMultiaddrsParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ChangeMultiaddrsParams, *miner8.ChangeMultiaddrsParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ChangePeerID(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ChangePeerIDParams, *miner15.ChangePeerIDParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ChangePeerIDParams, *miner14.ChangePeerIDParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ChangePeerIDParams, *miner13.ChangePeerIDParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ChangePeerIDParams, *miner12.ChangePeerIDParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ChangePeerIDParams, *miner11.ChangePeerIDParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ChangePeerIDParams, *miner10.ChangePeerIDParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ChangePeerIDParams, *miner9.ChangePeerIDParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ChangePeerIDParams, *miner8.ChangePeerIDParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ChangeWorkerAddress(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ChangeWorkerAddressParams, *miner15.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ChangeWorkerAddressParams, *miner14.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ChangeWorkerAddressParams, *miner13.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ChangeWorkerAddressParams, *miner12.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ChangeWorkerAddressParams, *miner11.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ChangeWorkerAddressParams, *miner10.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ChangeWorkerAddressParams, *miner9.ChangeWorkerAddressParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ChangeWorkerAddressParams, *miner8.ChangeWorkerAddressParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ChangeOwnerAddress(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*address.Address, *address.Address](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) IsControllingAddressExported(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.IsControllingAddressParams, *miner15.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.IsControllingAddressParams, *miner14.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.IsControllingAddressParams, *miner13.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.IsControllingAddressParams, *miner12.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.IsControllingAddressParams, *miner11.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.IsControllingAddressParams, *miner10.IsControllingAddressReturn](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) GetOwner(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.GetOwnerReturn, *miner15.GetOwnerReturn](rawReturn, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.GetOwnerReturn, *miner14.GetOwnerReturn](rawReturn, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.GetOwnerReturn, *miner13.GetOwnerReturn](rawReturn, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.GetOwnerReturn, *miner12.GetOwnerReturn](rawReturn, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.GetOwnerReturn, *miner11.GetOwnerReturn](rawReturn, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.GetOwnerReturn, *miner10.GetOwnerReturn](rawReturn, nil, false) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) GetPeerID(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.GetPeerIDReturn, *miner15.GetPeerIDReturn](rawReturn, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.GetPeerIDReturn, *miner14.GetPeerIDReturn](rawReturn, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.GetPeerIDReturn, *miner13.GetPeerIDReturn](rawReturn, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.GetPeerIDReturn, *miner12.GetPeerIDReturn](rawReturn, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.GetPeerIDReturn, *miner11.GetPeerIDReturn](rawReturn, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.GetPeerIDReturn, *miner10.GetPeerIDReturn](rawReturn, nil, false) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) GetMultiaddrs(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.GetMultiAddrsReturn, *miner15.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.GetMultiAddrsReturn, *miner14.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.GetMultiAddrsReturn, *miner13.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.GetMultiAddrsReturn, *miner12.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.GetMultiAddrsReturn, *miner11.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.GetMultiAddrsReturn, *miner10.GetMultiAddrsReturn](rawReturn, nil, false) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/miner/balance.go b/actors/miner/balance.go new file mode 100644 index 00000000..4efebd73 --- /dev/null +++ b/actors/miner/balance.go @@ -0,0 +1,81 @@ +package miner + +import ( + "fmt" + + miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner" + miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" + miner12 "github.com/filecoin-project/go-state-types/builtin/v12/miner" + miner13 "github.com/filecoin-project/go-state-types/builtin/v13/miner" + miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner" + miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" + "github.com/zondax/fil-parser/tools" +) + +func (*Miner) GetAvailableBalance(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.GetAvailableBalanceReturn, *miner15.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.GetAvailableBalanceReturn, *miner14.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.GetAvailableBalanceReturn, *miner13.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.GetAvailableBalanceReturn, *miner12.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.GetAvailableBalanceReturn, *miner11.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.GetAvailableBalanceReturn, *miner10.GetAvailableBalanceReturn](rawReturn, nil, false) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) GetVestingFunds(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.GetVestingFundsReturn, *miner15.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.GetVestingFundsReturn, *miner14.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.GetVestingFundsReturn, *miner13.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.GetVestingFundsReturn, *miner12.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.GetVestingFundsReturn, *miner11.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.GetVestingFundsReturn, *miner10.GetVestingFundsReturn](rawReturn, nil, false) + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ParseWithdrawBalance(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.WithdrawBalanceParams, *miner15.WithdrawBalanceParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.WithdrawBalanceParams, *miner14.WithdrawBalanceParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.WithdrawBalanceParams, *miner13.WithdrawBalanceParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.WithdrawBalanceParams, *miner12.WithdrawBalanceParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.WithdrawBalanceParams, *miner11.WithdrawBalanceParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.WithdrawBalanceParams, *miner10.WithdrawBalanceParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.WithdrawBalanceParams, *miner9.WithdrawBalanceParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.WithdrawBalanceParams, *miner8.WithdrawBalanceParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/miner/expected.json b/actors/miner/expected.json new file mode 100644 index 00000000..6a0820c4 --- /dev/null +++ b/actors/miner/expected.json @@ -0,0 +1,40 @@ +{ + "V1": { + "ChangeMultiaddrs": {}, + "ChangePeerID": {}, + "ChangeWorkerAddress": {}, + "ChangeOwnerAddress": {}, + "IsControllingAddressExported": {}, + "GetOwner": {}, + "GetPeerID": {}, + "GetMultiaddrs": {}, + "GetAvailableBalance": {}, + "GetVestingFunds": {}, + "ParseWithdrawBalance": {}, + "TerminateSectors": {}, + "DeclareFaults": {}, + "DeclareFaultsRecovered": {}, + "ProveReplicaUpdates": {}, + "PreCommitSectorBatch2": {}, + "ProveReplicaUpdates2": {}, + "ProveCommitAggregate": {}, + "DisputeWindowedPoSt": {}, + "ReportConsensusFault": {}, + "ChangeBeneficiary": {}, + "MinerConstructor": {}, + "ApplyRewards": {}, + "OnDeferredCronEvent": {}, + "ExtendSectorExpiration2": {}, + "PreCommitSector": {}, + "ProveCommitSector": {}, + "ProveCommitSectors3": {}, + "SubmitWindowedPoSt": {}, + "ConfirmSectorProofsValid": {}, + "CheckSectorProven": {}, + "ExtendSectorExpiration": {}, + "CompactSectorNumbers": {}, + "CompactPartitions": {}, + "PreCommitSectorBatch": {}, + "GetSectorSize": {} + } +} \ No newline at end of file diff --git a/actors/miner/generic.go b/actors/miner/generic.go new file mode 100644 index 00000000..8d80ebc1 --- /dev/null +++ b/actors/miner/generic.go @@ -0,0 +1,29 @@ +package miner + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parseGeneric[T minerParam, R minerReturn](rawParams, rawReturn []byte, customReturn bool) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(rawParams) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + if !customReturn { + return metadata, nil + } + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} diff --git a/actors/miner/miner.go b/actors/miner/miner.go new file mode 100644 index 00000000..10a2b78e --- /dev/null +++ b/actors/miner/miner.go @@ -0,0 +1,301 @@ +package miner + +import ( + "fmt" + + miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner" + miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" + miner12 "github.com/filecoin-project/go-state-types/builtin/v12/miner" + miner13 "github.com/filecoin-project/go-state-types/builtin/v13/miner" + miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner" + miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" + "github.com/zondax/fil-parser/tools" +) + +func (*Miner) TerminateSectors(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.TerminateSectorsParams, *miner15.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.TerminateSectorsParams, *miner14.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.TerminateSectorsParams, *miner13.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.TerminateSectorsParams, *miner12.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.TerminateSectorsParams, *miner11.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.TerminateSectorsParams, *miner10.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.TerminateSectorsParams, *miner9.TerminateSectorsReturn](rawParams, rawReturn, true) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.TerminateSectorsParams, *miner8.TerminateSectorsReturn](rawParams, rawReturn, true) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) DeclareFaults(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.DeclareFaultsParams, *miner15.DeclareFaultsParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.DeclareFaultsParams, *miner14.DeclareFaultsParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.DeclareFaultsParams, *miner13.DeclareFaultsParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.DeclareFaultsParams, *miner12.DeclareFaultsParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.DeclareFaultsParams, *miner11.DeclareFaultsParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.DeclareFaultsParams, *miner10.DeclareFaultsParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.DeclareFaultsParams, *miner9.DeclareFaultsParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.DeclareFaultsParams, *miner8.DeclareFaultsParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) DeclareFaultsRecovered(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.DeclareFaultsRecoveredParams, *miner15.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.DeclareFaultsRecoveredParams, *miner14.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.DeclareFaultsRecoveredParams, *miner13.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.DeclareFaultsRecoveredParams, *miner12.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.DeclareFaultsRecoveredParams, *miner11.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.DeclareFaultsRecoveredParams, *miner10.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.DeclareFaultsRecoveredParams, *miner9.DeclareFaultsRecoveredParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.DeclareFaultsRecoveredParams, *miner8.DeclareFaultsRecoveredParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ProveReplicaUpdates(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ProveReplicaUpdatesParams, *miner15.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ProveReplicaUpdatesParams, *miner14.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ProveReplicaUpdatesParams, *miner13.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ProveReplicaUpdatesParams, *miner12.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ProveReplicaUpdatesParams, *miner11.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ProveReplicaUpdatesParams, *miner10.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ProveReplicaUpdatesParams, *miner9.ProveReplicaUpdatesParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ProveReplicaUpdatesParams, *miner8.ProveReplicaUpdatesParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) PreCommitSectorBatch2(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.PreCommitSectorBatchParams2, *miner15.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.PreCommitSectorBatchParams2, *miner14.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.PreCommitSectorBatchParams2, *miner13.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.PreCommitSectorBatchParams2, *miner12.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.PreCommitSectorBatchParams2, *miner11.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.PreCommitSectorBatchParams2, *miner10.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.PreCommitSectorBatchParams2, *miner9.PreCommitSectorBatchParams2](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ProveReplicaUpdates2(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ProveReplicaUpdatesParams2, *miner15.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ProveReplicaUpdatesParams2, *miner14.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ProveReplicaUpdatesParams2, *miner13.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ProveReplicaUpdatesParams2, *miner12.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ProveReplicaUpdatesParams2, *miner11.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ProveReplicaUpdatesParams2, *miner10.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ProveReplicaUpdatesParams2, *miner9.ProveReplicaUpdatesParams2](rawParams, rawReturn, true) + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("unsupported height: %d", height) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ProveCommitAggregate(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ProveCommitAggregateParams, *miner15.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ProveCommitAggregateParams, *miner14.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ProveCommitAggregateParams, *miner13.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ProveCommitAggregateParams, *miner12.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ProveCommitAggregateParams, *miner11.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ProveCommitAggregateParams, *miner10.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ProveCommitAggregateParams, *miner9.ProveCommitAggregateParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ProveCommitAggregateParams, *miner8.ProveCommitAggregateParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) DisputeWindowedPoSt(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.DisputeWindowedPoStParams, *miner15.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.DisputeWindowedPoStParams, *miner14.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.DisputeWindowedPoStParams, *miner13.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.DisputeWindowedPoStParams, *miner12.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.DisputeWindowedPoStParams, *miner11.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.DisputeWindowedPoStParams, *miner10.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.DisputeWindowedPoStParams, *miner9.DisputeWindowedPoStParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.DisputeWindowedPoStParams, *miner8.DisputeWindowedPoStParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ReportConsensusFault(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ReportConsensusFaultParams, *miner15.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ReportConsensusFaultParams, *miner14.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ReportConsensusFaultParams, *miner13.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ReportConsensusFaultParams, *miner12.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ReportConsensusFaultParams, *miner11.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ReportConsensusFaultParams, *miner10.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ReportConsensusFaultParams, *miner9.ReportConsensusFaultParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ReportConsensusFaultParams, *miner8.ReportConsensusFaultParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ChangeBeneficiary(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ChangeBeneficiaryParams, *miner15.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ChangeBeneficiaryParams, *miner14.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ChangeBeneficiaryParams, *miner13.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ChangeBeneficiaryParams, *miner12.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ChangeBeneficiaryParams, *miner11.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ChangeBeneficiaryParams, *miner10.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ChangeBeneficiaryParams, *miner9.ChangeBeneficiaryParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) MinerConstructor(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.MinerConstructorParams, *miner15.MinerConstructorParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.MinerConstructorParams, *miner14.MinerConstructorParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.MinerConstructorParams, *miner13.MinerConstructorParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.MinerConstructorParams, *miner12.MinerConstructorParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.MinerConstructorParams, *miner11.MinerConstructorParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.MinerConstructorParams, *miner10.MinerConstructorParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.MinerConstructorParams, *miner9.MinerConstructorParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.MinerConstructorParams, *miner8.MinerConstructorParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ApplyRewards(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ApplyRewardParams, *miner15.ApplyRewardParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ApplyRewardParams, *miner14.ApplyRewardParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ApplyRewardParams, *miner13.ApplyRewardParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ApplyRewardParams, *miner12.ApplyRewardParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.ApplyRewardParams, *miner11.ApplyRewardParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ApplyRewardParams, *miner10.ApplyRewardParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ApplyRewardParams, *miner9.ApplyRewardParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ApplyRewardParams, *miner8.ApplyRewardParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) OnDeferredCronEvent(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.DeferredCronEventParams, *miner15.DeferredCronEventParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.DeferredCronEventParams, *miner14.DeferredCronEventParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.DeferredCronEventParams, *miner13.DeferredCronEventParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.DeferredCronEventParams, *miner12.DeferredCronEventParams](rawParams, nil, false) + case tools.V20.IsSupported(network, height): + return parseGeneric[*miner11.DeferredCronEventParams, *miner11.DeferredCronEventParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.DeferredCronEventParams, *miner10.DeferredCronEventParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.DeferredCronEventParams, *miner9.DeferredCronEventParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.DeferredCronEventParams, *miner8.DeferredCronEventParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/miner/miner_test.go b/actors/miner/miner_test.go new file mode 100644 index 00000000..10a0aaf8 --- /dev/null +++ b/actors/miner/miner_test.go @@ -0,0 +1,187 @@ +package miner_test + +import ( + _ "embed" + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/miner" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +type testFn func(network string, height int64, rawReturn []byte) (map[string]interface{}, error) + +//go:embed expected.json +var expected []byte +var expectedData map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expected, &expectedData); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + +func TestMiner(t *testing.T) { + miner := &miner.Miner{} + testFns := map[string]testFn{ + "DeclareFaults": miner.DeclareFaults, + "DeclareFaultsRecovered": miner.DeclareFaultsRecovered, + "ProveReplicaUpdates": miner.ProveReplicaUpdates, + "PreCommitSectorBatch2": miner.PreCommitSectorBatch2, + "ProveCommitAggregate": miner.ProveCommitAggregate, + "DisputeWindowedPoSt": miner.DisputeWindowedPoSt, + "ReportConsensusFault": miner.ReportConsensusFault, + "ChangeBeneficiary": miner.ChangeBeneficiary, + "MinerConstructor": miner.MinerConstructor, + "ApplyRewards": miner.ApplyRewards, + "OnDeferredCronEvent": miner.OnDeferredCronEvent, + "ChangeMultiaddrs": miner.ChangeMultiaddrs, + "ChangePeerID": miner.ChangePeerID, + "ChangeWorkerAddress": miner.ChangeWorkerAddress, + "ChangeOwnerAddress": miner.ChangeOwnerAddress, + "GetOwner": miner.GetOwner, + "GetPeerID": miner.GetPeerID, + "GetMultiaddrs": miner.GetMultiaddrs, + "GetAvailableBalance": miner.GetAvailableBalance, + "GetVestingFunds": miner.GetVestingFunds, + "ParseWithdrawBalance": miner.ParseWithdrawBalance, + "ExtendSectorExpiration2": miner.ExtendSectorExpiration2, + "PreCommitSector": miner.PreCommitSector, + "ProveCommitSector": miner.ProveCommitSector, + "SubmitWindowedPoSt": miner.SubmitWindowedPoSt, + "ConfirmSectorProofsValid": miner.ConfirmSectorProofsValid, + "CheckSectorProven": miner.CheckSectorProven, + "ExtendSectorExpiration": miner.ExtendSectorExpiration, + "CompactSectorNumbers": miner.CompactSectorNumbers, + "CompactPartitions": miner.CompactPartitions, + "PreCommitSectorBatch": miner.PreCommitSectorBatch, + "GetSectorSize": miner.GetSectorSize, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expectedData) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestTerminateSectors(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "TerminateSectors", expectedData) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + miner := &miner.Miner{} + result, err := miner.TerminateSectors(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func TestProveReplicaUpdates2(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "ProveReplicaUpdates2", expectedData) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + miner := &miner.Miner{} + result, err := miner.ProveReplicaUpdates2(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func TestIsControllingAddressExported(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "IsControllingAddressExported", expectedData) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + miner := &miner.Miner{} + result, err := miner.IsControllingAddressExported(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func TestProveCommitSectors3(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "ProveCommitSectors3", expectedData) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + miner := &miner.Miner{} + result, err := miner.ProveCommitSectors3(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} diff --git a/actors/miner/sector.go b/actors/miner/sector.go new file mode 100644 index 00000000..b724bcef --- /dev/null +++ b/actors/miner/sector.go @@ -0,0 +1,261 @@ +package miner + +import ( + "fmt" + + miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner" + miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" + miner12 "github.com/filecoin-project/go-state-types/builtin/v12/miner" + miner13 "github.com/filecoin-project/go-state-types/builtin/v13/miner" + miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner" + miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" + "github.com/zondax/fil-parser/tools" +) + +func (*Miner) ExtendSectorExpiration2(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ExtendSectorExpiration2Params, *miner15.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ExtendSectorExpiration2Params, *miner14.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ExtendSectorExpiration2Params, *miner13.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ExtendSectorExpiration2Params, *miner12.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.ExtendSectorExpiration2Params, *miner11.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ExtendSectorExpiration2Params, *miner10.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ExtendSectorExpiration2Params, *miner9.ExtendSectorExpiration2Params](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) PreCommitSector(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.PreCommitSectorParams, *miner15.PreCommitSectorParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.PreCommitSectorParams, *miner14.PreCommitSectorParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.PreCommitSectorParams, *miner13.PreCommitSectorParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.PreCommitSectorParams, *miner12.PreCommitSectorParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.PreCommitSectorParams, *miner11.PreCommitSectorParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.PreCommitSectorParams, *miner10.PreCommitSectorParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.PreCommitSectorParams, *miner9.PreCommitSectorParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.PreCommitSectorParams, *miner8.PreCommitSectorParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ProveCommitSector(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ProveCommitSectorParams, *miner15.ProveCommitSectorParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ProveCommitSectorParams, *miner14.ProveCommitSectorParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ProveCommitSectorParams, *miner13.ProveCommitSectorParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ProveCommitSectorParams, *miner12.ProveCommitSectorParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.ProveCommitSectorParams, *miner11.ProveCommitSectorParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ProveCommitSectorParams, *miner10.ProveCommitSectorParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ProveCommitSectorParams, *miner9.ProveCommitSectorParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ProveCommitSectorParams, *miner8.ProveCommitSectorParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ProveCommitSectors3(network string, height int64, rawParams, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ProveCommitSectors3Params, *miner15.ProveCommitSectors3Return](rawParams, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ProveCommitSectors3Params, *miner14.ProveCommitSectors3Return](rawParams, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ProveCommitSectors3Params, *miner13.ProveCommitSectors3Return](rawParams, rawReturn, true) + case tools.V21.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V19.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) SubmitWindowedPoSt(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.SubmitWindowedPoStParams, *miner15.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.SubmitWindowedPoStParams, *miner14.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.SubmitWindowedPoStParams, *miner13.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.SubmitWindowedPoStParams, *miner12.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.SubmitWindowedPoStParams, *miner11.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.SubmitWindowedPoStParams, *miner10.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.SubmitWindowedPoStParams, *miner9.SubmitWindowedPoStParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.SubmitWindowedPoStParams, *miner8.SubmitWindowedPoStParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ConfirmSectorProofsValid(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V23.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ConfirmSectorProofsParams, *miner13.ConfirmSectorProofsParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ConfirmSectorProofsParams, *miner12.ConfirmSectorProofsParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.ConfirmSectorProofsParams, *miner11.ConfirmSectorProofsParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ConfirmSectorProofsParams, *miner10.ConfirmSectorProofsParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ConfirmSectorProofsParams, *miner9.ConfirmSectorProofsParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ConfirmSectorProofsParams, *miner8.ConfirmSectorProofsParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) CheckSectorProven(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.CheckSectorProvenParams, *miner15.CheckSectorProvenParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.CheckSectorProvenParams, *miner14.CheckSectorProvenParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.CheckSectorProvenParams, *miner13.CheckSectorProvenParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.CheckSectorProvenParams, *miner12.CheckSectorProvenParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.CheckSectorProvenParams, *miner11.CheckSectorProvenParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.CheckSectorProvenParams, *miner10.CheckSectorProvenParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.CheckSectorProvenParams, *miner9.CheckSectorProvenParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.CheckSectorProvenParams, *miner8.CheckSectorProvenParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) ExtendSectorExpiration(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.ExtendSectorExpirationParams, *miner15.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.ExtendSectorExpirationParams, *miner14.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.ExtendSectorExpirationParams, *miner13.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.ExtendSectorExpirationParams, *miner12.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.ExtendSectorExpirationParams, *miner11.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.ExtendSectorExpirationParams, *miner10.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.ExtendSectorExpirationParams, *miner9.ExtendSectorExpirationParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.ExtendSectorExpirationParams, *miner8.ExtendSectorExpirationParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) CompactSectorNumbers(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.CompactSectorNumbersParams, *miner15.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.CompactSectorNumbersParams, *miner14.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.CompactSectorNumbersParams, *miner13.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.CompactSectorNumbersParams, *miner12.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.CompactSectorNumbersParams, *miner11.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.CompactSectorNumbersParams, *miner10.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.CompactSectorNumbersParams, *miner9.CompactSectorNumbersParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.CompactSectorNumbersParams, *miner8.CompactSectorNumbersParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) CompactPartitions(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.CompactPartitionsParams, *miner15.CompactPartitionsParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.CompactPartitionsParams, *miner14.CompactPartitionsParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.CompactPartitionsParams, *miner13.CompactPartitionsParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.CompactPartitionsParams, *miner12.CompactPartitionsParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.CompactPartitionsParams, *miner11.CompactPartitionsParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.CompactPartitionsParams, *miner10.CompactPartitionsParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.CompactPartitionsParams, *miner9.CompactPartitionsParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.CompactPartitionsParams, *miner8.CompactPartitionsParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) PreCommitSectorBatch(network string, height int64, rawParams []byte) (map[string]interface{}, error) { + switch { + case tools.V24.IsSupported(network, height): + return parseGeneric[*miner15.PreCommitSectorBatchParams, *miner15.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V23.IsSupported(network, height): + return parseGeneric[*miner14.PreCommitSectorBatchParams, *miner14.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V22.IsSupported(network, height): + return parseGeneric[*miner13.PreCommitSectorBatchParams, *miner13.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V21.IsSupported(network, height): + return parseGeneric[*miner12.PreCommitSectorBatchParams, *miner12.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V19.IsSupported(network, height): + return parseGeneric[*miner11.PreCommitSectorBatchParams, *miner11.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V18.IsSupported(network, height): + return parseGeneric[*miner10.PreCommitSectorBatchParams, *miner10.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V17.IsSupported(network, height): + return parseGeneric[*miner9.PreCommitSectorBatchParams, *miner9.PreCommitSectorBatchParams](rawParams, nil, false) + case tools.V16.IsSupported(network, height): + return parseGeneric[*miner8.PreCommitSectorBatchParams, *miner8.PreCommitSectorBatchParams](rawParams, nil, false) + } + return nil, fmt.Errorf("unsupported height: %d", height) +} + +func (*Miner) GetSectorSize(network string, height int64, rawReturn []byte) (map[string]interface{}, error) { + return nil, fmt.Errorf("unsupported height: %d", height) +} diff --git a/actors/miner/types.go b/actors/miner/types.go new file mode 100644 index 00000000..b3823985 --- /dev/null +++ b/actors/miner/types.go @@ -0,0 +1,11 @@ +package miner + +import "io" + +type minerParam interface { + UnmarshalCBOR(io.Reader) error +} + +type minerReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/multisig/expected.json b/actors/multisig/expected.json new file mode 100644 index 00000000..03b8f62c --- /dev/null +++ b/actors/multisig/expected.json @@ -0,0 +1,26 @@ +{ + "V1": { + "AddVerifierValue": {}, + "ChangeOwnerAddressValue": {}, + "ParseWithdrawBalanceValue": {}, + "ParseInvokeContractValue": {}, + "ParseAddSignerValue": {}, + "ParseApproveValue": {}, + "ParseCancelValue": {}, + "ChangeNumApprovalsThresholdValue": {}, + "ParseConstructorValue": {}, + "ParseLockBalanceValue": {}, + "ParseRemoveSignerValue": {}, + "ParseSendValue": {}, + "ParseSwapSignerValue": {}, + "ParseUniversalReceiverHookValue": {}, + "MsigConstructor": {}, + "MsigParams": {}, + "Approve": {}, + "Cancel": {}, + "RemoveSigner": {}, + "ChangeNumApprovalsThreshold": {}, + "LockBalance": {}, + "UniversalReceiverHook": {} + } +} \ No newline at end of file diff --git a/actors/multisig/generic.go b/actors/multisig/generic.go new file mode 100644 index 00000000..99df1bb5 --- /dev/null +++ b/actors/multisig/generic.go @@ -0,0 +1,85 @@ +package multisig + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + filTypes "github.com/filecoin-project/lotus/chain/types" + "github.com/zondax/fil-parser/parser" +) + +func parseWithMsigParser[T multisigParams, R multisigReturn](msg *parser.LotusMessage, + height int64, + key filTypes.TipSetKey, + fn ParseFn, + rawReturn []byte, + unmarshaller func(io.Reader, any) error, + customReturn bool, +) (map[string]interface{}, error) { + + metadata := make(map[string]interface{}) + params, err := fn(msg, height, key) + if err != nil { + return map[string]interface{}{}, err + } + metadata[parser.ParamsKey] = params + + if customReturn { + var r R + err = unmarshaller(bytes.NewReader(rawReturn), &r) + if err != nil { + return map[string]interface{}{}, err + } + metadata[parser.ReturnKey] = r + } + return metadata, nil + +} + +func parse[T multisigParams, P []byte | string](raw P, unmarshaller func(io.Reader, any) error) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + var params T + rawBytes, err := toBytes(raw) + if err != nil { + return map[string]interface{}{}, err + } + reader := bytes.NewReader(rawBytes) + err = unmarshaller(reader, ¶ms) + if err != nil { + return map[string]interface{}{}, err + } + metadata[parser.ParamsKey] = params + return metadata, nil +} + +func getValue[T multisigParams](height int64, raw map[string]interface{}) (interface{}, error) { + paramsRaw, ok := raw["Params"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("Params not found or not a map[string]interface{}") + } + + var v T + err := mapToStruct(paramsRaw, &v) + if err != nil { + return nil, err + } + return v, nil +} + +func jsonUnmarshaller[T multisigParams](reader io.Reader, to any) error { + err := json.NewDecoder(reader).Decode(to) + if err != nil { + return err + } + return nil +} + +func cborUnmarshaller[T multisigParams](reader io.Reader, to any) error { + return to.(T).UnmarshalCBOR(reader) +} + +func noopUnmarshaller[T multisigParams](reader io.Reader, to any) error { + return nil +} diff --git a/actors/multisig/multisig.go b/actors/multisig/multisig.go new file mode 100644 index 00000000..f7149334 --- /dev/null +++ b/actors/multisig/multisig.go @@ -0,0 +1,196 @@ +package multisig + +import ( + filTypes "github.com/filecoin-project/lotus/chain/types" + + "github.com/filecoin-project/go-state-types/abi" + multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig" + multisig11 "github.com/filecoin-project/go-state-types/builtin/v11/multisig" + multisig12 "github.com/filecoin-project/go-state-types/builtin/v12/multisig" + multisig13 "github.com/filecoin-project/go-state-types/builtin/v13/multisig" + multisig14 "github.com/filecoin-project/go-state-types/builtin/v14/multisig" + multisig15 "github.com/filecoin-project/go-state-types/builtin/v15/multisig" + multisig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" + multisig9 "github.com/filecoin-project/go-state-types/builtin/v9/multisig" + + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" +) + +type Msig struct{} + +func (*Msig) MsigConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig8.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig8.ConstructorParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig9.ConstructorParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig10.ConstructorParams]) + case tools.V20.IsSupported(network, height): + return parse[*multisig11.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig11.ConstructorParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig12.ConstructorParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig13.ConstructorParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig14.ConstructorParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.ConstructorParams, []byte](raw, cborUnmarshaller[*multisig15.ConstructorParams]) + } + return map[string]interface{}{}, nil +} + +func (*Msig) MsigParams(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parseWithMsigParser[*multisig8.ConstructorParams, *multisig8.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig8.ConstructorParams], false) + case tools.V17.IsSupported(network, height): + return parseWithMsigParser[*multisig9.ConstructorParams, *multisig9.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig9.ConstructorParams], false) + case tools.V18.IsSupported(network, height): + return parseWithMsigParser[*multisig10.ConstructorParams, *multisig10.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig10.ConstructorParams], false) + case tools.V20.IsSupported(network, height): + return parseWithMsigParser[*multisig11.ConstructorParams, *multisig11.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig11.ConstructorParams], false) + case tools.V21.IsSupported(network, height): + return parseWithMsigParser[*multisig12.ConstructorParams, *multisig12.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig12.ConstructorParams], false) + case tools.V22.IsSupported(network, height): + return parseWithMsigParser[*multisig13.ConstructorParams, *multisig13.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig13.ConstructorParams], false) + case tools.V23.IsSupported(network, height): + return parseWithMsigParser[*multisig14.ConstructorParams, *multisig14.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig14.ConstructorParams], false) + case tools.V24.IsSupported(network, height): + return parseWithMsigParser[*multisig15.ConstructorParams, *multisig15.ConstructorParams](msg, height, key, parser, nil, jsonUnmarshaller[*multisig15.ConstructorParams], false) + } + return map[string]interface{}{}, nil +} + +func (*Msig) Approve(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parseWithMsigParser[*multisig8.ApproveReturn, *multisig8.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig8.ApproveReturn], true) + case tools.V17.IsSupported(network, height): + return parseWithMsigParser[*multisig9.ApproveReturn, *multisig9.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig9.ApproveReturn], true) + case tools.V18.IsSupported(network, height): + return parseWithMsigParser[*multisig10.ApproveReturn, *multisig10.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig10.ApproveReturn], true) + case tools.V20.IsSupported(network, height): + return parseWithMsigParser[*multisig11.ApproveReturn, *multisig11.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig11.ApproveReturn], true) + case tools.V21.IsSupported(network, height): + return parseWithMsigParser[*multisig12.ApproveReturn, *multisig12.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig12.ApproveReturn], true) + case tools.V22.IsSupported(network, height): + return parseWithMsigParser[*multisig13.ApproveReturn, *multisig13.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig13.ApproveReturn], true) + case tools.V23.IsSupported(network, height): + return parseWithMsigParser[*multisig14.ApproveReturn, *multisig14.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig14.ApproveReturn], true) + case tools.V24.IsSupported(network, height): + return parseWithMsigParser[*multisig15.ApproveReturn, *multisig15.ApproveReturn](msg, height, key, parser, rawReturn, cborUnmarshaller[*multisig15.ApproveReturn], true) + } + return map[string]interface{}{}, nil +} + +func (*Msig) Cancel(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V17.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V18.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V20.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V21.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V22.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V23.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V24.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + } + return map[string]interface{}{}, nil +} + +func (*Msig) RemoveSigner(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V17.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V18.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V20.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V21.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V22.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V23.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + case tools.V24.IsSupported(network, height): + return parseWithMsigParser[metadataWithCbor, metadataWithCbor](msg, height, key, parser, rawReturn, noopUnmarshaller[metadataWithCbor], false) + } + return map[string]interface{}{}, nil +} + +func (*Msig) ChangeNumApprovalsThreshold(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig8.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig8.ChangeNumApprovalsThresholdParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig9.ChangeNumApprovalsThresholdParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig10.ChangeNumApprovalsThresholdParams]) + case tools.V20.IsSupported(network, height): + return parse[*multisig11.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig11.ChangeNumApprovalsThresholdParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig12.ChangeNumApprovalsThresholdParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig13.ChangeNumApprovalsThresholdParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig14.ChangeNumApprovalsThresholdParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.ChangeNumApprovalsThresholdParams, []byte](rawReturn, cborUnmarshaller[*multisig15.ChangeNumApprovalsThresholdParams]) + } + return map[string]interface{}{}, nil +} + +func (*Msig) LockBalance(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig8.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig8.LockBalanceParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig9.LockBalanceParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig10.LockBalanceParams]) + case tools.V20.IsSupported(network, height): + return parse[*multisig11.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig11.LockBalanceParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig12.LockBalanceParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig13.LockBalanceParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig14.LockBalanceParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.LockBalanceParams, []byte](rawReturn, cborUnmarshaller[*multisig15.LockBalanceParams]) + } + return map[string]interface{}{}, nil +} + +func (*Msig) UniversalReceiverHook(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser ParseFn) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V17.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V18.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V20.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V21.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V22.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V23.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + case tools.V24.IsSupported(network, height): + return parse[*abi.CborBytesTransparent, []byte](rawReturn, cborUnmarshaller[*abi.CborBytesTransparent]) + } + return map[string]interface{}{}, nil +} diff --git a/actors/multisig/multisig_test.go b/actors/multisig/multisig_test.go new file mode 100644 index 00000000..7a715bc5 --- /dev/null +++ b/actors/multisig/multisig_test.go @@ -0,0 +1,179 @@ +package multisig_test + +import ( + _ "embed" + "encoding/json" + "reflect" + "testing" + + filTypes "github.com/filecoin-project/lotus/chain/types" + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/multisig" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" + + typesV2 "github.com/zondax/fil-parser/parser/v2/types" +) + +type testFn func(network string, msg *parser.LotusMessage, height int64, key filTypes.TipSetKey, rawReturn []byte, parser multisig.ParseFn) (map[string]interface{}, error) +type valueTestFn func(network string, height int64, txMetadata string) (interface{}, error) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +func TestMsig(t *testing.T) { + multisig := &multisig.Msig{} + testFns := map[string]testFn{ + "Approve": multisig.Approve, + "Cancel": multisig.Cancel, + "RemoveSigner": multisig.RemoveSigner, + "ChangeNumApprovalsThreshold": multisig.ChangeNumApprovalsThreshold, + "LockBalance": multisig.LockBalance, + "UniversalReceiverHook": multisig.UniversalReceiverHook, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestValues(t *testing.T) { + multisig := &multisig.Msig{} + testFns := map[string]valueTestFn{ + "ChangeOwnerAddressValue": multisig.ChangeOwnerAddressValue, + "ParseWithdrawBalanceValue": multisig.ParseWithdrawBalanceValue, + "ParseInvokeContractValue": multisig.ParseInvokeContractValue, + "ParseAddSignerValue": multisig.ParseAddSignerValue, + "ParseApproveValue": multisig.ParseApproveValue, + "ParseCancelValue": multisig.ParseCancelValue, + "ChangeNumApprovalsThresholdValue": multisig.ChangeNumApprovalsThresholdValue, + "ParseConstructorValue": multisig.ParseConstructorValue, + "ParseLockBalanceValue": multisig.ParseLockBalanceValue, + "ParseRemoveSignerValue": multisig.ParseRemoveSignerValue, + "ParseSendValue": multisig.ParseSendValue, + "ParseSwapSignerValue": multisig.ParseSwapSignerValue, + "ParseUniversalReceiverHookValue": multisig.ParseUniversalReceiverHookValue, + "AddVerifierValue": multisig.AddVerifierValue, + } + + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runValueTest(t, fn, tests) + }) + } + +} + +func TestMsigConstructor(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "MsigConstructor", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + multisig := &multisig.Msig{} + result, err := multisig.MsigConstructor(tt.Network, tt.Height, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} +func TestMsigParams(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "MsigParams", expected) + require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + lotusMsg := &parser.LotusMessage{ + To: trace.Msg.To, + From: trace.Msg.From, + Method: trace.Msg.Method, + } + multisig := &multisig.Msig{} + result, err := multisig.MsigParams(tt.Network, lotusMsg, tt.Height, tt.TipsetKey, func(*parser.LotusMessage, int64, filTypes.TipSetKey) (string, error) { + return "", nil + }) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + lotusMsg := &parser.LotusMessage{ + To: trace.Msg.To, + From: trace.Msg.From, + Method: trace.Msg.Method, + } + result, err := fn(tt.Network, lotusMsg, tt.Height, tt.TipsetKey, trace.MsgRct.Return, func(*parser.LotusMessage, int64, filTypes.TipSetKey) (string, error) { + return "", nil + }) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} + +func runValueTest(t *testing.T, fn valueTestFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + // TODO: parse whole multisig tx first before calling this function + + result, err := fn(tt.Network, tt.Height, string(trace.Msg.Params)) + require.NoError(t, err) + require.True(t, reflect.DeepEqual(result, tt.Expected)) + } + }) + } +} diff --git a/actors/multisig/types.go b/actors/multisig/types.go new file mode 100644 index 00000000..05fd5987 --- /dev/null +++ b/actors/multisig/types.go @@ -0,0 +1,90 @@ +package multisig + +import ( + "io" + + filTypes "github.com/filecoin-project/lotus/chain/types" + "github.com/zondax/fil-parser/parser" +) + +type multisigParams interface { + UnmarshalCBOR(io.Reader) error +} + +type multisigReturn interface { + UnmarshalCBOR(io.Reader) error +} + +type ParseFn func(*parser.LotusMessage, int64, filTypes.TipSetKey) (string, error) + +type metadataWithCbor map[string]interface{} + +type WithCBOR struct{} + +type ChangeOwnerAddressParams struct { + WithCBOR + Params string `json:"Params"` +} + +// I decided omit ethLog because it's not needed +type InvokeContractParams struct { + WithCBOR + Params string `json:"Params"` + Return string `json:"Return"` +} + +type ApproveValue struct { + ID int `json:"ID"` + ProposalHash string `json:"ProposalHash"` + Return any `json:"Return"` +} + +type CancelValue struct { + WithCBOR + ID int `json:"ID"` + ProposalHash string `json:"ProposalHash"` +} + +type SendValue struct { + WithCBOR + Params interface{} `json:"Params"` +} + +type UniversalReceiverHookValue struct { + Type uint64 `json:"Type"` + Payload string `json:"Payload"` + Return UniversalReceiverHookReturnValue `json:"Return"` +} + +type UniversalReceiverHookParams struct { + Type_ int `json:"Type_"` + Payload string `json:"Payload"` +} + +type TransactionUniversalReceiverHookMetadata struct { + Params string `json:"Params"` + Return UniversalReceiverHookReturnValue `json:"Return"` +} + +type UniversalReceiverHookReturnValue struct { + AllocationResults UniversalReceiverHookResults `json:"AllocationResults"` + ExtensionResults UniversalReceiverHookResults `json:"ExtensionResults"` + NewAllocations []int `json:"NewAllocations"` +} + +type UniversalReceiverHookResults struct { + SuccessCount int `json:"SuccessCount"` + FailCodes interface{} `json:"FailCodes"` +} + +func (m metadataWithCbor) UnmarshalCBOR(reader io.Reader) error { + return nil +} + +func (w *WithCBOR) UnmarshalCBOR(reader io.Reader) error { + return nil +} + +func (w *WithCBOR) MarshalCBOR(writer io.Writer) error { + return nil +} diff --git a/actors/multisig/utils.go b/actors/multisig/utils.go new file mode 100644 index 00000000..cc6a3677 --- /dev/null +++ b/actors/multisig/utils.go @@ -0,0 +1,185 @@ +package multisig + +import ( + "encoding/json" + "errors" + "fmt" + + multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig" + multisig11 "github.com/filecoin-project/go-state-types/builtin/v11/multisig" + multisig12 "github.com/filecoin-project/go-state-types/builtin/v12/multisig" + multisig13 "github.com/filecoin-project/go-state-types/builtin/v13/multisig" + multisig14 "github.com/filecoin-project/go-state-types/builtin/v14/multisig" + multisig15 "github.com/filecoin-project/go-state-types/builtin/v15/multisig" + multisig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" + multisig9 "github.com/filecoin-project/go-state-types/builtin/v9/multisig" + "github.com/filecoin-project/go-state-types/exitcode" + "github.com/zondax/fil-parser/tools" +) + +func toBytes(raw any) ([]byte, error) { + switch v := raw.(type) { + case []byte: + return v, nil + case string: + return []byte(v), nil + } + return nil, errors.New("invalid type") +} + +func mapToStruct(m map[string]interface{}, v interface{}) error { + data, err := json.Marshal(m) + if err != nil { + return err + } + return json.Unmarshal(data, v) +} + +func getApproveReturn(network string, height int64, raw map[string]interface{}) (interface{}, error) { + var params ApproveValue + + returnRaw, ok := raw["Return"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("Return not found or not a map") + } + + applied, ok := returnRaw["Applied"].(bool) + if !ok { + return nil, fmt.Errorf("Applied not found or not a bool") + } + + code, ok := returnRaw["Code"].(float64) + if !ok { + return nil, fmt.Errorf("Code not found or not a float64") + } + + ret, ok := returnRaw["Ret"].(string) + if !ok { + return nil, fmt.Errorf("Ret not found or not a string") + } + + switch { + case tools.V8.IsSupported(network, height): + params.Return = multisig8.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V9.IsSupported(network, height): + params.Return = multisig9.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V10.IsSupported(network, height): + params.Return = multisig10.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V11.IsSupported(network, height): + params.Return = multisig11.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V12.IsSupported(network, height): + params.Return = multisig12.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V13.IsSupported(network, height): + params.Return = multisig13.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V14.IsSupported(network, height): + params.Return = multisig14.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + case tools.V15.IsSupported(network, height): + params.Return = multisig15.ApproveReturn{ + Applied: applied, + Code: exitcode.ExitCode(code), + Ret: []byte(ret), + } + } + + return params, nil +} + +func getCancelReturn(raw map[string]interface{}) (interface{}, error) { + paramsStr, ok := raw["Params"].(string) + if !ok { + return nil, fmt.Errorf("Params not found or not a string") + } + + var paramsRaw map[string]interface{} + err := json.Unmarshal([]byte(paramsStr), ¶msRaw) + if err != nil { + return nil, err + } + + var v CancelValue + err = mapToStruct(paramsRaw, &v) + if err != nil { + return nil, err + } + + return v, nil +} + +func getChangeNumApprovalsThresholdValue(network string, height int64, raw map[string]interface{}) (interface{}, error) { + paramsStr, ok := raw["Params"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("Params not found or not a map") + } + + var newValue uint64 + if newThreshold, ok := paramsStr["NewThreshold"].(float64); ok { + newValue = uint64(newThreshold) + } else { + return nil, fmt.Errorf("NewThreshold not found or not a number") + } + var v any + switch { + case tools.V8.IsSupported(network, height): + v = multisig8.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V9.IsSupported(network, height): + v = multisig9.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V10.IsSupported(network, height): + v = multisig10.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V11.IsSupported(network, height): + v = multisig11.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V12.IsSupported(network, height): + v = multisig12.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V13.IsSupported(network, height): + v = multisig13.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V14.IsSupported(network, height): + v = multisig14.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + case tools.V15.IsSupported(network, height): + v = multisig15.ChangeNumApprovalsThresholdParams{ + NewThreshold: newValue, + } + } + + return v, nil +} diff --git a/actors/multisig/values.go b/actors/multisig/values.go new file mode 100644 index 00000000..816dd808 --- /dev/null +++ b/actors/multisig/values.go @@ -0,0 +1,462 @@ +package multisig + +import ( + "encoding/json" + + multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig" + miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" + multisig11 "github.com/filecoin-project/go-state-types/builtin/v11/multisig" + multisig12 "github.com/filecoin-project/go-state-types/builtin/v12/multisig" + multisig13 "github.com/filecoin-project/go-state-types/builtin/v13/multisig" + multisig14 "github.com/filecoin-project/go-state-types/builtin/v14/multisig" + multisig15 "github.com/filecoin-project/go-state-types/builtin/v15/multisig" + multisig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" + multisig9 "github.com/filecoin-project/go-state-types/builtin/v9/multisig" + "github.com/zondax/fil-parser/tools" +) + +func (*Msig) ChangeOwnerAddressValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V17.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V18.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V19.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V21.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V22.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V23.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + case tools.V24.IsSupported(network, height): + return parse[*ChangeOwnerAddressParams, string](txMetadata, jsonUnmarshaller[*ChangeOwnerAddressParams]) + } + return nil, nil +} + +func (*Msig) ParseWithdrawBalanceValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V17.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V18.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V19.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V21.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V22.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V23.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + case tools.V24.IsSupported(network, height): + return parse[*miner11.WithdrawBalanceParams, string](txMetadata, jsonUnmarshaller[*miner11.WithdrawBalanceParams]) + } + return nil, nil +} + +func (*Msig) ParseInvokeContractValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V17.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V18.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V19.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V21.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V22.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V23.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + case tools.V24.IsSupported(network, height): + return parse[*InvokeContractParams, string](txMetadata, jsonUnmarshaller[*InvokeContractParams]) + } + return nil, nil +} + +func (*Msig) ParseAddSignerValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig11.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig11.AddSignerParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig9.AddSignerParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig10.AddSignerParams]) + case tools.V19.IsSupported(network, height): + return parse[*multisig11.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig11.AddSignerParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig12.AddSignerParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig13.AddSignerParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig14.AddSignerParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.AddSignerParams, string](txMetadata, jsonUnmarshaller[*multisig15.AddSignerParams]) + } + return nil, nil +} + +func (*Msig) ParseApproveValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V17.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V18.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V19.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V21.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V22.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V23.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + case tools.V24.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getApproveReturn(network, height, data) + } + } + return nil, nil +} + +func (*Msig) ParseCancelValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V17.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V18.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V19.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V21.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V22.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V23.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + case tools.V24.IsSupported(network, height): + if data, err := parse[metadataWithCbor, string](txMetadata, jsonUnmarshaller[metadataWithCbor]); err != nil { + return nil, err + } else { + return getCancelReturn(data) + } + } + return nil, nil +} + +func (*Msig) ChangeNumApprovalsThresholdValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig8.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig8.ChangeNumApprovalsThresholdParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig9.ChangeNumApprovalsThresholdParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig10.ChangeNumApprovalsThresholdParams]) + case tools.V19.IsSupported(network, height): + return parse[*multisig11.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig11.ChangeNumApprovalsThresholdParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig12.ChangeNumApprovalsThresholdParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig13.ChangeNumApprovalsThresholdParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig14.ChangeNumApprovalsThresholdParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.ChangeNumApprovalsThresholdParams, string](txMetadata, jsonUnmarshaller[*multisig15.ChangeNumApprovalsThresholdParams]) + } + return nil, nil +} + +func (*Msig) ParseConstructorValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + if data, err := parse[*multisig8.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig8.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig8.ConstructorParams](height, data) + } + case tools.V17.IsSupported(network, height): + if data, err := parse[*multisig9.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig9.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig9.ConstructorParams](height, data) + } + case tools.V18.IsSupported(network, height): + if data, err := parse[*multisig10.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig10.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig10.ConstructorParams](height, data) + } + case tools.V19.IsSupported(network, height): + if data, err := parse[*multisig11.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig11.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig11.ConstructorParams](height, data) + } + case tools.V21.IsSupported(network, height): + if data, err := parse[*multisig12.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig12.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig12.ConstructorParams](height, data) + } + case tools.V22.IsSupported(network, height): + if data, err := parse[*multisig13.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig13.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig13.ConstructorParams](height, data) + } + case tools.V23.IsSupported(network, height): + if data, err := parse[*multisig14.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig14.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig14.ConstructorParams](height, data) + } + case tools.V24.IsSupported(network, height): + if data, err := parse[*multisig15.ConstructorParams, string](txMetadata, jsonUnmarshaller[*multisig15.ConstructorParams]); err != nil { + return nil, err + } else { + return getValue[*multisig15.ConstructorParams](height, data) + } + } + return nil, nil +} + +func (*Msig) ParseLockBalanceValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + if data, err := parse[*multisig8.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig8.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig8.LockBalanceParams](height, data) + } + case tools.V17.IsSupported(network, height): + if data, err := parse[*multisig9.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig9.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig9.LockBalanceParams](height, data) + } + case tools.V18.IsSupported(network, height): + if data, err := parse[*multisig10.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig10.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig10.LockBalanceParams](height, data) + } + case tools.V19.IsSupported(network, height): + if data, err := parse[*multisig11.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig11.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig11.LockBalanceParams](height, data) + } + case tools.V21.IsSupported(network, height): + if data, err := parse[*multisig12.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig12.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig12.LockBalanceParams](height, data) + } + case tools.V22.IsSupported(network, height): + if data, err := parse[*multisig13.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig13.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig13.LockBalanceParams](height, data) + } + case tools.V23.IsSupported(network, height): + if data, err := parse[*multisig14.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig14.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig14.LockBalanceParams](height, data) + } + case tools.V24.IsSupported(network, height): + if data, err := parse[*multisig15.LockBalanceParams, string](txMetadata, jsonUnmarshaller[*multisig15.LockBalanceParams]); err != nil { + return nil, err + } else { + return getValue[*multisig15.LockBalanceParams](height, data) + } + } + return nil, nil +} + +func (*Msig) ParseRemoveSignerValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + if data, err := parse[*multisig8.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig8.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig8.RemoveSignerParams](height, data) + } + case tools.V17.IsSupported(network, height): + if data, err := parse[*multisig9.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig9.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig9.RemoveSignerParams](height, data) + } + case tools.V18.IsSupported(network, height): + if data, err := parse[*multisig10.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig10.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig10.RemoveSignerParams](height, data) + } + case tools.V19.IsSupported(network, height): + if data, err := parse[*multisig11.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig11.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig11.RemoveSignerParams](height, data) + } + case tools.V21.IsSupported(network, height): + if data, err := parse[*multisig12.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig12.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig12.RemoveSignerParams](height, data) + } + case tools.V22.IsSupported(network, height): + if data, err := parse[*multisig13.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig13.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig13.RemoveSignerParams](height, data) + } + case tools.V23.IsSupported(network, height): + if data, err := parse[*multisig14.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig14.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig14.RemoveSignerParams](height, data) + } + case tools.V24.IsSupported(network, height): + if data, err := parse[*multisig15.RemoveSignerParams, string](txMetadata, jsonUnmarshaller[*multisig15.RemoveSignerParams]); err != nil { + return nil, err + } else { + return getValue[*multisig15.RemoveSignerParams](height, data) + } + } + return nil, nil +} + +func (*Msig) ParseSendValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V17.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V18.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V19.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V21.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V22.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V23.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + case tools.V24.IsSupported(network, height): + return parse[*SendValue, string](txMetadata, jsonUnmarshaller[*SendValue]) + } + return nil, nil +} + +func (*Msig) ParseSwapSignerValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*multisig8.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig8.SwapSignerParams]) + case tools.V17.IsSupported(network, height): + return parse[*multisig9.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig9.SwapSignerParams]) + case tools.V18.IsSupported(network, height): + return parse[*multisig10.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig10.SwapSignerParams]) + case tools.V19.IsSupported(network, height): + return parse[*multisig11.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig11.SwapSignerParams]) + case tools.V21.IsSupported(network, height): + return parse[*multisig12.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig12.SwapSignerParams]) + case tools.V22.IsSupported(network, height): + return parse[*multisig13.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig13.SwapSignerParams]) + case tools.V23.IsSupported(network, height): + return parse[*multisig14.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig14.SwapSignerParams]) + case tools.V24.IsSupported(network, height): + return parse[*multisig15.SwapSignerParams, string](txMetadata, jsonUnmarshaller[*multisig15.SwapSignerParams]) + } + return nil, nil +} + +func (*Msig) ParseUniversalReceiverHookValue(network string, height int64, txMetadata string) (interface{}, error) { + var tx TransactionUniversalReceiverHookMetadata + err := json.Unmarshal([]byte(txMetadata), &tx) + if err != nil { + return nil, err + } + + var params UniversalReceiverHookParams + err = json.Unmarshal([]byte(tx.Params), ¶ms) + if err != nil { + return nil, err + } + + result := UniversalReceiverHookValue{ + Type: uint64(params.Type_), + Payload: params.Payload, + Return: tx.Return, + } + + return result, nil +} diff --git a/actors/multisig/verifier.go b/actors/multisig/verifier.go new file mode 100644 index 00000000..f5db9117 --- /dev/null +++ b/actors/multisig/verifier.go @@ -0,0 +1,35 @@ +package multisig + +import ( + verifreg10 "github.com/filecoin-project/go-state-types/builtin/v10/verifreg" + verifreg11 "github.com/filecoin-project/go-state-types/builtin/v11/verifreg" + verifreg12 "github.com/filecoin-project/go-state-types/builtin/v12/verifreg" + verifreg13 "github.com/filecoin-project/go-state-types/builtin/v13/verifreg" + verifreg14 "github.com/filecoin-project/go-state-types/builtin/v14/verifreg" + verifreg15 "github.com/filecoin-project/go-state-types/builtin/v15/verifreg" + verifreg8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" + verifreg9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg" + "github.com/zondax/fil-parser/tools" +) + +func (*Msig) AddVerifierValue(network string, height int64, txMetadata string) (interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifreg8.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg8.AddVerifierParams]) + case tools.V17.IsSupported(network, height): + return parse[*verifreg9.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg9.AddVerifierParams]) + case tools.V18.IsSupported(network, height): + return parse[*verifreg10.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg10.AddVerifierParams]) + case tools.V20.IsSupported(network, height): + return parse[*verifreg11.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg11.AddVerifierParams]) + case tools.V21.IsSupported(network, height): + return parse[*verifreg12.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg12.AddVerifierParams]) + case tools.V22.IsSupported(network, height): + return parse[*verifreg13.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg13.AddVerifierParams]) + case tools.V23.IsSupported(network, height): + return parse[*verifreg14.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg14.AddVerifierParams]) + case tools.V24.IsSupported(network, height): + return parse[*verifreg15.AddVerifierParams, string](txMetadata, jsonUnmarshaller[*verifreg15.AddVerifierParams]) + } + return nil, nil +} diff --git a/actors/multisig_types.go b/actors/multisig_types.go index 9092b138..78218ce3 100644 --- a/actors/multisig_types.go +++ b/actors/multisig_types.go @@ -1,6 +1,10 @@ package actors -import multisig2 "github.com/filecoin-project/go-state-types/builtin/v14/multisig" +import ( + "io" + + multisig2 "github.com/filecoin-project/go-state-types/builtin/v14/multisig" +) type ApproveValue struct { ID int `json:"ID"` @@ -45,6 +49,7 @@ type TransactionUniversalReceiverHookMetadata struct { } type ChangeOwnerAddressParams struct { + WithCBOR Params string `json:"Params"` } @@ -53,3 +58,14 @@ type InvokeContractParams struct { Params string `json:"Params"` Return string `json:"Return"` } + +type WithCBOR struct { +} + +func (w *WithCBOR) UnmarshalCBOR(reader io.Reader) error { + return nil +} + +func (w *WithCBOR) MarshalCBOR(writer io.Writer) error { + return nil +} diff --git a/actors/paymentChannel/expected.json b/actors/paymentChannel/expected.json new file mode 100644 index 00000000..a2fa5a1a --- /dev/null +++ b/actors/paymentChannel/expected.json @@ -0,0 +1,6 @@ +{ + "V1": { + "PaymentChannelConstructor": {}, + "UpdateChannelState": {} + } +} \ No newline at end of file diff --git a/actors/paymentChannel/generic.go b/actors/paymentChannel/generic.go new file mode 100644 index 00000000..114b0aa6 --- /dev/null +++ b/actors/paymentChannel/generic.go @@ -0,0 +1,19 @@ +package paymentchannel + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parse[T paymentChannelParams](raw []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var constructor T + err := constructor.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = constructor + return metadata, nil +} diff --git a/actors/paymentChannel/paymentChannel.go b/actors/paymentChannel/paymentChannel.go new file mode 100644 index 00000000..aaec79e6 --- /dev/null +++ b/actors/paymentChannel/paymentChannel.go @@ -0,0 +1,64 @@ +package paymentchannel + +import ( + "io" + + paychv10 "github.com/filecoin-project/go-state-types/builtin/v10/paych" + paychv11 "github.com/filecoin-project/go-state-types/builtin/v11/paych" + paychv12 "github.com/filecoin-project/go-state-types/builtin/v12/paych" + paychv13 "github.com/filecoin-project/go-state-types/builtin/v13/paych" + paychv14 "github.com/filecoin-project/go-state-types/builtin/v14/paych" + paychv15 "github.com/filecoin-project/go-state-types/builtin/v15/paych" + paychv8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" + paychv9 "github.com/filecoin-project/go-state-types/builtin/v9/paych" + "github.com/zondax/fil-parser/tools" +) + +type PaymentChannel struct{} +type paymentChannelParams interface { + UnmarshalCBOR(io.Reader) error +} + +func (*PaymentChannel) PaymentChannelConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*paychv8.ConstructorParams](raw) + case tools.V17.IsSupported(network, height): + return parse[*paychv9.ConstructorParams](raw) + case tools.V18.IsSupported(network, height): + return parse[*paychv10.ConstructorParams](raw) + case tools.V20.IsSupported(network, height): + return parse[*paychv11.ConstructorParams](raw) + case tools.V21.IsSupported(network, height): + return parse[*paychv12.ConstructorParams](raw) + case tools.V22.IsSupported(network, height): + return parse[*paychv13.ConstructorParams](raw) + case tools.V23.IsSupported(network, height): + return parse[*paychv14.ConstructorParams](raw) + case tools.V24.IsSupported(network, height): + return parse[*paychv15.ConstructorParams](raw) + } + return nil, nil +} + +func (*PaymentChannel) UpdateChannelState(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*paychv8.UpdateChannelStateParams](raw) + case tools.V17.IsSupported(network, height): + return parse[*paychv9.UpdateChannelStateParams](raw) + case tools.V18.IsSupported(network, height): + return parse[*paychv10.UpdateChannelStateParams](raw) + case tools.V20.IsSupported(network, height): + return parse[*paychv11.UpdateChannelStateParams](raw) + case tools.V21.IsSupported(network, height): + return parse[*paychv12.UpdateChannelStateParams](raw) + case tools.V22.IsSupported(network, height): + return parse[*paychv13.UpdateChannelStateParams](raw) + case tools.V23.IsSupported(network, height): + return parse[*paychv14.UpdateChannelStateParams](raw) + case tools.V24.IsSupported(network, height): + return parse[*paychv15.UpdateChannelStateParams](raw) + } + return nil, nil +} diff --git a/actors/paymentChannel/paymentChannel_test.go b/actors/paymentChannel/paymentChannel_test.go new file mode 100644 index 00000000..2ed2d9c6 --- /dev/null +++ b/actors/paymentChannel/paymentChannel_test.go @@ -0,0 +1,69 @@ +package paymentchannel_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + paymentchannel "github.com/zondax/fil-parser/actors/paymentChannel" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +type testFn func(network string, height int64, raw []byte) (map[string]interface{}, error) +type test struct { + name string + height int64 + version string + expected map[string]interface{} +} + +func TestPaymentChannel(t *testing.T) { + paymentchannel := &paymentchannel.PaymentChannel{} + testFns := map[string]testFn{ + "PaymentChannelConstructor": paymentchannel.PaymentChannelConstructor, + "UpdateChannelState": paymentchannel.UpdateChannelState, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + + } + }) + } +} diff --git a/actors/power/expected.json b/actors/power/expected.json new file mode 100644 index 00000000..1e9dc4ac --- /dev/null +++ b/actors/power/expected.json @@ -0,0 +1,15 @@ +{ + "V1": { + "CurrentTotalPower": {}, + "SubmitPoRepForBulkVerify": {}, + "PowerConstructor": {}, + "CreateMiner": {}, + "EnrollCronEvent": {}, + "UpdateClaimedPower": {}, + "UpdatePledgeTotal": {}, + "NetworkRawPower": {}, + "MinerRawPower": {}, + "MinerCount": {}, + "MinerConsensusCount": {} + } +} \ No newline at end of file diff --git a/actors/power/generic.go b/actors/power/generic.go new file mode 100644 index 00000000..bdaa14ad --- /dev/null +++ b/actors/power/generic.go @@ -0,0 +1,33 @@ +package power + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/types" +) + +func parse[T powerParams, R powerReturn](msg *parser.LotusMessage, raw, rawReturn []byte, customReturn bool) (map[string]interface{}, *types.AddressInfo, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var constructor T + err := constructor.UnmarshalCBOR(reader) + if err != nil { + return metadata, nil, err + } + + metadata[parser.ParamsKey] = constructor + if !customReturn { + return metadata, nil, nil + } + + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, nil, err + } + createdActor := getAddressInfo(r, msg) + metadata[parser.ReturnKey] = createdActor + return metadata, createdActor, nil +} diff --git a/actors/power/power.go b/actors/power/power.go new file mode 100644 index 00000000..e70d5ac8 --- /dev/null +++ b/actors/power/power.go @@ -0,0 +1,317 @@ +package power + +import ( + "fmt" + + "github.com/filecoin-project/go-state-types/abi" + powerv10 "github.com/filecoin-project/go-state-types/builtin/v10/power" + powerv11 "github.com/filecoin-project/go-state-types/builtin/v11/power" + powerv12 "github.com/filecoin-project/go-state-types/builtin/v12/power" + powerv13 "github.com/filecoin-project/go-state-types/builtin/v13/power" + powerv14 "github.com/filecoin-project/go-state-types/builtin/v14/power" + powerv15 "github.com/filecoin-project/go-state-types/builtin/v15/power" + powerv8 "github.com/filecoin-project/go-state-types/builtin/v8/power" + powerv9 "github.com/filecoin-project/go-state-types/builtin/v9/power" + "github.com/filecoin-project/go-state-types/proof" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/tools" +) + +type Power struct{} + +func (*Power) CurrentTotalPower(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*powerv8.CurrentTotalPowerReturn, *powerv8.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*powerv9.CurrentTotalPowerReturn, *powerv9.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.CurrentTotalPowerReturn, *powerv10.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.CurrentTotalPowerReturn, *powerv11.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.CurrentTotalPowerReturn, *powerv12.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.CurrentTotalPowerReturn, *powerv13.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.CurrentTotalPowerReturn, *powerv14.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.CurrentTotalPowerReturn, *powerv15.CurrentTotalPowerReturn](msg, raw, rawReturn, false) + return data, err + } + return nil, nil +} + +func (*Power) SubmitPoRepForBulkVerify(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + data, _, err := parse[*proof.SealVerifyInfo, *proof.SealVerifyInfo](msg, raw, rawReturn, false) + return data, err +} + +func (*Power) PowerConstructor(network string, height int64, msg *parser.LotusMessage, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*powerv8.MinerConstructorParams, *powerv8.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*powerv9.MinerConstructorParams, *powerv9.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.MinerConstructorParams, *powerv10.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.MinerConstructorParams, *powerv11.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.MinerConstructorParams, *powerv12.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.MinerConstructorParams, *powerv13.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.MinerConstructorParams, *powerv14.MinerConstructorParams](msg, raw, nil, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.MinerConstructorParams, *powerv15.MinerConstructorParams](msg, raw, nil, false) + return data, err + } + return nil, nil +} + +func (*Power) CreateMiner(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*powerv8.CreateMinerParams, *powerv8.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*powerv9.CreateMinerParams, *powerv9.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.CreateMinerParams, *powerv10.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.CreateMinerParams, *powerv11.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.CreateMinerParams, *powerv12.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.CreateMinerParams, *powerv13.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.CreateMinerParams, *powerv14.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.CreateMinerParams, *powerv15.CreateMinerReturn](msg, raw, rawReturn, true) + return data, err + } + return nil, nil +} + +func (*Power) EnrollCronEvent(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*powerv8.EnrollCronEventParams, *powerv8.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*powerv9.EnrollCronEventParams, *powerv9.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.EnrollCronEventParams, *powerv10.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.EnrollCronEventParams, *powerv11.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.EnrollCronEventParams, *powerv12.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.EnrollCronEventParams, *powerv13.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.EnrollCronEventParams, *powerv14.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.EnrollCronEventParams, *powerv15.EnrollCronEventParams](msg, raw, rawReturn, true) + return data, err + } + return nil, nil +} + +func (*Power) UpdateClaimedPower(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*powerv8.UpdateClaimedPowerParams, *powerv8.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*powerv9.UpdateClaimedPowerParams, *powerv9.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.UpdateClaimedPowerParams, *powerv10.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.UpdateClaimedPowerParams, *powerv11.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.UpdateClaimedPowerParams, *powerv12.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.UpdateClaimedPowerParams, *powerv13.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.UpdateClaimedPowerParams, *powerv14.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.UpdateClaimedPowerParams, *powerv15.UpdateClaimedPowerParams](msg, raw, rawReturn, true) + return data, err + } + return nil, nil +} + +func (*Power) UpdatePledgeTotal(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V17.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V18.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*abi.TokenAmount, *abi.TokenAmount](msg, raw, rawReturn, false) + return data, err + } + return nil, nil +} + +func (*Power) NetworkRawPower(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.NetworkRawPowerReturn, *powerv10.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.NetworkRawPowerReturn, *powerv11.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.NetworkRawPowerReturn, *powerv12.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.NetworkRawPowerReturn, *powerv13.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.NetworkRawPowerReturn, *powerv14.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.NetworkRawPowerReturn, *powerv15.NetworkRawPowerReturn](msg, raw, rawReturn, false) + return data, err + } + return nil, nil +} + +func (*Power) MinerRawPower(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.MinerRawPowerParams, *powerv10.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.MinerRawPowerParams, *powerv11.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.MinerRawPowerParams, *powerv12.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.MinerRawPowerParams, *powerv13.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.MinerRawPowerParams, *powerv14.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.MinerRawPowerParams, *powerv15.MinerRawPowerReturn](msg, raw, rawReturn, true) + return data, err + } + return nil, nil +} + +func (*Power) MinerCount(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.MinerCountReturn, *powerv10.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.MinerCountReturn, *powerv11.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.MinerCountReturn, *powerv12.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.MinerCountReturn, *powerv13.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.MinerCountReturn, *powerv14.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.MinerCountReturn, *powerv15.MinerCountReturn](msg, raw, rawReturn, false) + return data, err + } + return nil, nil +} + +func (*Power) MinerConsensusCount(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V18.IsSupported(network, height): + data, _, err := parse[*powerv10.MinerConsensusCountReturn, *powerv10.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V19.IsSupported(network, height): + data, _, err := parse[*powerv11.MinerConsensusCountReturn, *powerv11.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V21.IsSupported(network, height): + data, _, err := parse[*powerv12.MinerConsensusCountReturn, *powerv12.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V22.IsSupported(network, height): + data, _, err := parse[*powerv13.MinerConsensusCountReturn, *powerv13.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V23.IsSupported(network, height): + data, _, err := parse[*powerv14.MinerConsensusCountReturn, *powerv14.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + case tools.V24.IsSupported(network, height): + data, _, err := parse[*powerv15.MinerConsensusCountReturn, *powerv15.MinerConsensusCountReturn](msg, raw, rawReturn, false) + return data, err + } + return nil, nil +} diff --git a/actors/power/power_test.go b/actors/power/power_test.go new file mode 100644 index 00000000..007b3114 --- /dev/null +++ b/actors/power/power_test.go @@ -0,0 +1,102 @@ +package power_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/power" + "github.com/zondax/fil-parser/parser" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +type testFn func(network string, msg *parser.LotusMessage, height int64, raw, rawReturn []byte) (map[string]interface{}, error) + +func TestPower(t *testing.T) { + power := &power.Power{} + testFns := map[string]testFn{ + "CurrentTotalPower": power.CurrentTotalPower, + "SubmitPoRepForBulkVerify": power.SubmitPoRepForBulkVerify, + "CreateMiner": power.CreateMiner, + "EnrollCronEvent": power.EnrollCronEvent, + "UpdateClaimedPower": power.UpdateClaimedPower, + "UpdatePledgeTotal": power.UpdatePledgeTotal, + "NetworkRawPower": power.NetworkRawPower, + "MinerRawPower": power.MinerRawPower, + "MinerCount": power.MinerCount, + "MinerConsensusCount": power.MinerConsensusCount, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestPowerConstructor(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, "PowerConstructor", expected) + require.NoError(t, err) + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + lotusMsg := &parser.LotusMessage{ + To: trace.Msg.To, + From: trace.Msg.From, + Method: trace.Msg.Method, + } + power := &power.Power{} + result, err := power.PowerConstructor(tt.Network, tt.Height, lotusMsg, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + lotusMsg := &parser.LotusMessage{ + To: trace.Msg.To, + From: trace.Msg.From, + Method: trace.Msg.Method, + } + result, err := fn(tt.Network, lotusMsg, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/power/types.go b/actors/power/types.go new file mode 100644 index 00000000..a0fc7609 --- /dev/null +++ b/actors/power/types.go @@ -0,0 +1,11 @@ +package power + +import "io" + +type powerParams interface { + UnmarshalCBOR(io.Reader) error +} + +type powerReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/power/utils.go b/actors/power/utils.go new file mode 100644 index 00000000..24867cf9 --- /dev/null +++ b/actors/power/utils.go @@ -0,0 +1,46 @@ +package power + +import ( + "github.com/filecoin-project/go-address" + powerv10 "github.com/filecoin-project/go-state-types/builtin/v10/power" + powerv11 "github.com/filecoin-project/go-state-types/builtin/v11/power" + powerv12 "github.com/filecoin-project/go-state-types/builtin/v12/power" + powerv13 "github.com/filecoin-project/go-state-types/builtin/v13/power" + powerv14 "github.com/filecoin-project/go-state-types/builtin/v14/power" + powerv15 "github.com/filecoin-project/go-state-types/builtin/v15/power" + powerv8 "github.com/filecoin-project/go-state-types/builtin/v8/power" + powerv9 "github.com/filecoin-project/go-state-types/builtin/v9/power" + "github.com/ipfs/go-cid" + "github.com/zondax/fil-parser/parser" + "github.com/zondax/fil-parser/types" +) + +func getAddressInfo(r powerReturn, msg *parser.LotusMessage) *types.AddressInfo { + createAddressInfo := func(idAddress, robustAddress address.Address, cid cid.Cid) *types.AddressInfo { + return &types.AddressInfo{ + Short: idAddress.String(), + Robust: robustAddress.String(), + ActorType: "miner", + CreationTxCid: cid.String(), + } + } + switch r := r.(type) { + case *powerv8.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv9.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv10.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv11.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv12.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv13.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv14.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + case *powerv15.CreateMinerReturn: + return createAddressInfo(r.IDAddress, r.RobustAddress, msg.Cid) + } + return nil +} diff --git a/actors/reward/expected.json b/actors/reward/expected.json new file mode 100644 index 00000000..1b30035e --- /dev/null +++ b/actors/reward/expected.json @@ -0,0 +1,8 @@ +{ + "V1": { + "RewardConstructor": {}, + "AwardBlockReward": {}, + "UpdateNetworkKPI": {}, + "ThisEpochReward": {} + } +} \ No newline at end of file diff --git a/actors/reward/generic.go b/actors/reward/generic.go new file mode 100644 index 00000000..3d482b90 --- /dev/null +++ b/actors/reward/generic.go @@ -0,0 +1,19 @@ +package reward + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parse[T rewardParams](raw []byte) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + return metadata, nil +} diff --git a/actors/reward/reward.go b/actors/reward/reward.go new file mode 100644 index 00000000..f6c52f44 --- /dev/null +++ b/actors/reward/reward.go @@ -0,0 +1,68 @@ +package reward + +import ( + "github.com/filecoin-project/go-state-types/abi" + rewardv10 "github.com/filecoin-project/go-state-types/builtin/v10/reward" + rewardv11 "github.com/filecoin-project/go-state-types/builtin/v11/reward" + rewardv12 "github.com/filecoin-project/go-state-types/builtin/v12/reward" + rewardv13 "github.com/filecoin-project/go-state-types/builtin/v13/reward" + rewardv14 "github.com/filecoin-project/go-state-types/builtin/v14/reward" + rewardv15 "github.com/filecoin-project/go-state-types/builtin/v15/reward" + rewardv8 "github.com/filecoin-project/go-state-types/builtin/v8/reward" + rewardv9 "github.com/filecoin-project/go-state-types/builtin/v9/reward" + "github.com/zondax/fil-parser/tools" +) + +type Reward struct{} + +func (*Reward) RewardConstructor(network string, height int64, raw []byte) (map[string]interface{}, error) { + return parse[*abi.StoragePower](raw) +} + +func (*Reward) AwardBlockReward(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*rewardv8.AwardBlockRewardParams](raw) + case tools.V17.IsSupported(network, height): + return parse[*rewardv9.AwardBlockRewardParams](raw) + case tools.V18.IsSupported(network, height): + return parse[*rewardv10.AwardBlockRewardParams](raw) + case tools.V20.IsSupported(network, height): + return parse[*rewardv11.AwardBlockRewardParams](raw) + case tools.V21.IsSupported(network, height): + return parse[*rewardv12.AwardBlockRewardParams](raw) + case tools.V22.IsSupported(network, height): + return parse[*rewardv13.AwardBlockRewardParams](raw) + case tools.V23.IsSupported(network, height): + return parse[*rewardv14.AwardBlockRewardParams](raw) + case tools.V24.IsSupported(network, height): + return parse[*rewardv15.AwardBlockRewardParams](raw) + } + return nil, nil +} + +func (*Reward) UpdateNetworkKPI(network string, height int64, raw []byte) (map[string]interface{}, error) { + return parse[*abi.StoragePower](raw) +} + +func (*Reward) ThisEpochReward(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*rewardv8.ThisEpochRewardReturn](raw) + case tools.V17.IsSupported(network, height): + return parse[*rewardv9.ThisEpochRewardReturn](raw) + case tools.V18.IsSupported(network, height): + return parse[*rewardv10.ThisEpochRewardReturn](raw) + case tools.V20.IsSupported(network, height): + return parse[*rewardv11.ThisEpochRewardReturn](raw) + case tools.V21.IsSupported(network, height): + return parse[*rewardv12.ThisEpochRewardReturn](raw) + case tools.V22.IsSupported(network, height): + return parse[*rewardv13.ThisEpochRewardReturn](raw) + case tools.V23.IsSupported(network, height): + return parse[*rewardv14.ThisEpochRewardReturn](raw) + case tools.V24.IsSupported(network, height): + return parse[*rewardv15.ThisEpochRewardReturn](raw) + } + return nil, nil +} diff --git a/actors/reward/reward_test.go b/actors/reward/reward_test.go new file mode 100644 index 00000000..956586c4 --- /dev/null +++ b/actors/reward/reward_test.go @@ -0,0 +1,64 @@ +package reward_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + "github.com/zondax/fil-parser/actors/reward" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +type testFn func(network string, height int64, raw []byte) (map[string]interface{}, error) + +func TestReward(t *testing.T) { + reward := &reward.Reward{} + testFns := map[string]testFn{ + "RewardConstructor": reward.RewardConstructor, + "AwardBlockReward": reward.AwardBlockReward, + "UpdateNetworkKPI": reward.UpdateNetworkKPI, + "ThisEpochReward": reward.ThisEpochReward, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/actors/reward/types.go b/actors/reward/types.go new file mode 100644 index 00000000..0448ba5f --- /dev/null +++ b/actors/reward/types.go @@ -0,0 +1,7 @@ +package reward + +import "io" + +type rewardParams interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/verifiedRegistry.go b/actors/verifiedRegistry.go index a51153d7..e182ece8 100644 --- a/actors/verifiedRegistry.go +++ b/actors/verifiedRegistry.go @@ -2,6 +2,7 @@ package actors import ( "bytes" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/builtin/v11/verifreg" "github.com/zondax/fil-parser/parser" diff --git a/actors/verifiedRegistry/expected.json b/actors/verifiedRegistry/expected.json new file mode 100644 index 00000000..30f7af14 --- /dev/null +++ b/actors/verifiedRegistry/expected.json @@ -0,0 +1,18 @@ +{ + "V1": { + "AddVerifier": {}, + "RemoveVerifier": {}, + "AddVerifiedClient": {}, + "UseBytes": {}, + "RestoreBytes": {}, + "RemoveVerifiedClientDataCap": {}, + "RemoveExpiredAllocations": {}, + "Deprecated1": {}, + "Deprecated2": {}, + "ClaimAllocations": {}, + "GetClaims": {}, + "ExtendClaimTerms": {}, + "RemoveExpiredClaims": {}, + "VerifregUniversalReceiverHook": {} + } +} \ No newline at end of file diff --git a/actors/verifiedRegistry/generic.go b/actors/verifiedRegistry/generic.go new file mode 100644 index 00000000..349236e1 --- /dev/null +++ b/actors/verifiedRegistry/generic.go @@ -0,0 +1,29 @@ +package verifiedregistry + +import ( + "bytes" + + "github.com/zondax/fil-parser/parser" +) + +func parse[T verifiedRegistryParams, R verifiedRegistryReturn](raw, rawReturn []byte, customReturn bool) (map[string]interface{}, error) { + metadata := make(map[string]interface{}) + reader := bytes.NewReader(raw) + var params T + err := params.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ParamsKey] = params + if customReturn { + return metadata, nil + } + reader = bytes.NewReader(rawReturn) + var r R + err = r.UnmarshalCBOR(reader) + if err != nil { + return metadata, err + } + metadata[parser.ReturnKey] = r + return metadata, nil +} diff --git a/actors/verifiedRegistry/types.go b/actors/verifiedRegistry/types.go new file mode 100644 index 00000000..f15f9e3c --- /dev/null +++ b/actors/verifiedRegistry/types.go @@ -0,0 +1,11 @@ +package verifiedregistry + +import "io" + +type verifiedRegistryParams interface { + UnmarshalCBOR(io.Reader) error +} + +type verifiedRegistryReturn interface { + UnmarshalCBOR(io.Reader) error +} diff --git a/actors/verifiedRegistry/verifiedRegistry.go b/actors/verifiedRegistry/verifiedRegistry.go new file mode 100644 index 00000000..c7af9788 --- /dev/null +++ b/actors/verifiedRegistry/verifiedRegistry.go @@ -0,0 +1,309 @@ +package verifiedregistry + +import ( + "fmt" + + "github.com/filecoin-project/go-address" + verifregv10 "github.com/filecoin-project/go-state-types/builtin/v10/verifreg" + verifregv11 "github.com/filecoin-project/go-state-types/builtin/v11/verifreg" + verifregv12 "github.com/filecoin-project/go-state-types/builtin/v12/verifreg" + verifregv13 "github.com/filecoin-project/go-state-types/builtin/v13/verifreg" + verifregv14 "github.com/filecoin-project/go-state-types/builtin/v14/verifreg" + verifregv15 "github.com/filecoin-project/go-state-types/builtin/v15/verifreg" + verifregv8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" + verifregv9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg" + + "github.com/zondax/fil-parser/tools" +) + +type VerifiedRegistry struct{} + +func (*VerifiedRegistry) AddVerifier(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.AddVerifierParams, *verifregv8.AddVerifierParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.AddVerifierParams, *verifregv9.AddVerifierParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.AddVerifierParams, *verifregv10.AddVerifierParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.AddVerifierParams, *verifregv11.AddVerifierParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.AddVerifierParams, *verifregv12.AddVerifierParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.AddVerifierParams, *verifregv13.AddVerifierParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.AddVerifierParams, *verifregv14.AddVerifierParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.AddVerifierParams, *verifregv15.AddVerifierParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) RemoveVerifier(network string, height int64, raw []byte) (map[string]interface{}, error) { + return parse[*address.Address, *address.Address](raw, nil, false) +} + +func (*VerifiedRegistry) AddVerifiedClient(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.AddVerifiedClientParams, *verifregv8.AddVerifiedClientParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.AddVerifiedClientParams, *verifregv9.AddVerifiedClientParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.AddVerifiedClientParams, *verifregv10.AddVerifiedClientParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.AddVerifiedClientParams, *verifregv11.AddVerifiedClientParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.AddVerifiedClientParams, *verifregv12.AddVerifiedClientParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.AddVerifiedClientParams, *verifregv13.AddVerifiedClientParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.AddVerifiedClientParams, *verifregv14.AddVerifiedClientParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.AddVerifiedClientParams, *verifregv15.AddVerifiedClientParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) UseBytes(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.UseBytesParams, *verifregv8.UseBytesParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.UseBytesParams, *verifregv9.UseBytesParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.UseBytesParams, *verifregv10.UseBytesParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.UseBytesParams, *verifregv11.UseBytesParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.UseBytesParams, *verifregv12.UseBytesParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.UseBytesParams, *verifregv13.UseBytesParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.UseBytesParams, *verifregv14.UseBytesParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.UseBytesParams, *verifregv15.UseBytesParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) RestoreBytes(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.RestoreBytesParams, *verifregv8.RestoreBytesParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.RestoreBytesParams, *verifregv9.RestoreBytesParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.RestoreBytesParams, *verifregv10.RestoreBytesParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.RestoreBytesParams, *verifregv11.RestoreBytesParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.RestoreBytesParams, *verifregv12.RestoreBytesParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.RestoreBytesParams, *verifregv13.RestoreBytesParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.RestoreBytesParams, *verifregv14.RestoreBytesParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.RestoreBytesParams, *verifregv15.RestoreBytesParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) RemoveVerifiedClientDataCap(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.DataCap, *verifregv8.DataCap](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.DataCap, *verifregv9.DataCap](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.DataCap, *verifregv10.DataCap](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.DataCap, *verifregv11.DataCap](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.DataCap, *verifregv12.DataCap](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.DataCap, *verifregv13.DataCap](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.DataCap, *verifregv14.DataCap](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.DataCap, *verifregv15.DataCap](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) RemoveExpiredAllocations(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.RemoveExpiredAllocationsParams, *verifregv9.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.RemoveExpiredAllocationsParams, *verifregv10.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.RemoveExpiredAllocationsParams, *verifregv11.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.RemoveExpiredAllocationsParams, *verifregv12.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.RemoveExpiredAllocationsParams, *verifregv13.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.RemoveExpiredAllocationsParams, *verifregv14.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.RemoveExpiredAllocationsParams, *verifregv15.RemoveExpiredAllocationsReturn](raw, rawReturn, true) + } + return nil, nil +} + +func (*VerifiedRegistry) Deprecated1(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.RestoreBytesParams, *verifregv8.RestoreBytesParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.RestoreBytesParams, *verifregv9.RestoreBytesParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.RestoreBytesParams, *verifregv10.RestoreBytesParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.RestoreBytesParams, *verifregv11.RestoreBytesParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.RestoreBytesParams, *verifregv12.RestoreBytesParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.RestoreBytesParams, *verifregv13.RestoreBytesParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.RestoreBytesParams, *verifregv14.RestoreBytesParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.RestoreBytesParams, *verifregv15.RestoreBytesParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) Deprecated2(network string, height int64, raw []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return parse[*verifregv8.UseBytesParams, *verifregv8.UseBytesParams](raw, nil, false) + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.UseBytesParams, *verifregv9.UseBytesParams](raw, nil, false) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.UseBytesParams, *verifregv10.UseBytesParams](raw, nil, false) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.UseBytesParams, *verifregv11.UseBytesParams](raw, nil, false) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.UseBytesParams, *verifregv12.UseBytesParams](raw, nil, false) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.UseBytesParams, *verifregv13.UseBytesParams](raw, nil, false) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.UseBytesParams, *verifregv14.UseBytesParams](raw, nil, false) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.UseBytesParams, *verifregv15.UseBytesParams](raw, nil, false) + } + return nil, nil +} + +func (*VerifiedRegistry) ClaimAllocations(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.ClaimAllocationsParams, *verifregv9.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.ClaimAllocationsParams, *verifregv10.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.ClaimAllocationsParams, *verifregv11.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.ClaimAllocationsParams, *verifregv12.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.ClaimAllocationsParams, *verifregv13.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.ClaimAllocationsParams, *verifregv14.ClaimAllocationsReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.ClaimAllocationsParams, *verifregv15.ClaimAllocationsReturn](raw, rawReturn, true) + } + return nil, nil +} + +func (*VerifiedRegistry) GetClaims(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.GetClaimsParams, *verifregv9.GetClaimsReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.GetClaimsParams, *verifregv10.GetClaimsReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.GetClaimsParams, *verifregv11.GetClaimsReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.GetClaimsParams, *verifregv12.GetClaimsReturn](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.GetClaimsParams, *verifregv13.GetClaimsReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.GetClaimsParams, *verifregv14.GetClaimsReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.GetClaimsParams, *verifregv15.GetClaimsReturn](raw, rawReturn, true) + } + return nil, nil +} + +func (*VerifiedRegistry) ExtendClaimTerms(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.ExtendClaimTermsParams, *verifregv9.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.ExtendClaimTermsParams, *verifregv10.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.ExtendClaimTermsParams, *verifregv11.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.ExtendClaimTermsParams, *verifregv12.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.ExtendClaimTermsParams, *verifregv13.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.ExtendClaimTermsParams, *verifregv14.ExtendClaimTermsReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.ExtendClaimTermsParams, *verifregv15.ExtendClaimTermsReturn](raw, rawReturn, true) + } + return nil, nil +} + +func (*VerifiedRegistry) RemoveExpiredClaims(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.RemoveExpiredClaimsParams, *verifregv9.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.RemoveExpiredClaimsParams, *verifregv10.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.RemoveExpiredClaimsParams, *verifregv11.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.RemoveExpiredClaimsParams, *verifregv12.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.RemoveExpiredClaimsParams, *verifregv13.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.RemoveExpiredClaimsParams, *verifregv14.RemoveExpiredClaimsReturn](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.RemoveExpiredClaimsParams, *verifregv15.RemoveExpiredClaimsReturn](raw, rawReturn, true) + } + return nil, nil +} + +func (*VerifiedRegistry) VerifregUniversalReceiverHook(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) { + switch { + case tools.V16.IsSupported(network, height): + return nil, fmt.Errorf("not supported") + case tools.V17.IsSupported(network, height): + return parse[*verifregv9.UniversalReceiverParams, *verifregv9.AllocationsResponse](raw, rawReturn, true) + case tools.V18.IsSupported(network, height): + return parse[*verifregv10.UniversalReceiverParams, *verifregv10.AllocationsResponse](raw, rawReturn, true) + case tools.V19.IsSupported(network, height): + return parse[*verifregv11.UniversalReceiverParams, *verifregv11.AllocationsResponse](raw, rawReturn, true) + case tools.V21.IsSupported(network, height): + return parse[*verifregv12.UniversalReceiverParams, *verifregv12.AllocationsResponse](raw, rawReturn, true) + case tools.V22.IsSupported(network, height): + return parse[*verifregv13.UniversalReceiverParams, *verifregv13.AllocationsResponse](raw, rawReturn, true) + case tools.V23.IsSupported(network, height): + return parse[*verifregv14.UniversalReceiverParams, *verifregv14.AllocationsResponse](raw, rawReturn, true) + case tools.V24.IsSupported(network, height): + return parse[*verifregv15.UniversalReceiverParams, *verifregv15.AllocationsResponse](raw, rawReturn, true) + } + return nil, nil +} diff --git a/actors/verifiedRegistry/verifiedRegistry_test.go b/actors/verifiedRegistry/verifiedRegistry_test.go new file mode 100644 index 00000000..de00fddf --- /dev/null +++ b/actors/verifiedRegistry/verifiedRegistry_test.go @@ -0,0 +1,107 @@ +package verifiedregistry_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + verifiedregistry "github.com/zondax/fil-parser/actors/verifiedRegistry" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" + "github.com/zondax/fil-parser/tools" +) + +//go:embed expected.json +var expectedData []byte +var expected map[string]any + +var network string + +func TestMain(m *testing.M) { + network = "mainnet" + if err := json.Unmarshal(expectedData, &expected); err != nil { + panic(err) + } + m.Run() +} + +type testFn func(network string, height int64, raw []byte) (map[string]interface{}, error) +type testFn2 func(network string, height int64, raw, rawReturn []byte) (map[string]interface{}, error) + +func TestVerifiedRegistry(t *testing.T) { + verifiedregistry := &verifiedregistry.VerifiedRegistry{} + testFns := map[string]testFn{ + "AddVerifier": verifiedregistry.AddVerifier, + "RemoveVerifier": verifiedregistry.RemoveVerifier, + "AddVerifiedClient": verifiedregistry.AddVerifiedClient, + "UseBytes": verifiedregistry.UseBytes, + "RestoreBytes": verifiedregistry.RestoreBytes, + "RemoveVerifiedClientDataCap": verifiedregistry.RemoveVerifiedClientDataCap, + "Deprecated1": verifiedregistry.Deprecated1, + "Deprecated2": verifiedregistry.Deprecated2, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest(t, fn, tests) + }) + } +} + +func TestVerifiedRegistry2(t *testing.T) { + verifiedregistry := &verifiedregistry.VerifiedRegistry{} + testFns := map[string]testFn2{ + "ClaimAllocations": verifiedregistry.ClaimAllocations, + "GetClaims": verifiedregistry.GetClaims, + "ExtendClaimTerms": verifiedregistry.ExtendClaimTerms, + "RemoveExpiredClaims": verifiedregistry.RemoveExpiredClaims, + "VerifregUniversalReceiverHook": verifiedregistry.VerifregUniversalReceiverHook, + "RemoveExpiredAllocations": verifiedregistry.RemoveExpiredAllocations, + } + for name, fn := range testFns { + t.Run(name, func(t *testing.T) { + tests, err := tools.LoadTestData[map[string]any](network, name, expected) + require.NoError(t, err) + runTest2(t, fn, tests) + }) + } +} + +func runTest(t *testing.T, fn testFn, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} + +func runTest2(t *testing.T, fn testFn2, tests []tools.TestCase[map[string]any]) { + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + computeState, err := tools.ComputeState[typesV2.ComputeStateOutputV2](tt.Height, tt.Version) + require.NoError(t, err) + + for _, trace := range computeState.Trace { + if trace.Msg == nil { + continue + } + + result, err := fn(tt.Network, tt.Height, trace.Msg.Params, trace.MsgRct.Return) + require.NoError(t, err) + require.True(t, tools.CompareResult(result, tt.Expected)) + } + }) + } +} diff --git a/cmd/tracedl/cli.go b/cmd/tracedl/cli.go index 3b6734ff..c1b361a0 100644 --- a/cmd/tracedl/cli.go +++ b/cmd/tracedl/cli.go @@ -3,6 +3,7 @@ package main import ( "bytes" "compress/gzip" + "encoding/json" "fmt" "io" "io/fs" @@ -13,6 +14,8 @@ import ( lotusChainTypes "github.com/filecoin-project/lotus/chain/types" "github.com/klauspost/compress/s2" "github.com/spf13/cobra" + "github.com/zondax/fil-parser/actors/account" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" "github.com/zondax/golem/pkg/cli" "go.uber.org/zap" ) @@ -28,10 +31,38 @@ func GetStartCommand(c *cli.CLI) *cobra.Command { cmd.Flags().String("type", "traces", "--type trace") cmd.Flags().String("outPath", ".", "--outPath ../") cmd.Flags().String("compress", "gz", "--compress s2") - cmd.Flags().Uint64("height", 0, "--height 387926") + + cmd.Flags().UintSlice("heights", []uint{0}, "--heights 387926,387927,387928") return cmd } +func getTrace(height uint64, logType string, rpcClient *RPCClient) ([]byte, error) { + var data any + var err error + switch logType { + case "traces": + data, err = getTraceFileByHeight(height, rpcClient.client) + case "tipset": + data, err = getTipsetFileByHeight(height, lotusChainTypes.EmptyTSK, rpcClient.client) + case "ethlog": + data, err = getEthLogsByHeight(height, rpcClient.client) + case "nativelog": + data, err = getNativeLogsByHeight(height, rpcClient.client) + case "metadata": + data, err = getMetadata(rpcClient) + } + + if err != nil { + return nil, err + } + + dataJson, err := sonic.Marshal(data) + if err != nil { + return nil, err + } + return dataJson, nil +} + func get(c *cli.CLI, cmd *cobra.Command, _ []string) { zap.S().Infof(c.GetVersionString()) @@ -55,57 +86,50 @@ func get(c *cli.CLI, cmd *cobra.Command, _ []string) { zap.S().Errorf("Error loading compress: %s", err) return } - height, err := cmd.Flags().GetUint64("height") - if err != nil { - zap.S().Errorf("Error loading height: %s", err) - return - } - - rpcClient, err := newFilecoinRPCClient(config.NodeURL, config.NodeToken) - if err != nil { - zap.S().Error(err) - return - } - - var data any - switch logType { - case "traces": - data, err = getTraceFileByHeight(height, rpcClient.client) - case "tipset": - data, err = getTipsetFileByHeight(height, lotusChainTypes.EmptyTSK, rpcClient.client) - case "ethlog": - data, err = getEthLogsByHeight(height, rpcClient.client) - case "nativelog": - data, err = getNativeLogsByHeight(height, rpcClient.client) - case "metadata": - data, err = getMetadata(rpcClient) - } + heights, err := cmd.Flags().GetUintSlice("heights") if err != nil { - zap.S().Error(err) + zap.S().Errorf("Error loading heights: %s", err) return } - dataJson, err := sonic.Marshal(data) + rpcClient, err := newFilecoinRPCClient(config.NodeURL, config.NodeToken) if err != nil { zap.S().Error(err) return } + if len(heights) > 0 { + for _, tmp := range heights { + height := uint64(tmp) + dataJson, err := getTrace(height, logType, rpcClient) + if err != nil { + zap.S().Error(err) + return + } + actorJson, err := DownloadActorJSON(height, dataJson) + if err != nil { + zap.S().Error(err) + continue + } + fmt.Println(string(actorJson)) + + out := dataJson + fname := fmt.Sprintf("%s_%d.json", logType, height) + if format != "" { + out, err = compress(format, dataJson) + if err != nil { + zap.S().Error(err) + return + } + fname = fmt.Sprintf("%s_%d.json.%s", logType, height, format) + } + + if err := writeToFile(outPath, fname, out); err != nil { + zap.S().Error(err) + return + } - out := dataJson - fname := fmt.Sprintf("%s_%d.json", logType, height) - if format != "" { - out, err = compress(format, dataJson) - if err != nil { - zap.S().Error(err) - return } - fname = fmt.Sprintf("%s_%d.json.%s", logType, height, format) - } - - if err := writeToFile(outPath, fname, out); err != nil { - zap.S().Error(err) - return } } @@ -144,3 +168,26 @@ func compress(format string, data []byte) ([]byte, error) { return b.Bytes(), nil } + +func DownloadActorJSON(height uint64, traces []byte) ([]byte, error) { + var computeState *typesV2.ComputeStateOutputV2 + err := sonic.Unmarshal(traces, &computeState) + if err != nil { + return nil, err + } + if len(computeState.Trace) == 0 { + return nil, fmt.Errorf("no traces found") + } + resp, err := account.AuthenticateMessage("mainnet", 10000, computeState.Trace[0].Msg.Params, computeState.Trace[0].MsgRct.Return) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp) + if err != nil { + return nil, err + } + if string(data) == "{}" { + return nil, fmt.Errorf("no data found") + } + return data, nil +} diff --git a/cmd/tracedl/pkg.go b/cmd/tracedl/pkg.go new file mode 100644 index 00000000..310bae84 --- /dev/null +++ b/cmd/tracedl/pkg.go @@ -0,0 +1,126 @@ +package main + +import ( + "fmt" + "reflect" +) + +// FunctionInfo holds information about an exported function +type FunctionInfo struct { + Name string + NumParams int + ParamTypes []reflect.Type + ReturnTypes []reflect.Type +} + +// PackageExporter handles discovery and execution of exported functions +type PackageExporter struct { + pkg interface{} + functionCache map[string]reflect.Value + functionInfo map[string]FunctionInfo +} + +// NewPackageExporter creates a new PackageExporter instance +func NewPackageExporter(pkg interface{}) *PackageExporter { + pe := &PackageExporter{ + pkg: pkg, + functionCache: make(map[string]reflect.Value), + functionInfo: make(map[string]FunctionInfo), + } + pe.discoverFunctions() + return pe +} + +// discoverFunctions finds all exported functions and caches their information +func (pe *PackageExporter) discoverFunctions() { + pkgType := reflect.TypeOf(pe.pkg) + pkgValue := reflect.ValueOf(pe.pkg) + + for i := 0; i < pkgType.NumMethod(); i++ { + method := pkgType.Method(i) + if !method.IsExported() { + continue + } + + methodType := method.Type + info := FunctionInfo{ + Name: method.Name, + NumParams: methodType.NumIn() - 1, // subtract 1 for receiver + ParamTypes: make([]reflect.Type, methodType.NumIn()-1), + ReturnTypes: make([]reflect.Type, methodType.NumOut()), + } + + // Get parameter types + for j := 1; j < methodType.NumIn(); j++ { // start from 1 to skip receiver + info.ParamTypes[j-1] = methodType.In(j) + } + + // Get return types + for j := 0; j < methodType.NumOut(); j++ { + info.ReturnTypes[j] = methodType.Out(j) + } + + pe.functionInfo[method.Name] = info + pe.functionCache[method.Name] = pkgValue.Method(i) + } +} + +// GetExportedFunctions returns information about all exported functions +func (pe *PackageExporter) GetExportedFunctions() []FunctionInfo { + functions := make([]FunctionInfo, 0, len(pe.functionInfo)) + for _, info := range pe.functionInfo { + functions = append(functions, info) + } + return functions +} + +// CallFunction calls an exported function by name with the provided arguments +func (pe *PackageExporter) CallFunction(functionName string, args ...interface{}) ([]interface{}, error) { + // Check if function exists + method, exists := pe.functionCache[functionName] + if !exists { + return nil, fmt.Errorf("function %s not found", functionName) + } + + info := pe.functionInfo[functionName] + + // Check number of arguments + if len(args) != info.NumParams { + return nil, fmt.Errorf("function %s expects %d arguments, got %d", + functionName, info.NumParams, len(args)) + } + + // Convert and type check arguments + reflectArgs := make([]reflect.Value, len(args)) + for i, arg := range args { + argValue := reflect.ValueOf(arg) + expectedType := info.ParamTypes[i] + + if !argValue.Type().AssignableTo(expectedType) { + return nil, fmt.Errorf("argument %d type mismatch: expected %v, got %v", + i, expectedType, argValue.Type()) + } + reflectArgs[i] = argValue + } + + // Call the function + results := method.Call(reflectArgs) + + // Convert results to interface slice + returnValues := make([]interface{}, len(results)) + for i, result := range results { + returnValues[i] = result.Interface() + } + + // Check if the last return value is an error + if len(results) > 0 { + lastResult := results[len(results)-1] + if lastResult.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !lastResult.IsNil() { + return returnValues[:len(returnValues)-1], lastResult.Interface().(error) + } + } + } + + return returnValues, nil +} diff --git a/go.mod b/go.mod index fe45b2a0..d1dc48cd 100644 --- a/go.mod +++ b/go.mod @@ -88,12 +88,12 @@ require ( github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 // indirect github.com/filecoin-project/go-hamt-ipld/v3 v3.4.0 // indirect github.com/filecoin-project/go-jsonrpc v0.7.1 - github.com/filecoin-project/specs-actors/v2 v2.3.6 // indirect - github.com/filecoin-project/specs-actors/v3 v3.1.2 // indirect - github.com/filecoin-project/specs-actors/v4 v4.0.2 // indirect - github.com/filecoin-project/specs-actors/v5 v5.0.6 // indirect - github.com/filecoin-project/specs-actors/v6 v6.0.2 // indirect - github.com/filecoin-project/specs-actors/v7 v7.0.1 // indirect + github.com/filecoin-project/specs-actors/v2 v2.3.6 + github.com/filecoin-project/specs-actors/v3 v3.1.2 + github.com/filecoin-project/specs-actors/v4 v4.0.2 + github.com/filecoin-project/specs-actors/v5 v5.0.6 + github.com/filecoin-project/specs-actors/v6 v6.0.2 + github.com/filecoin-project/specs-actors/v7 v7.0.1 github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gbrlsnchs/jwt/v3 v3.0.1 // indirect github.com/go-chi/chi/v5 v5.0.11 // indirect diff --git a/tools/testutil.go b/tools/testutil.go new file mode 100644 index 00000000..8299f179 --- /dev/null +++ b/tools/testutil.go @@ -0,0 +1,200 @@ +package tools + +import ( + "bytes" + "compress/gzip" + "context" + "fmt" + "net/http" + "os" + "reflect" + "strconv" + + "github.com/bytedance/sonic" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/api/client" + filTypes "github.com/filecoin-project/lotus/chain/types" + "github.com/zondax/fil-parser/types" + rosettaFilecoinLib "github.com/zondax/rosetta-filecoin-lib" +) + +const ( + dataPath = "../../data/heights" + fileDataExtension = "json.gz" + tracesPrefix = "traces" + tipsetPrefix = "tipset" + ethLogPrefix = "ethlog" + nativeLogPrefix = "nativelog" + NodeUrl = "https://node-fil-mainnet-next.zondax.ch/rpc/v1" + calibNextNodeUrl = "https://hel1-node-fil-calibration-stable.zondax.ch/rpc/v1" + feeType = "fee" +) + +func getLotusClient(url string) (api.FullNode, error) { + lotusClient, _, err := client.NewFullNodeRPCV1(context.Background(), url, http.Header{}) + if err != nil { + return nil, err + } + return lotusClient, nil +} + +func GetLib(nodeURL string) (*rosettaFilecoinLib.RosettaConstructionFilecoin, error) { + lotusClient, err := getLotusClient(nodeURL) + if err != nil { + return nil, err + } + + lib := rosettaFilecoinLib.NewRosettaConstructionFilecoin(lotusClient) + return lib, nil +} + +func getFilename(prefix string, height int64) string { + return fmt.Sprintf(`%s/%s_%d.%s`, dataPath, prefix, height, fileDataExtension) +} + +func tracesFilename(height int64) string { + return getFilename(tracesPrefix, height) +} + +func ehtlogFilename(height int64) string { + return getFilename(ethLogPrefix, height) +} + +func nativeLogFilename(height int64) string { + return getFilename(nativeLogPrefix, height) +} + +func tipsetFilename(height int64) string { + return getFilename(tipsetPrefix, height) +} + +func read[T any](fileNameFn func(height int64) string, height int64) (*T, error) { + raw, err := readGzFile(fileNameFn(height)) + if err != nil { + return nil, err + } + var r T + err = sonic.Unmarshal(raw, &r) + if err != nil { + return nil, err + } + return &r, nil +} + +func readGzFile(fileName string) ([]byte, error) { + file, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer file.Close() + gzipReader, err := gzip.NewReader(file) + if err != nil { + return nil, err + } + defer gzipReader.Close() + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(gzipReader) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func ReadTipset(height int64) (*types.ExtendedTipSet, error) { + return read[types.ExtendedTipSet](tipsetFilename, height) +} + +func ReadEthLogs(height int64) ([]types.EthLog, error) { + logs, err := read[[]types.EthLog](ehtlogFilename, height) + if err != nil { + return nil, err + } + return *logs, nil +} + +func ReadNativeLogs(height int64) ([]*filTypes.ActorEvent, error) { + events, err := read[[]*filTypes.ActorEvent](nativeLogFilename, height) + if err != nil { + return nil, err + } + return *events, nil +} + +func ReadTraces(height int64) ([]byte, error) { + return readGzFile(tracesFilename(height)) +} + +func ComputeState[T any](height int64, version string) (*T, error) { + traces, err := ReadTraces(height) + if err != nil { + return nil, err + } + + var computeState T + err = sonic.UnmarshalString(string(traces), &computeState) + if err != nil { + return nil, err + } + return &computeState, nil + +} + +func CompareResult(result1, result2 map[string]any) bool { + return reflect.DeepEqual(result1, result2) +} + +type TestCase[T any] struct { + Name string + Version string + Url string + Height int64 + Network string + TipsetKey filTypes.TipSetKey + Expected T + Address *types.AddressInfo +} + +func LoadTestData[T any](network string, fnName string, expected map[string]any) ([]TestCase[T], error) { + var tests []TestCase[T] + versions := GetSupportedVersions(network) + for _, version := range versions { + + versionData := expected[version.String()] + if versionData == nil { + return nil, fmt.Errorf("version %s not found in expected data", version.String()) + } + tmp, ok := versionData.(map[string]any) + if !ok { + return nil, fmt.Errorf("version %s not found in expected data", version.String()) + } + fnData := tmp[fnName] + + if fnData == nil { + return nil, fmt.Errorf("function %s not found in version %s", fnName, version.String()) + } + + height := version.Height() + if version != version.next() { + height = (version.Height() + version.next().Height()) / 2 + } + if version.Height() == 0 { + height = V8.Height() + } else { + height += 100 + } + + if !version.IsSupported(network, height) { + fmt.Println("skipping", version.String(), height) + continue + } + + tests = append(tests, TestCase[T]{ + Name: fnName + "_" + version.String() + "_" + strconv.FormatInt(height, 10), + Version: version.String(), + Url: NodeUrl, + Height: height, + Expected: fnData.(T), + }) + } + return tests, nil +} diff --git a/tools/tools_test.go b/tools/tools_test.go index b33a8bed..ed76a7a8 100644 --- a/tools/tools_test.go +++ b/tools/tools_test.go @@ -6,6 +6,7 @@ import ( filTypes "github.com/filecoin-project/lotus/chain/types" "github.com/stretchr/testify/require" + typesV2 "github.com/zondax/fil-parser/parser/v2/types" ) func TestBuildTipSetKeyHash(t *testing.T) { @@ -34,6 +35,60 @@ func TestBuildTipSetKeyHash(t *testing.T) { } } +func TestIsSupported(t *testing.T) { + tests := []struct { + name string + version version + network string + height int64 + want bool + }{ + + {name: "V7 on calibration", version: V7, network: "calibration", height: 2383680, want: false}, + {name: "V7 on mainnet", version: V7, network: "mainnet", height: 170000, want: false}, + {name: "V7 on calibration", version: V7, network: "calibration", height: 0, want: false}, + {name: "V7 on mainnet", version: V7, network: "mainnet", height: 10000, want: true}, + + {name: "V9 on calibration", version: V9, network: "calibration", height: 265100, want: false}, + {name: "V9 on mainnet", version: V9, network: "mainnet", height: 265201, want: true}, + {name: "V9 on calibration", version: V9, network: "calibration", height: 265200, want: false}, + {name: "V9 on mainnet", version: V9, network: "mainnet", height: 265200, want: false}, + + {name: "V24 on calibration", version: V24, network: "calibration", height: 2081674, want: true}, + {name: "V24 on mainnet", version: V24, network: "mainnet", height: 1427974, want: false}, + {name: "V24 on calibration", version: V24, network: "calibration", height: 2081672, want: false}, + {name: "V24 on mainnet", version: V24, network: "mainnet", height: 4461240, want: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, tt.version.IsSupported(tt.network, tt.height)) + }) + } +} + +func TestDownloadTraces(t *testing.T) { + versions := GetSupportedVersions("mainnet") + + for _, version := range versions { + height := version.Height() + if version != version.next() { + height = (version.Height() + version.next().Height()) / 2 + } + if version.Height() == 0 { + height = V8.Height() + } else { + height += 100 + } + + traces, err := ReadTraces(height) + require.NoError(t, err) + require.NotEmpty(t, traces) + _, err = ComputeState[typesV2.ComputeStateOutputV2](height, version.String()) + require.NoError(t, err) + require.NotEmpty(t, traces) + } +} + /* func TestBuildCidFromMessageTrace(t *testing.T) { h1, err := multihash.Sum([]byte("TEST"), multihash.SHA2_256, -1) diff --git a/tools/version_mapping.go b/tools/version_mapping.go new file mode 100644 index 00000000..e3fcb61e --- /dev/null +++ b/tools/version_mapping.go @@ -0,0 +1,121 @@ +package tools + +import "fmt" + +type version struct { + calibration int64 + mainnet int64 + + nodeVersion int64 + currentNetwork string +} + +var ( + supportedVersions = []version{V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24} + V1 version = version{calibration: 0, mainnet: 0, nodeVersion: 1} + V2 version = version{calibration: 0, mainnet: 0, nodeVersion: 2} + V3 version = version{calibration: 0, mainnet: 0, nodeVersion: 3} + V4 version = version{calibration: 0, mainnet: 0, nodeVersion: 4} + V5 version = version{calibration: 0, mainnet: 0, nodeVersion: 5} + V6 version = version{calibration: 0, mainnet: 0, nodeVersion: 6} + V7 version = version{calibration: 0, mainnet: 0, nodeVersion: 7} + V8 version = version{calibration: 0, mainnet: 170000, nodeVersion: 8} + V9 version = version{calibration: 0, mainnet: 265200, nodeVersion: 9} + V10 version = version{calibration: 0, mainnet: 550321, nodeVersion: 10} + V11 version = version{calibration: 0, mainnet: 665280, nodeVersion: 11} + V12 version = version{calibration: 193789, mainnet: 712320, nodeVersion: 12} + V13 version = version{calibration: 0, mainnet: 892800, nodeVersion: 13} // calibration reset + V14 version = version{calibration: 312746, mainnet: 1231620, nodeVersion: 14} + V15 version = version{calibration: 682006, mainnet: 1594680, nodeVersion: 15} + V16 version = version{calibration: 1044660, mainnet: 1960320, nodeVersion: 16} + V17 version = version{calibration: 16800, mainnet: 2383680, nodeVersion: 17} // calibration reset + V18 version = version{calibration: 322354, mainnet: 2683348, nodeVersion: 18} + V19 version = version{calibration: 489094, mainnet: 2809800, nodeVersion: 19} + V20 version = version{calibration: 492214, mainnet: 2809800, nodeVersion: 20} + V21 version = version{calibration: 1108174, mainnet: 3469380, nodeVersion: 21} + V22 version = version{calibration: 1427974, mainnet: 3817920, nodeVersion: 22} + V23 version = version{calibration: 1779094, mainnet: 4154640, nodeVersion: 23} + V24 version = version{calibration: 2081674, mainnet: 4461240, nodeVersion: 24} + LatestVersion version = V24 +) + +func (v version) IsSupported(network string, height int64) bool { + if network == "calibration" { + if height >= LatestVersion.calibration { + return v == LatestVersion + } + // check if the height is greater than the current version but less than the next version + if height > v.calibration && height < v.next().calibration { + return true + } + } else { + if height >= LatestVersion.mainnet { + return v == LatestVersion + } + // check if the height is greater than the current version but less than the next version + if height > v.mainnet && height < v.next().mainnet { + return true + } + } + + return false +} + +func AnyIsSupported(network string, height int64, versions ...version) bool { + for _, v := range versions { + if v.IsSupported(network, height) { + return true + } + } + return false +} + +func (v version) next() version { + for i, version := range supportedVersions { + if version.nodeVersion == v.nodeVersion { + if i == len(supportedVersions)-1 { + return v + } + return supportedVersions[i+1] + } + } + return v +} + +func (v version) String() string { + return fmt.Sprintf("V%d", v.nodeVersion) +} + +func (v version) Height() int64 { + if v.currentNetwork == "calibration" { + return v.calibration + } + return v.mainnet +} + +func GetSupportedVersions(network string) []version { + var result []version + for _, v := range supportedVersions { + v.currentNetwork = network + result = append(result, v) + } + return result +} + +func VersionsBefore(version version) []version { + for i, v := range supportedVersions { + if v.nodeVersion == version.nodeVersion { + return supportedVersions[:i+1] + } + } + return nil +} + +func VersionsAfter(version version) []version { + for i, v := range supportedVersions { + if v.nodeVersion == version.nodeVersion { + return supportedVersions[i:] + } + } + return nil +}