# social.exchange_safebox ## Scope 审计玩家面对面交易、交易确认/防调包、仓库(Safebox)、仓库密码与分页、商城(Mall)只读取出、金币变化和窗口距离/关闭清理。判断标准是当前端是否复现 40250 的客户端请求门控、服务器回包权威状态、物品 socket/属性传递、错误分支和窗口时序;本地脚本能够独立完成一次交易或仓库存取,不能作为与 40250 实现统一的证明。 ## Reference call chain - `UserInterface/PythonNetworkStreamPhaseGame.cpp` - `RecvExchangePacket` 按 `START/ITEM_ADD/ITEM_DEL/ELK_ADD/ACCEPT/END` 更新 `CPythonExchange`,每个物品同时保存 socket 与 attribute,并在物品变化后刷新交易和背包窗口。 - `SendExchangeStartPacket`、`SendExchangeElkAddPacket`、`SendExchangeItemAddPacket`、`SendExchangeAcceptPacket`、`SendExchangeExitPacket` 均先经过 `__CanActMainInstance()`,再发送 `CG_EXCHANGE` 并追加 sequence;客户端不直接结算交易。 - `UserInterface/PythonExchange.cpp` / `Client/Eternexus/root/uiexchange.py` - `CPythonExchange` 保存双方姓名、12 个展示槽、socket/attribute、金币和接受状态;交易结束由 `GC_END` 驱动 `EndExchange`,成功/失败详情通过服务器聊天提示提供。 - 交易 UI 只提交物品、金币、接受或退出请求,等待服务器回包刷新;物品源位置、anti flag、背包和金币结果由服务端确认。 - `UserInterface/PythonNetworkStreamPhaseGameItem.cpp` - Safebox checkin/checkout/move、密码错误、大小、金币变化和 Mall open/set/del/checkout 都是协议路径;Safebox/Mall item set 回包复制 vnum/count/flags/anti_flags、socket 和 attribute 后刷新窗口。 - Safebox 金币主动修改包在该版本明确未启用;Mall checkout 还触发对应掉落音效。 - `Client/Eternexus/root/uisafebox.py` / `game.py` - 仓库由服务器返回页数和物品状态,5×9 每页 45 格;拖放/右键发送 checkin、checkout 或 move,关闭和密码命令走服务器流程。商城只允许取出,不允许向 Mall 存入。 ## Current call chain - native `M2Client`/`ClassicSession` 已提供 exchange start/item/gold/accept/cancel、safebox checkin/checkout/move/password/change/close、mall checkout/password,以及 `EntityStore` 的 exchange/safebox/mall parser、dirty 标记和 signal。 - `EntityStore` 能保存交易双方 12 槽、金币、接受标志、notice,能够复制交易物品 socket/attribute;Safebox/Mall parser 能复制 item flags、anti_flags、socket 和 attribute,并处理 open/set/del/close/wrong-password 基础事件。 - `project/ui/exchange_ui.gd`、`safebox_ui.gd`、`mall_ui.gd` 已提供 12 槽交易 UI、45 格分页仓库、商城只读出、tooltip、密码和距离自动关闭;主要 UI 已从 native getter/signal 刷新,而不是只依赖本地物品列表。 - `project/player_trade_exchange_system.gd` 和 `project/safebox_storage_keeper_system.gd` 是另外一套本地状态机:它们直接保存玩家字典、交易物品、金币、仓库密码、库存和金条熔铸结果。这些 helper 可用于单元测试,但不是 40250 客户端的网络 authority 链。 ## Branch matrix | 场景 | 40250 | 当前端 | 结论 | |---|---|---|---| | 开始交易 | `__CanActMainInstance`→`CG_EXCHANGE START`→服务器 `GC_START` | native 能发 start,UI/helper 能打开交易 | PARTIAL:native 缺同等动作门控和 active/partner 状态限制;helper 可绕开服务器 | | 放入物品 | 客户端只发源位置和展示槽,服务器回 `GC_ITEM_ADD`;变化时双方接受状态由服务器清除 | UI 做 anti-give/重复源位置检查后立即记录 `_offered_cells`,native 只做位置边界 | PARTIAL:本地 optimistic 集合没有按 `GC_ITEM_ADD/ITEM_DEL` 重建,拒绝或删除后可能仍阻塞源物品 | | 放入金币 | `SendExchangeElkAddPacket` 只负责请求,服务器决定金额并回包 | UI 限制 1..9,999,999,native 只做 u32/in-game 检查 | PARTIAL:本地上限和已放金币判断不是 40250 客户端 authority;native 缺交易 active/拥有金币/动作门控 | | 接受/取消/结束 | 接受和退出发包,窗口等 `GC_END` 关闭;交易结果由服务器聊天和回包提供 | 接受有本地 pending;取消和距离超限会发包后立即 `close()` | PARTIAL:取消/距离分支不等待权威 `GC_END`,真实拒绝、断线和乱序关闭未覆盖 | | 交易安全/原子结算 | 客户端不计算交换、不改双方背包/金币;服务端负责锁定、空间、金额和最终交付 | `player_trade_exchange_system.gd` 本地计算 ready、金币、空间和原子转移 | GAP(本地 helper):这不是 40250 客户端实现,不能作为 live parity 依据 | | Safebox 打开/关闭 | `GC_SAFEBOX_SIZE` 打开,服务端控制大小;关闭走 `/safebox_close`,窗口状态由服务端同步 | native/UI 有 open/close、页数和 10m 自动关闭;close 后本地立即隐藏 | PARTIAL:基础链存在,但本地先隐藏/请求失败回滚、乱序重开和真实服务端错误缺测试 | | Safebox 存取/移动 | checkin/checkout/move 请求后由 `GC_SAFEBOX_SET/DEL` 更新 | 拖放使用目标槽,移动/右键取出存在;移动端 deposit 先找本地首个空位并记录 pending | PARTIAL:pending 没有与回包关联;本地 helper 直接存取/堆叠,不能证明服务器拒绝、堆叠和物品属性结果一致 | | Safebox 密码/金币 | wrong-password 和 size/money change 由服务器回包;客户端不保存真实密码 | native 通过命令发送密码;本地 `safebox_storage_keeper_system.gd` 保存密码、冷却、锁定和金条规则 | PARTIAL/GAP:helper 的密码/冷却/金条熔铸是自定义本地 authority,不能替代 40250 server command/GC 结果 | | Mall 打开/取出 | `GC_MALL_OPEN/SET/DEL` 驱动只读窗口,checkout 后服务器更新背包/Mall | native parser/UI/getter/checkout 存在,UI 禁止插入 | PARTIAL:主路径接近,但服务端失败、背包回包、重连清理和掉落音效没有端到端证据 | ## Implementation-equivalence matrix | 项目 | 状态 | 证据/限制 | |---|---|---| | Preconditions | PARTIAL | 位置、展示槽、u32、窗口和部分 anti flag 检查存在;exchange native 缺 `__CanActMainInstance` 等阶段/动作门控,真实库存/交易 active/拥有金币由服务端决定且未在客户端等价复现 | | Branch structure | PARTIAL | exchange/safebox/mall 的协议分支和 UI 分支基本存在;取消立即关闭、移动端首空位 deposit、local helper 结算和密码/金条旁路与参考客户端不一致 | | Algorithms/formulas | GAP | 40250 客户端不实现交易结算、库存空间、仓库密码存储或金条熔铸公式;当前本地 helper 复制这些服务器职责,不能宣称与客户端统一 | | State transition order | PARTIAL | native store 大体是请求→GC→dirty/signal→UI;交易 `_offered_cells`、safebox pending 和 close 先隐藏造成本地 optimistic 状态,拒绝/乱序时序尚未闭合 | | Constants/units | PARTIAL | 12 交易槽、45 格/页、socket/attribute 槽和距离限制存在;金币 9,999,999 UI 上限、helper 45 格/单页和自定义冷却/金条常量需避免冒充 40250 client 常量 | | Timing/event sources | PARTIAL | exchange/safebox/mall dirty signal、10m 距离关闭和密码错误 UI 存在;真实 GC_END、GC_ITEM_SET/DEL、断线、重复请求和重新打开时序缺回归 | | Resource/data sources | PARTIAL | live item tooltip 使用协议 item 数据并保留 socket/attribute;本地交易/仓库 helper 使用脚本 Dictionary,移动端 pending/首空位选择可能在服务器结果前改变显示 | | Protocol side effects | PARTIAL | CG exchange、safebox、mall 基础布局和 store parser 存在;exchange 的动作门控、完整错误结果、商城掉落音效和实际服务器回包副作用不完整 | | Interruption/failure/cleanup | GAP | helper 可无服务器回包直接成功;UI 的本地关闭、optimistic 源物品/pending 集合、密码失败、背包满、断线和乱序恢复没有完整回滚/重放证明 | ## Regression evidence - `project/test_player_trade_exchange_parity.gd`:28/28 通过;覆盖的是本地交易 helper 的距离、不可交易物品、双方锁定、金币、空间和原子交付,不是 `GC_EXCHANGE` live 回包。 - `project/test_safebox_mall_parity.gd`:37/37 通过;覆盖 fake client 的 45 格、距离、socket/attribute、checkin/checkout/move、商城禁止插入和密码命令。 - `project/test_safebox_storage_keeper_parity.gd`:37/37 通过;覆盖本地密码/冷却、库存堆叠、移动、金条熔铸/承兑和非法格位,不能证明 40250 server authority。 - `project/shop_cube_mall_test.gd`、`project/test_mall_affect_parity.gd`、`project/popup_windows_parity_test.gd`、`project/test_security_lock_parity.gd`、`build/extension/net_entity_test`、`build/extension/net_classic_session_test`:通过;主要验证 UI/helper、item-mall 辅助效果或基础 packet/store,没有完整 exchange/safebox/mall 服务器拒绝、乱序、断线和回包回滚。 - `project/complex_item_drop_test.gd`:当前 1 项失败(购买模式仍允许把物品拖到出售目标),说明统一拖放门控仍有可复现差异;该失败属于相邻商店合同,但会影响交易/仓库共用拖放边界审计。 ## Deep audit round 2026-09-21 ### Fresh regression results - `godot --headless --path project --script test_player_trade_exchange_parity.gd`:退出码 0,28/28 通过;覆盖本地交易距离、anti-give、锁定、金币、空间、原子转移和取消 helper。 - `godot --headless --path project --script test_safebox_mall_parity.gd`:退出码 0,37/37 通过;覆盖 fake client 的仓库/商城窗口、45 格、距离关闭、属性显示、存取移动和密码命令。 - `godot --headless --path project --script test_safebox_storage_keeper_parity.gd`:退出码 0,37/37 通过;覆盖本地密码/冷却、堆叠、45 格和金条 helper。 - `godot --headless --path project --script shop_cube_mall_test.gd`、`test_mall_affect_parity.gd`、`popup_windows_parity_test.gd`、`test_security_lock_parity.gd`:均退出码 0;商城效果、窗口和安全锁局部测试通过,其中安全锁为 48/48。 - `build/extension/net_entity_test` 与 `build/extension/net_classic_session_test`:均退出码 0;基础 exchange/safebox/mall parser/session 通过。 - `godot --headless --path project --script complex_item_drop_test.gd`:退出码 1;购买模式出售目标门控失败,属于相邻 shop/drag contract 的持续回归。 ### Static parity findings - 40250 交易请求全部先经过 `__CanActMainInstance`,客户端只发送源位置/金币/接受/退出,`GC_EXCHANGE_*` 决定展示和最终结束;当前 native exchange 请求主要做阶段/范围校验,`player_trade_exchange_system.gd` 仍可脱离网络直接完成双方金币、空间和物品转移。 - 当前 `exchange_ui.gd` 的 `_offered_cells`、pending 和取消/距离关闭逻辑没有统一由 `GC_ITEM_ADD/DEL`、`GC_ACCEPT`、`GC_END` 重建;拒绝、乱序、断线和重新打开可能保留乐观状态。 - 40250 Safebox/Mall item 回包保留 vnum/count/flags/anti_flags/socket/attribute,并由服务端决定页数、堆叠、空间和金币;当前 live native/store 路径能承接这些字段,但 `safebox_storage_keeper_system.gd` 仍保存密码、冷却、堆叠和金条 authority。 - Safebox/Mall UI 的距离自动关闭、密码命令和商城只出路径有局部验证;没有真实 `GC_SAFEBOX_SIZE/SET/DEL/WRONG_PASSWORD`、`GC_MALL_*` 与背包回包的成功/失败/重连/断线顺序 fixture,也没有 Mall checkout 音效的端到端验证。 - `M2Client`/`ClassicSession` 的 exchange/safebox/mall 包布局基础存在,但 native action gate、交易 active/partner/金币拥有量、服务器拒绝文案、SendSequence 和关闭幂等性未形成统一合同。 ### Round conclusion 本轮仍为 `PARTIAL`:交易/仓库/商城 native 骨架和局部 UI 测试通过,但本地结算/密码/库存 helper 旁路、乐观关闭/pending 状态、动作门控与真实 GC 回包回滚仍未与 40250 统一。本轮未修改实现代码。 ## Active UserInterface exchange, safebox and shop review - `PythonExchange.h`/`PythonExchangeModule.cpp` 的状态读取覆盖双方名称、金钱、接受状态、槽位 vnum/count、metin socket、attribute 和 elk mode;这些值由交易回包写入,UI getter 不承担结算。 - `PythonSafeBox.h` 区分 safebox 与 mall 的打开尺寸、slot item、删除、金钱和当前大小;`PythonShop.h` 另外维护普通商店 tab/coin/name/item,以及私有商店 stock/display position/price/build/close,不能把它们合并为一个背包字典。 - 当前 native/store 已覆盖部分字段,但交易、仓库和商城 helper 仍有本地 optimistic/persistent 状态;真实 GC 添加/删除/接受/错误、密码失败、页尺寸、私店重建、断线和重复关闭顺序没有逐包等价测试,合同保持 `PARTIAL`。 ## Static review evidence 已将 `PythonExchange.h`、`PythonExchangeModule.cpp`、`PythonSafeBox.h`、`PythonShop.h` 纳入 active source 证据;本轮确认了交易/仓库/商城的独立 owner 和回包字段边界,未修改实现。 ## Status `PARTIAL`。当前端已经具备 exchange/safebox/mall 的 native 协议骨架、回包存储和主要 UI,交易物品属性与仓库商城的基本网络状态能够展示;但 native exchange 请求缺 40250 动作门控,交易/仓库 UI 存在 optimistic 状态和提前关闭,本地 helper 直接承担交易结算、密码、库存和金条 authority,且真实错误、乱序、断线和回包回滚证据不足。本轮完成审计并记录,未修改实现。 ### 2026-09-22 死代码删除 以下文件只被自身测试引用、运行时从不加载,已删除;本文中以它们为实现或证据的结论作废,相关行为需按 40250 源码单元重新移植:`player_trade_exchange_system.gd`, `safebox_storage_keeper_system.gd`, `test_mall_affect_parity.gd`, `test_player_trade_exchange_parity.gd`, `test_safebox_storage_keeper_parity.gd`, `test_security_lock_parity.gd`。