钱包业务层 - 8. 交易所钱包业务大总结(极其重要)

经过这么长时间,我们钱包业务层的业务拆解总算是完成了。前面1-7讲我们分析了钱包业务层的框架搭建、区块同步器、交易发现器、提现、归集、内部交易、回滚和通知业务。

完结感言

经过这么长时间,我们钱包业务层的业务拆解总算是完成了。前面 1-7 讲我们分析了钱包业务层的框架搭建、区块同步器、交易发现器、提现、归集、内部交易、回滚和通知业务。但是前面的业务都是从局部入手来详细分析各项任务代码处理,有点缺乏整体框架的概念。而这一讲中,我们将整合前面所提到的所有模块,来从宏观层面上来理解钱包业务层这一整个系统的框架和模块。

完整项目 github 地址(如果对您有用,请给个小 star ⭐️):

  1. exchange-wallet-service:钱包业务层服务: <https://github.com/Shawn-Shaw-x/exchange-wallet-service>
  2. signature-machine:离线签名机:  <https://github.com/Shawn-Shaw-x/signature-machine>
  3. chains-union-rpc:多链统一 rpc:  <https://github.com/Shawn-Shaw-x/chains-union-rpc>

总结图

image.png

详细解析整个系统的组件

在上面的整体框架图中,我们可以看到,我们将一整个钱包业务层的框架划分成 8 个独立模块,每个模块都是相对独立但又相互关联作用的。

  1. 数据库迁移任务

数据库迁移任务中是一个一次性任务,只需要我们在第一次执行钱包应用的时候执行一次,进行 postgre 数据库表的生成即可。它在内部实际上是执行我们写好的 sql 文件来为我们生成好对应的地址表、余额表、交易表等系统必须的底层数据库表。

  1. grpc 服务

grpc 服务中,我们对外层系统(如交易所业务层或者项目方)暴露了必须的接口。例如:业务注册、地址转换、构建未签名交易、构建已签名交易等接口。grpc 服务是一个独立的服务,运行在系统的某一个端口上,提供给外层系统调用能力。

并且,在 grpc 服务中,我们还构建了一个客户端 client,负责在我们钱包层的系统中提供对外调用的能力(例如调用 chains-union-rpc 去执行区块链 rpc 接口的数据获取)

  1. 区块同步器

区块同步器是我们钱包业务系统的核心组件,相当于一个消息的生产者角色。它是一个独立的协程启动的定时任务,负责批量去获取链上的区块。并且通过获取区块内的交易,解析并筛选出来和我们系统相关的交易类型。然后推送的一个管道中,提供交易的消息。

并且,在区块的同步器中,它还负责判断本地区块是否与链上区块出现 新扫到区块的parentHash != 数据库中区块的 hash的情况。如果出现了不相等的情况,则说明区块链中存在回滚的情况。此时,扫链同步器会暂停扫块,转而触发回滚任务(另一个协程启动的定时任务)去执行区块和交易的回滚流程。

  1. 交易发现器

交易发现器相当于一个消费者的角色,它负责消费处理区块同步器推送到核心交易管道(可以理解为消息队列,只是在 go 语言中内置的)中的交易。在交易的发现器中,我们系统主要做两件事情:

  • 新交易的发现

处理充值、提现、归集、热转冷、冷转热等交易的链上发现流程。例如充值交易,会发现并入库,同时更新 lockBalance。而提现、归集、热转冷、冷转热交易虽然也会发现交易并修改库中状态,但却不会更新 balance 或者 lockBalance 的信(具体原因且看下面的交易状态解析)

  • 旧交易的确认位处理

在这里,还会进行旧交易的确认位处理,例如在充值交易中,我们只会增加 lockBalance 的值,并不去修改 balance 的值。但是交易一旦在这里得到确认,则可以减少对应的 lockBalance 的值,并加到 balance 中去。代表这这笔充值交易已经被完全确认了,无法进行回滚。

并且例如提现、归集、热转冷、冷转热交易的确认位处理,也是在这里处理。因为这些都是交易所系统内部发起的交易,例如提现:热钱包地址的 lockBalance 减少。balance 不变(交易广播发起时候 balance 已经减少了,lockBalance 增加)

  1. 提现任务处理

在提现任务中处理中,这里主要负责的是提现任务的提取并调用 chains-union-rpc 服务去将这笔提现任务发送到区块链网络中。同时更新提现任务的状态和热钱包地址的 balancelockBalance 信息(balance 减少,lockBalance 增加)

  1. 内部交易任务处理

内部交易城任务的处理和提现任务的处理类似,都是将数据库的已经签名但未发送出去的交易通过调用 chains-union-rpc 的方式发送出去。同时更新内部交易任务的状态和两个钱包地址的余额。

以归集交易为例

  • 用户地址的 balance 减少,lockBalance 增加。

  • 热钱包地址的 balance 不变,lockBalance 增加。

等这笔内部交易确认后

  • 用户地址的 balance 不变,lockBalance 减少。

  • 热钱包地址的 balance 增加,lockBalance 减少。

  1. 回滚任务处理

我们的回滚任务处理仍然是一个定时任务去处理,它会实时监控我们的扫链同步器的回滚状态,一旦它监测到我们扫链同步器进入了回滚状态无法正常扫块。则我们的回滚任务会被触发。

在回滚任务中,主要是会根据同步器标记的出现回滚的区块,调用 chains-union-rpc 的接口去一个个区块往回找,直到寻找到这个链的分叉起始点(通过本地区块的 parentHash == 链上区块的 hash可以找到)。这样,就能获取到我们需要回滚区块的范围。例如 10 -20 这个范围。那么我们下面将要做的是:

  • 备份 10 - 20 这个范围的区块头信息,删除掉原来的区块头的记录。

  • 更新充值、提现、归集、热转冷、冷转热交易的状态为 fallback,更新对应的地址的余额信息(回滚了,资金扣除)

  • 通知项目方(交易所业务层)去做对应的回滚处理。(这个在通知任务中处理)

  1. 通知任务处理

因为我们交易有许多中状态,例如充值交易中会有:1.已扫到交易 2. 交易确认。3. 交易回滚。提现交易会有:1. 交易已广播。2. 交易已经扫到。 3. 交易已确认。4. 交易已回滚 等状态。我们项目方(或者钱包的业务层)需要得知这些交易的状态来进行相应的业务处理。所以我们钱包的系统中,需要启动一个单独的通知任务,去持续扫描我们数据库中的各种未通知交易,去发送 http 请求给项目方(业务层)去通知。在通知业务里面,主要做的事情有:

  1. 扫描充值、提现、归集、热转冷、冷转热、回滚等交易的各个状态未通知的交易。将其构造出通知消息,通过 http 请求的方式通知对应业务层(项目方)

  2. 更新已被通知的交易的状态为已通知,避免重复通知。

不同交易的状态、余额变化

鉴于不同交易的生命周期不一样,以及其余额处理(balancelockBalance)的不一致,所以下面我们用详细的案例来分析各种交易的状态和余额变动情况。

所有案例我们都采用转账 100 ETH 的情况来进行分析。

充值

充值交易的状态有:

  1. 充值已发现: 我们的交易同步器第一次发现这个充值的交易,被交易发现器处理,则为这个充值交易已发现的状态。 此时余额变动为用户地址的 balance 不变。lockBalance = lockBalance + 100。表示我们得知了充值,但余额暂不可用。

  2. 充值回滚: 在充值已发现,但还未被确认的情况下。如果链上发生了回滚,则我们的回滚任务触发,充值的状态变更为已回滚。 此时的余额变动为:用户地址 balance 不变。lockBalance = lockBalance - 100。表示为我们的余额被回滚了。

  3. 充值已确认: 如果在确认位之前,我们的充值交易没有被回滚,则可以认为这笔交易是安全有效的。(我们在交易的发现器中,查询数据库中的充值交易的区块高度是否小于链上最新高度的 k 个块,k 为我们确认位的个数) 在充值交易已确认后,余额变动为:用户地址 balance = balance + 100lockBalance = lockBalance - 100;表示我们的余额从 lockBalance 中的缓存移动到真实可用的 balance 余额。

提现

由于提现交易和归集、热转冷、冷转热交易这些内部交易一样,都是由我们交易所业务层主动发起的,所以,交易的状态会和充值有点不一样(更多)

  1. 提现未签名: 指业务层调用我们 rpc 服务提供的构建未签名交易的过程。这时候会创建一笔提现交易,但是没有签名信息,无法发送交易。

  2. 提现已签名、未广播: 指业务层将未签名的交易调用签名机去签名出来,获得签名。调用我们 rpc 服务构建已签名交易的过程,在这个过程中。已签名的交易会入库,但还未发送,等待定时任务去实际广播出去。

  3. 提现已广播: 指我们的定时任务将已签名,未广播的交易调用 chains-union-rpc 接口将交易广播出去。 此时的余额变化为:热钱包地址的 balance = balnance - 100lockBalance = lockBalance + 100

  4. 提现已发现: 指我们扫链同步器发现这笔交易,并在交易发现器中处理已发现交易的过程。此时提现交易的 balance 和 lockBalnce不会产生实际变动。只会更新提现交易的状态。

  5. 提现交易被回滚: 如果提现交易被回滚,则需要更新提现交易的状态为已回滚,同时热钱包地址余额信息也将更新:balance = balance + 100lockBalance = lockBalance - 100

  6. 提现已经确认: 如果提现过了确认位已被确认的情况下。则热钱包地址余额的变动情况为:balance 不变。lockBalance = lockBalance - 100

归集

归集和提现、热转冷、冷转热交易一样,都是属于内部交易,也都是由我们交易所业务层主动发起的。

  1. 归集未签名: 指业务层调用我们 rpc 服务提供的构建未签名交易的过程。这时候会创建一笔归集交易,但是没有签名信息,无法发送交易。

  2. 归集已签名、未广播: 指业务层将未签名的交易调用签名机去签名出来,获得签名。调用我们 rpc 服务构建已签名交易的过程,在这个过程中。已签名的交易会入库,但还未发送,等待定时任务去实际广播出去。

  3. 归集已广播: 指我们的定时任务将已签名,未广播的交易调用 chains-union-rpc 接口将交易广播出去。 此时的余额变化为:用户地址的 balance = balnance - 100lockBalance = lockBalance + 100。热钱包地址的 balance 不变。 lockBalance = lockBalance + 100

  4. 归集已发现: 指我们扫链同步器发现这笔交易,并在交易发现器中处理已发现交易的过程。此时归集交易的 balancelockBalnce 不会产生实际变动。只会更新归集交易的状态。

  5. 归集交易被回滚: 如果归集交易被回滚,则需要更新归集交易的状态为已回滚,同时用户地址余额信息也将更新:balance = balance + 100lockBalance = lockBalance - 100;热钱包地址余额:balance = balance不变。 lockBalnce = lockBalance - 100

  6. 归集已经确认: 如果归集过了确认位已被确认的情况下。同时用户地址余额信息也将更新:balance 不变。lockBalance = lockBalance - 100;热钱包地址余额:balance = balance + 100lockBalnce = lockBalance - 100

热转冷

热转冷和归集、冷转热交易一样,都是属于内部交易,也都是由我们交易所业务层主动发起的。

  1. 热转冷未签名: 指业务层调用我们 rpc 服务提供的构建未签名交易的过程。这时候会创建一笔热转冷交易,但是没有签名信息,无法发送交易。

  2. 热转冷已签名、未广播: 指业务层将未签名的交易调用签名机去签名出来,获得签名。调用我们 rpc 服务提供出来的构建已签名交易的过程,在这个过程中。已签名的交易会入库,但还未发送,等待定时任务去实际广播出去。

  3. 热转冷已广播: 指我们的定时任务将已签名,未广播的交易调用 chains-union-rpc 接口将交易广播出去。 此时的余额变化为:热钱包地址的 balance = balnance - 100lockBalance = lockBalance + 100。冷钱包地址的 balance 不变。 lockBalance = lockBalance + 100

  4. 热转冷已发现: 指我们扫链同步器发现这笔交易,并在交易发现器中处理已发现交易的过程。此时热转冷交易的 balance 和 lockBalnce 不会产生实际变动。只会更新热转冷交易的状态。

  5. 热转冷交易被回滚: 如果热转冷交易被回滚,则需要更新热转冷交易的状态为已回滚,同时热钱包地址余额信息也将更新:balance = balance + 100lockBalance = lockBalance - 100;冷钱包地址余额: balance 不变。 lockBalnce = lockBalance - 100

  6. 热转冷已经确认: 如果热转冷过了确认位已被确认的情况下。同时热钱包地址余额信息也将更新:balance 不变。lockBalance = lockBalance - 100;冷钱包地址余额:balance = balance + 100lockBalnce = lockBalance - 100

    冷转热

    冷转热和归集、热转冷交易一样,都是属于内部交易,也都是由我们交易所业务层主动发起的。

  7. 冷转热未签名: 指业务层调用我们 rpc 服务提供的构建未签名交易的过程。这时候会创建一笔冷转热交易,但是没有签名信息,无法发送交易。

  8. 冷转热已签名、未广播: 指业务层将未签名的交易调用签名机去签名出来,获得签名。调用我们 rpc 服务提供出来的构建已签名交易的过程,在这个过程中。已签名的交易会入库,但还未发送,等待定时任务去实际广播出去。

  9. 冷转热已广播: 指我们的定时任务将已签名,未广播的交易调用 chains-union-rpc 接口将交易广播出去。 此时的余额变化为:冷钱包地址的 balance = balnance - 100lockBalance = lockBalance + 100。热钱包地址的 balance 不变。 lockBalance = lockBalance + 100

  10. 冷转热已发现: 指我们扫链同步器发现这笔交易,并在交易发现器中处理已发现交易的过程。此时冷转热交易的 balancelockBalnce 不会产生实际变动。只会更新冷转热交易的状态。

  11. 冷转热交易被回滚: 如果冷转热交易被回滚,则需要更新冷转热交易的状态为已回滚,同时冷钱包地址余额信息也将更新:balance = balance + 100lockBalance = lockBalance - 100;热钱包地址余额:balance 不变。 lockBalnce = lockBalance - 100

  12. 冷转热已经确认: 如果冷转热过了确认位已被确认的情况下。同时冷钱包地址余额信息也将更新:balance 不变。lockBalance = lockBalance - 100;热钱包地址余额:balance = balance + 100lockBalnce = lockBalance - 100

至此,我们整个钱包业务系统也总结完啦。本来想简写写点的,但不知不觉间,又写了 4k+ 的文字了。主要是交易状态和 balancelockBalance 较为复杂,讲解长了点。希望对您的钱包开发生涯有用啦。如果可以,希望您能给我的文章和 github 点点 star ⭐️。

点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
shawn_shaw
shawn_shaw
web3潜水员、技术爱好者、web3钱包开发工程师。欢迎闲聊唠嗑、精进技术、交流工作机会。vx:cola_ocean