diff --git a/actors/address.go b/actors/address.go index 7d7181fd..274ead3a 100644 --- a/actors/address.go +++ b/actors/address.go @@ -4,12 +4,21 @@ import ( "fmt" "github.com/filecoin-project/go-address" - "github.com/zondax/fil-parser/actors/cache" "github.com/zondax/fil-parser/actors/cache/impl/common" + "github.com/zondax/fil-parser/parser/helper" "github.com/zondax/golem/pkg/logger" ) -func ConsolidateRobustAddress(addr address.Address, actorCache cache.IActorsCache, logger *logger.Logger, bestEffort bool) (string, error) { +// ConsolidateToRobustAddress consolidates an address to a robust address +// if the address is a zero address account actor, it returns the robust address of the zero address account actor +// if the address is already a robust address, it returns the address +// if the address is f2 evm, we consolidate f2 -> f0 -> f4 +func ConsolidateToRobustAddress(addr address.Address, h *helper.Helper, logger *logger.Logger, bestEffort bool) (string, error) { + actorCache := h.GetActorsCache() + if ok, _, _ := h.IsZeroAddressAccountActor(addr); ok { + return helper.ZeroAddressAccountActorRobust, nil + } + if isRobust, _ := common.IsRobustAddress(addr); isRobust { // we need to handle cases where a f2 address for evm actors is used // f2 -> f0 -> f4, as we want to consolidate the address to f4 style diff --git a/actors/v2/init/parse.go b/actors/v2/init/parse.go index 79b4fe7a..d0d93e4c 100644 --- a/actors/v2/init/parse.go +++ b/actors/v2/init/parse.go @@ -10,7 +10,7 @@ import ( "github.com/zondax/fil-parser/types" ) -func (i *Init) Parse(_ context.Context, network string, height int64, txType string, msg *parser.LotusMessage, msgRct *parser.LotusMessageReceipt, _ cid.Cid, _ filTypes.TipSetKey) (map[string]interface{}, *types.AddressInfo, error) { +func (i *Init) Parse(_ context.Context, network string, height int64, txType string, msg *parser.LotusMessage, msgRct *parser.LotusMessageReceipt, mainMsgCid cid.Cid, _ filTypes.TipSetKey) (map[string]interface{}, *types.AddressInfo, error) { var err error metadata := make(map[string]interface{}) switch txType { diff --git a/actors/v2/multisig/multisig.go b/actors/v2/multisig/multisig.go index e5cbdf0b..530f1325 100644 --- a/actors/v2/multisig/multisig.go +++ b/actors/v2/multisig/multisig.go @@ -71,44 +71,51 @@ func (m *Msig) Propose(network string, msg *parser.LotusMessage, height int64, p if err != nil { return nil, err } + applied, innerReturnRaw, innerReturnParsed, err := getProposeReturn(network, height, rawReturn) + if err != nil { + return nil, err + } - method, innerParams, err := m.innerProposeParams(msg, to, network, height, methodNum, innerParamsRaw, key) + method, innerMsg, err := m.parseInnerProposeMsg(msg, to, network, height, methodNum, innerParamsRaw, innerReturnRaw, key) if err != nil { _ = m.metrics.UpdateMultisigProposeMetric(manifest.MultisigKey, proposeKind, fmt.Sprint(methodNum)) m.logger.Errorf("could not decode multisig inner params. Method: %v. Err: %v", methodNum.String(), err) } - params := innerParams - // get ParamsKey for innerParams if possible - if innerParams != nil && innerParams[parser.ParamsKey] != nil { - params, err = m.paramsToMap(innerParams[parser.ParamsKey]) - if err != nil { - return nil, err - } - } - - metadata[parser.ParamsKey] = parser.MultisigPropose{ + proposalData := parser.MultisigPropose{ To: to.String(), Value: value, Method: method, - Params: params, + Params: innerMsg, } - version := tools.VersionFromHeight(network, height) - r, ok := proposeReturn[version.String()] - if !ok { - return map[string]interface{}{}, fmt.Errorf("proposeReturn: %s not found", version.String()) + // this is the params of the multisig proposal execution (always present) + if innerMsg != nil && innerMsg[parser.ParamsKey] != nil { + parsedCBORParams, err := m.paramsToMap(innerMsg[parser.ParamsKey]) + if err != nil { + return nil, err + } + proposalData.Params = parsedCBORParams } - val := r() - err = val.UnmarshalCBOR(bytes.NewReader(rawReturn)) - if err != nil { - return map[string]interface{}{}, err + + // this is the return data of the multisig proposal execution, only present if applied=true + if applied && innerMsg != nil && innerMsg[parser.ReturnKey] != nil { + parsedCBORReturn, err := m.paramsToMap(innerMsg[parser.ReturnKey]) + if err != nil { + return nil, err + } + proposalData.Return = parsedCBORReturn } - metadata[parser.ReturnKey] = val + + metadata[parser.ParamsKey] = proposalData + + // this is the return status of the multisig proposal that indicates the TxnID and if the proposal was applied + metadata[parser.ReturnKey] = innerReturnParsed return metadata, nil } +// paramsToMap converts the parameters to a map from a generic CBORUnmarshaler interface type. func (*Msig) paramsToMap(params any) (map[string]any, error) { dataAsMap := make(map[string]any) diff --git a/actors/v2/multisig/params.go b/actors/v2/multisig/params.go index 94c2cc68..36112367 100644 --- a/actors/v2/multisig/params.go +++ b/actors/v2/multisig/params.go @@ -369,7 +369,7 @@ var proposeParams = map[string]func() cbg.CBORUnmarshaler{ tools.V25.String(): func() cbg.CBORUnmarshaler { return &multisig16.ProposeParams{} }, } -func getProposeParams(network string, height int64, rawParams []byte) (raw []byte, methodNum abi.MethodNum, to address.Address, value string, params multisigParams, err error) { +func getProposeParams(network string, height int64, rawParams []byte) (raw []byte, methodNum abi.MethodNum, to address.Address, value string, params cbg.CBORUnmarshaler, err error) { version := tools.VersionFromHeight(network, height) tmp, ok := proposeParams[version.String()] if !ok { @@ -419,3 +419,54 @@ func getProposeParams(network string, height int64, rawParams []byte) (raw []byt return nil, 0, address.Address{}, "", nil, fmt.Errorf("%w: %d", actors.ErrUnsupportedHeight, height) } } + +func getProposeReturn(network string, height int64, rawReturn []byte) (applied bool, raw []byte, retValue cbg.CBORUnmarshaler, err error) { + version := tools.VersionFromHeight(network, height) + tmp, ok := proposeReturn[version.String()] + if !ok { + return false, rawReturn, nil, fmt.Errorf("%w: %d", actors.ErrUnsupportedHeight, height) + } + val := tmp() + err = val.UnmarshalCBOR(bytes.NewReader(rawReturn)) + if err != nil { + return false, rawReturn, nil, err + } + + switch parsedReturn := val.(type) { + case *legacyv1.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // exact same type, commented out due to compiler error. + // case *legacyv2.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // case *legacyv3.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // case *legacyv4.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // case *legacyv5.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // case *legacyv6.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + // case *legacyv7.ProposeParams: + // return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig8.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig9.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig10.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig11.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig12.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig13.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig14.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig15.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + case *multisig16.ProposeReturn: + return parsedReturn.Applied, parsedReturn.Ret, parsedReturn, nil + default: + return false, rawReturn, nil, fmt.Errorf("%w: %d", actors.ErrUnsupportedHeight, height) + } +} diff --git a/actors/v2/multisig/propose.go b/actors/v2/multisig/propose.go index d616abe3..cfc7b6ff 100644 --- a/actors/v2/multisig/propose.go +++ b/actors/v2/multisig/propose.go @@ -16,13 +16,13 @@ import ( "github.com/zondax/fil-parser/parser" ) -// innerProposeParams processes the parameters for a multisig proposal by: +// parseInnerProposeMsg processes the parameters for a multisig proposal by: // 1. Creating a new LotusMessage with the proposal details // 2. Getting the actor and method name for the proposal // 3. Parsing the proposal parameters using the actor's Parse method -func (m *Msig) innerProposeParams( +func (m *Msig) parseInnerProposeMsg( msg *parser.LotusMessage, to address.Address, network string, height int64, method abi.MethodNum, - proposeParams []byte, key filTypes.TipSetKey, + proposeParams, proposeReturn []byte, key filTypes.TipSetKey, ) (string, map[string]interface{}, error) { proposeMsg := &parser.LotusMessage{ To: to, @@ -32,12 +32,14 @@ func (m *Msig) innerProposeParams( Params: proposeParams, } + proposeMsgRct := &parser.LotusMessageReceipt{ExitCode: exitcode.Ok, Return: proposeReturn} + actor, proposedMethod, err := m.innerProposeMethod(proposeMsg, network, height, key) if err != nil { return "", nil, err } - metadata, _, err := actor.Parse(context.Background(), network, height, proposedMethod, proposeMsg, &parser.LotusMessageReceipt{ExitCode: exitcode.Ok, Return: []byte{}}, msg.Cid, key) + metadata, _, err := actor.Parse(context.Background(), network, height, proposedMethod, proposeMsg, proposeMsgRct, msg.Cid, key) if err != nil { return "", nil, err } diff --git a/parser/helper/helpers.go b/parser/helper/helpers.go index fb0b9fc6..52736126 100644 --- a/parser/helper/helpers.go +++ b/parser/helper/helpers.go @@ -190,7 +190,7 @@ func (h *Helper) GetActorAddressInfo(add address.Address, key filTypes.TipSetKey addInfo.Short, err = h.actorCache.GetShortAddress(add) if err != nil { - if ok, _, _ := h.isZeroAddressAccountActor(add); ok { + if ok, _, _ := h.IsZeroAddressAccountActor(add); ok { addInfo.Short = ZeroAddressAccountActorShort } h.logger.Errorf("could not get short address for %s. Err: %v", add.String(), err) @@ -198,7 +198,7 @@ func (h *Helper) GetActorAddressInfo(add address.Address, key filTypes.TipSetKey addInfo.Robust, err = h.actorCache.GetRobustAddress(add) if err != nil { - if ok, _, _ := h.isZeroAddressAccountActor(add); ok { + if ok, _, _ := h.IsZeroAddressAccountActor(add); ok { addInfo.Robust = ZeroAddressAccountActorRobust } h.logger.Errorf("could not get robust address for %s. Err: %v", add.String(), err) @@ -248,7 +248,7 @@ func (h *Helper) GetActorNameFromAddress(add address.Address, height int64, key // isSpecialAccountActor handles actor addresses that will fail to resolve from the node for reasons documented in each case. func (h *Helper) isSpecialAccountActor(add address.Address, height int64) (bool, cid.Cid, string) { - if ok, cid, actorName := h.isZeroAddressAccountActor(add); ok { + if ok, cid, actorName := h.IsZeroAddressAccountActor(add); ok { return true, cid, actorName } if ok, cid, actorName := h.isKeylessAccountActor(add, height); ok { @@ -260,7 +260,7 @@ func (h *Helper) isSpecialAccountActor(add address.Address, height int64) (bool, // The f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a(f067253) is a zero address actor that existed until V10. // Created: https://github.com/filecoin-project/lotus/blob/5750f49834deee9dfce752ff840630ae402a8b51/build/buildconstants/params_shared_vals.go#L56 // Terminated: https://github.com/filecoin-project/lotus/blob/5750f49834deee9dfce752ff840630ae402a8b51/chain/consensus/filcns/upgrades.go#L1054 -func (h *Helper) isZeroAddressAccountActor(add address.Address) (bool, cid.Cid, string) { +func (h *Helper) IsZeroAddressAccountActor(add address.Address) (bool, cid.Cid, string) { if h.network != tools.MainnetNetwork || (add.String() != ZeroAddressAccountActorRobust && add.String() != ZeroAddressAccountActorShort) { return false, cid.Undef, "" } diff --git a/parser/types.go b/parser/types.go index bc478799..fb5bbd3b 100644 --- a/parser/types.go +++ b/parser/types.go @@ -57,6 +57,7 @@ type MultisigPropose struct { Value string Method string Params map[string]interface{} + Return map[string]interface{} } type Propose struct { diff --git a/parser/v1/parser.go b/parser/v1/parser.go index 7e3a1993..22d776d8 100644 --- a/parser/v1/parser.go +++ b/parser/v1/parser.go @@ -302,7 +302,7 @@ func (p *Parser) parseTrace(ctx context.Context, trace typesV1.ExecutionTraceV1, To: trace.Msg.To, From: trace.Msg.From, Method: trace.Msg.Method, - Cid: trace.Msg.Cid(), + Cid: mainMsgCid, Params: trace.Msg.Params, }, mainMsgCid, &parser.LotusMessageReceipt{ ExitCode: trace.MsgRct.ExitCode, @@ -428,7 +428,7 @@ func (p *Parser) feesMetadata(msg *typesV1.InvocResultV1, tipset *types.Extended p.logger.Errorf("Error when trying to parse miner address: %v", err) } - minerAddress, err = actors.ConsolidateRobustAddress(minerAddr, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + minerAddress, err = actors.ConsolidateToRobustAddress(minerAddr, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { p.logger.Errorf("Error when trying to consolidate miner address to robust: %v", err) } @@ -468,12 +468,12 @@ func (p *Parser) getFromToRobustAddresses(from, to address.Address) (string, str txFrom := from.String() txTo := to.String() if p.config.ConsolidateRobustAddress { - txFrom, err = actors.ConsolidateRobustAddress(from, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + txFrom, err = actors.ConsolidateToRobustAddress(from, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { txFrom = from.String() p.logger.Warnf("Could not consolidate robust address: %v", err) } - txTo, err = actors.ConsolidateRobustAddress(to, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + txTo, err = actors.ConsolidateToRobustAddress(to, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { txTo = to.String() p.logger.Warnf("Could not consolidate robust address: %v", err) diff --git a/parser/v2/parser.go b/parser/v2/parser.go index 74253b91..47d990b1 100644 --- a/parser/v2/parser.go +++ b/parser/v2/parser.go @@ -210,7 +210,7 @@ func (p *Parser) ParseNativeEvents(_ context.Context, eventsData types.EventsDat if err != nil { return nil, err } - if consolidatedAddr, err := actors.ConsolidateRobustAddress(eventAddr, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort); err == nil { + if consolidatedAddr, err := actors.ConsolidateToRobustAddress(eventAddr, p.helper, p.logger, p.config.RobustAddressBestEffort); err == nil { event.Emitter = consolidatedAddr } } @@ -247,7 +247,7 @@ func (p *Parser) ParseEthLogs(_ context.Context, eventsData types.EventsData) (* if err != nil { return nil, fmt.Errorf("error parsing emitter address: %s: %w", event.Emitter, err) } - if consolidatedAddr, err := actors.ConsolidateRobustAddress(eventAddr, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort); err == nil { + if consolidatedAddr, err := actors.ConsolidateToRobustAddress(eventAddr, p.helper, p.logger, p.config.RobustAddressBestEffort); err == nil { event.Emitter = consolidatedAddr } } @@ -465,7 +465,7 @@ func (p *Parser) feesMetadata(msg *typesV2.InvocResultV2, tipset *types.Extended p.logger.Errorf("Error when trying to parse miner address: %v", err) } - minerAddress, err = actors.ConsolidateRobustAddress(minerAddr, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + minerAddress, err = actors.ConsolidateToRobustAddress(minerAddr, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { minerAddress = minerAddr.String() p.logger.Errorf("Error when trying to consolidate miner address to robust: %v", err) @@ -506,12 +506,12 @@ func (p *Parser) getFromToRobustAddresses(from, to address.Address) (string, str txFrom := from.String() txTo := to.String() if p.config.ConsolidateRobustAddress { - txFrom, err = actors.ConsolidateRobustAddress(from, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + txFrom, err = actors.ConsolidateToRobustAddress(from, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { txFrom = from.String() p.logger.Warnf("Could not consolidate robust address: %v", err) } - txTo, err = actors.ConsolidateRobustAddress(to, p.helper.GetActorsCache(), p.logger, p.config.RobustAddressBestEffort) + txTo, err = actors.ConsolidateToRobustAddress(to, p.helper, p.logger, p.config.RobustAddressBestEffort) if err != nil { txTo = to.String() p.logger.Warnf("Could not consolidate robust address: %v", err) diff --git a/parser_test.go b/parser_test.go index aa202ffb..1f34eab6 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2108,7 +2108,10 @@ func TestParser_ActorVersionComparison(t *testing.T) { } if metadataV1[parser.ParamsKey] != nil { - require.EqualValuesf(t, metadataV1[parser.ParamsKey], metadataV2[parser.ParamsKey], fmt.Sprintf("tx_type: %s \n V1: %s \n V2: %s", tx.TxType, tx.TxMetadata, parsedResultActorV2.Txs[i].TxMetadata)) + // multisig propose correctly parses return params in v2 + if tx.TxType != parser.MethodPropose { + require.EqualValuesf(t, metadataV1[parser.ParamsKey], metadataV2[parser.ParamsKey], fmt.Sprintf("tx_type: %s \n V1: %s \n V2: %s", tx.TxType, tx.TxMetadata, parsedResultActorV2.Txs[i].TxMetadata)) + } } if metadataV1[parser.ReturnKey] != nil { // ClaimAllocations return struct changed to support slices.