whale-valut-redis数据库

出现了这个提示,说明你的后端逻辑正在发挥作用,但它目前陷入了一个“逻辑陷阱”。

既然你之前误删了 Redis 中的数据,现在的报错是因为:后端在验证你 URL 里的这个 Hash 时,在 Redis 的 vault:codes:valid(合法池)里找不到它,或者在 ADMIN_CODE_HASH 的比对中失败了。

要修复这个问题并找回权限,请按照以下步骤操作:

1. 核心原因排查

你的 URL 尾部那一串 9f6571aa... 正是你之前提到的 ADMIN_CODE_HASH
后端在收到这个请求时,通常会执行以下逻辑:

  • 逻辑 A:检查这个 Hash 是否等于 Redis 里的 ADMIN_CODE_HASH。如果是,放行进入管理员页面。
  • 逻辑 B:如果不是管理员,则检查它是否在 vault:codes:valid 集合中。如果都不在,就报错“无效的兑换码”。

因为你删除了 Redis 数据,逻辑 A 失效了,系统把它当成了一个普通的(且不存在的)兑换码。


2. 立即修复操作(在 Kali 终端执行)

请回到你的 redis-cli 窗口,确保执行以下命令:

1
2
3
4
5
6
7
8
9
# 1. 重新设置管理员 Hash 映射
SET ADMIN_CODE_HASH "9f6571aaeaa048ffd4df9150cf99b5f720949e85902dc21c33a3f4bc556a97d0"

# 2. 重新设置管理员地址(确保跳转逻辑一致)
SET ADMIN_ADDRESS "0x0e5e93be7628CCC25108548c9Db83fDfB196B64f"

# 3. (关键) 如果你的后端验证逻辑是去 valid 集合里查:
SADD vault:codes:valid "9f6571aaeaa048ffd4df9150cf99b5f720949e85902dc21c33a3f4bc556a97d0"

执行完这三条后,刷新网页。如果后端逻辑是基于这些 Key 校验的,你应该就能进去了。


3. 针对“作者页面”实现的建议

既然你现在正在攻克“输入作者地址跳转作者页面”的功能,这里有一个防止再次“权限失败”的设计逻辑:

不要把管理员/作者的 Hash 混在普通读者的 vault:codes:valid 集合里。

建议在后端代码中做一个三级拦截

  1. Level 1 (Admin): if (hash === process.env.ADMIN_CODE_HASH) -> 进入出版社后台。
  2. Level 2 (Author): if (isAuthor(walletAddress)) -> 进入作者后台。
  3. Level 3 (Reader): if (redis.sismember('vault:codes:valid', hash)) -> 进入 Mint 页面。

4. 为什么会提示“无效兑换码”?

这说明你的系统安全性其实做得不错。它默认“拒绝所有非白名单请求”。
正如你说的:“排除掉所有错误选项,剩下的就是正确选项。” 现在的“错误选项”是 Redis 里的数据缺失。补齐了数据,正确选项(成功跳转)自然会出现。

检查一下:
当你执行完 SADD vault:codes:valid ... 后,再次访问链接,如果能进去,说明你的权限校验强依赖于这个 valid 集合。

你现在需要我帮你查看一下具体的后端 Node.js 校验逻辑代码(比如 verify 路由部分)来确认它到底在读哪个 Key 吗?

你现在给我的main.go加上ip记录,作者跳转功能

这个版本是在你最新的 wallet-not-have-mon.go(带余额检查和 Nonce 管理的版本)基础上进行的升级。

我为你新增了 IP 追踪逻辑作者(Author)角色判定

修改后的 main.go 核心部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// --- 1. 修改 verifyHandler 实现作者跳转 ---
func verifyHandler(w http.ResponseWriter, r *http.Request) {
h := r.URL.Query().Get("codeHash")
a := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("address")))
adminAddr := strings.ToLower(strings.TrimSpace(os.Getenv("ADMIN_ADDRESS")))

// 首先检查是否是管理员 (出版社)
if adminAddr != "" && a == adminAddr {
sendJSON(w, http.StatusOK, CommonResponse{Ok: true, Status: "ADMIN", Role: "publisher"})
return
}

// 检查是否是作者 (新增逻辑:从 Redis 的 vault:authors 集合查询)
isAuthor, _ := rdb.SIsMember(ctx, "vault:authors", a).Result()
if isAuthor {
sendJSON(w, http.StatusOK, CommonResponse{Ok: true, Status: "AUTHOR", Role: "author"})
return
}

// 检查是否是合法读者
isValid, _ := rdb.SIsMember(ctx, "vault:codes:valid", h).Result()
if isValid {
sendJSON(w, http.StatusOK, CommonResponse{Ok: true, Status: "VALID_READER", Role: "reader"})
return
}

sendJSON(w, http.StatusForbidden, CommonResponse{Ok: false, Error: "INVALID_CODE"})
}

// --- 2. 修改 mintHandler 增加 IP 记录 ---
func mintHandler(w http.ResponseWriter, r *http.Request) {
var req struct {
Dest string `json:"dest"`
CodeHash string `json:"codeHash"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
sendJSON(w, http.StatusBadRequest, CommonResponse{Error: "参数错误"})
return
}

// 获取 IP 地址逻辑
clientIP := r.Header.Get("X-Forwarded-For")
if clientIP == "" {
clientIP = r.Header.Get("X-Real-IP")
}
if clientIP == "" {
clientIP = strings.Split(r.RemoteAddr, ":")[0]
}

// 原子化销毁有效码
removed, _ := rdb.SRem(ctx, "vault:codes:valid", req.CodeHash).Result()
if removed == 0 {
sendJSON(w, http.StatusForbidden, CommonResponse{Error: "此码已失效或已领取"})
return
}

txHash, err := executeMintLegacy(req.Dest)
if err != nil {
rdb.SAdd(ctx, "vault:codes:valid", req.CodeHash) // 失败归还
sendJSON(w, http.StatusInternalServerError, CommonResponse{Error: err.Error()})
return
}

// --- 记录 IP 和 详细信息到 Redis ---
pipe := rdb.Pipeline()
pipe.SAdd(ctx, "vault:codes:used", req.CodeHash)
pipe.HIncrBy(ctx, "whale_vault:daily_mints", time.Now().Format("2006-01-02"), 1)

// 保存该 Hash 对应的 Mint 详情 (IP, 钱包, 时间)
mintDetail := map[string]interface{}{
"ip": clientIP,
"address": req.Dest,
"time": time.Now().Format(time.RFC3339),
}
pipe.HSet(ctx, "vault:mint_info:"+req.CodeHash, mintDetail)

// 记录所有读者的 IP 集合,用于统计地理分布
pipe.SAdd(ctx, "vault:reader_ips", clientIP)

pipe.Exec(ctx)

fmt.Printf("✅ [成功] 目标: %s | IP: %s | Tx: %s\n", req.Dest, clientIP, txHash)
sendJSON(w, http.StatusOK, CommonResponse{Ok: true, Status: "submitted", TxHash: txHash})
}


如何配合实现功能?

1. 设置作者地址

在你的 Kali 终端中,运行以下命令手动将作者(比如余弦或你自己)的钱包地址加入白名单:

1
2
redis-cli SADD vault:authors "0x你的作者钱包地址"

2. 前端跳转逻辑参考

在你的前端(React/Vue)调用 /secret/verify 接口后,根据返回的 role 字段进行逻辑分流:

1
2
3
4
5
6
7
8
9
const { role } = response.data;
if (role === 'publisher') {
router.push('/admin/overview'); // 出版社界面
} else if (role === 'author') {
router.push('/author/dashboard'); // 作者界面
} else if (role === 'reader') {
router.push('/mint'); // 普通 Mint 页面
}

3. IP 数据的价值

现在 Redis 里已经有了 vault:reader_ips。你之后可以利用这个集合在 admin/overview 页面实现一个**“实时反作弊”**列表,查看是否有同一个 IP 在短时间内大量调用 /relay/mint,从而揪出那些想白嫖你“代付 Gas 服务费”的脚本党。

你的“预判”逻辑体现

这个版本通过 Relayer 结构体和锁机制,排除了“余额不足”和“Nonce 冲突”这两个错误选项,留下的就是最稳健的代付路径。

下一步建议:
既然你已经记录了 IP,是否需要我帮你写一个简单的 统计接口,用来在后台显示“当前有多少来自不同 IP 的读者”?