|
| 1 | +package cascade |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "encoding/json" |
| 6 | + "fmt" |
| 7 | + |
| 8 | + actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" |
| 9 | + "github.com/LumeraProtocol/supernode/v2/pkg/cascadekit" |
| 10 | +) |
| 11 | + |
| 12 | +// DebugReverseEngineerAction fetches an action by ID, decodes its Cascade |
| 13 | +// metadata and embedded index information, and prints a detailed breakdown. |
| 14 | +// It performs read-only inspection and is intended for internal debugging. |
| 15 | +func (task *CascadeRegistrationTask) DebugReverseEngineerAction(ctx context.Context, actionID string) error { |
| 16 | + _ = ctx // kept for parity with other methods; not used here |
| 17 | + |
| 18 | + if actionID == "" { |
| 19 | + fmt.Println("DebugReverseEngineerAction: empty actionID, nothing to do") |
| 20 | + return nil |
| 21 | + } |
| 22 | + |
| 23 | + fmt.Printf("DebugReverseEngineerAction: fetching action %s\n", actionID) |
| 24 | + |
| 25 | + // Step 1: Fetch the action from the chain |
| 26 | + action, err := task.fetchAction(context.Background(), actionID, nil) |
| 27 | + if err != nil { |
| 28 | + fmt.Printf("DebugReverseEngineerAction: error fetching action %s: %v\n", actionID, err) |
| 29 | + return err |
| 30 | + } |
| 31 | + |
| 32 | + // Step 2: Print basic action summary |
| 33 | + fmt.Println("=== Action Summary ===") |
| 34 | + fmt.Printf("Action ID : %s\n", action.ActionID) |
| 35 | + fmt.Printf("Creator : %s\n", action.Creator) |
| 36 | + fmt.Printf("Action Type : %s\n", action.ActionType.String()) |
| 37 | + fmt.Printf("State : %s\n", action.State.String()) |
| 38 | + fmt.Printf("Block Height : %d\n", action.BlockHeight) |
| 39 | + fmt.Printf("Price : %s\n", action.Price) |
| 40 | + fmt.Printf("Expiration (unix): %d\n", action.ExpirationTime) |
| 41 | + fmt.Printf("Metadata bytes : %d\n", len(action.Metadata)) |
| 42 | + fmt.Printf("Supernodes (%d) : %v\n", len(action.SuperNodes), action.SuperNodes) |
| 43 | + |
| 44 | + // Only Cascade actions carry CascadeMetadata |
| 45 | + if action.ActionType != actiontypes.ActionTypeCascade { |
| 46 | + fmt.Println("Action is not of type CASCADE; skipping cascade-specific decoding.") |
| 47 | + return nil |
| 48 | + } |
| 49 | + |
| 50 | + if len(action.Metadata) == 0 { |
| 51 | + fmt.Println("Cascade action has empty metadata; nothing to decode.") |
| 52 | + return nil |
| 53 | + } |
| 54 | + |
| 55 | + // Step 3: Decode Cascade metadata |
| 56 | + cascadeMeta, err := cascadekit.UnmarshalCascadeMetadata(action.Metadata) |
| 57 | + if err != nil { |
| 58 | + fmt.Printf("Failed to unmarshal cascade metadata: %v\n", err) |
| 59 | + return err |
| 60 | + } |
| 61 | + |
| 62 | + fmt.Println("\n=== Cascade Metadata (summary) ===") |
| 63 | + fmt.Printf("Data hash (b64) : %s\n", cascadeMeta.DataHash) |
| 64 | + fmt.Printf("File name : %s\n", cascadeMeta.FileName) |
| 65 | + fmt.Printf("rq_ids_ic : %d\n", cascadeMeta.RqIdsIc) |
| 66 | + fmt.Printf("rq_ids_max : %d\n", cascadeMeta.RqIdsMax) |
| 67 | + fmt.Printf("rq_ids_ids (#) : %d\n", len(cascadeMeta.RqIdsIds)) |
| 68 | + fmt.Printf("Public : %v\n", cascadeMeta.Public) |
| 69 | + if len(cascadeMeta.RqIdsIds) > 0 { |
| 70 | + fmt.Printf("rq_ids_ids : %v\n", cascadeMeta.RqIdsIds) |
| 71 | + } |
| 72 | + fmt.Printf("Signatures len : %d\n", len(cascadeMeta.Signatures)) |
| 73 | + |
| 74 | + if metaJSON, mErr := json.MarshalIndent(cascadeMeta, "", " "); mErr == nil { |
| 75 | + fmt.Println("\n=== Cascade Metadata (JSON) ===") |
| 76 | + fmt.Println(string(metaJSON)) |
| 77 | + } |
| 78 | + |
| 79 | + // Step 4: Decode index information from the signatures field |
| 80 | + if cascadeMeta.Signatures == "" { |
| 81 | + fmt.Println("\nCascade metadata has empty signatures field; cannot decode index.") |
| 82 | + return nil |
| 83 | + } |
| 84 | + |
| 85 | + indexB64, creatorSigB64, err := cascadekit.ExtractIndexAndCreatorSig(cascadeMeta.Signatures) |
| 86 | + if err != nil { |
| 87 | + fmt.Printf("Failed to extract index and creator signature: %v\n", err) |
| 88 | + return err |
| 89 | + } |
| 90 | + |
| 91 | + fmt.Println("\n=== Index Signature Components ===") |
| 92 | + fmt.Printf("index_b64 length : %d\n", len(indexB64)) |
| 93 | + fmt.Printf("creator_sig_b64 length : %d\n", len(creatorSigB64)) |
| 94 | + if len(indexB64) > 0 { |
| 95 | + previewLen := 64 |
| 96 | + if len(indexB64) < previewLen { |
| 97 | + previewLen = len(indexB64) |
| 98 | + } |
| 99 | + fmt.Printf("index_b64 prefix : %s\n", indexB64[:previewLen]) |
| 100 | + } |
| 101 | + if len(creatorSigB64) > 0 { |
| 102 | + previewLen := 64 |
| 103 | + if len(creatorSigB64) < previewLen { |
| 104 | + previewLen = len(creatorSigB64) |
| 105 | + } |
| 106 | + fmt.Printf("creator_sig_b64 prefix : %s\n", creatorSigB64[:previewLen]) |
| 107 | + } |
| 108 | + |
| 109 | + // Step 5: Decode the logical index file (base64(JSON(IndexFile))) |
| 110 | + indexFile, err := cascadekit.DecodeIndexB64(indexB64) |
| 111 | + if err != nil { |
| 112 | + fmt.Printf("Failed to decode index file from base64: %v\n", err) |
| 113 | + return err |
| 114 | + } |
| 115 | + |
| 116 | + fmt.Println("\n=== Index File (summary) ===") |
| 117 | + fmt.Printf("Version : %d\n", indexFile.Version) |
| 118 | + fmt.Printf("Layout IDs (#) : %d\n", len(indexFile.LayoutIDs)) |
| 119 | + fmt.Printf("Layout IDs : %v\n", indexFile.LayoutIDs) |
| 120 | + fmt.Printf("Layout signature len : %d\n", len(indexFile.LayoutSignature)) |
| 121 | + if layoutSig := indexFile.LayoutSignature; layoutSig != "" { |
| 122 | + previewLen := 64 |
| 123 | + if len(layoutSig) < previewLen { |
| 124 | + previewLen = len(layoutSig) |
| 125 | + } |
| 126 | + fmt.Printf("Layout signature prefix: %s\n", layoutSig[:previewLen]) |
| 127 | + } |
| 128 | + |
| 129 | + if indexJSON, iErr := json.MarshalIndent(indexFile, "", " "); iErr == nil { |
| 130 | + fmt.Println("\n=== Index File (JSON) ===") |
| 131 | + fmt.Println(string(indexJSON)) |
| 132 | + } |
| 133 | + |
| 134 | + fmt.Println("\nDebugReverseEngineerAction: completed successfully.") |
| 135 | + |
| 136 | + return nil |
| 137 | +} |
0 commit comments