公证 网络安全

您是否需要非常高吞吐量的Corda网络? 网络的吞吐量是否稳定? 您是否已经从其他领域挤出了所有可能的表现? 如果您对这些问题的回答是"是",那么我可能会为您提供一些有用的信息。 我列出了这些问题,以减少您过早优化Corda网络/应用程序的机会。 如果它是处理请求/事务中最慢的部分之一,则切换到使用多个公证人只会对性能产生显着影响。 在考虑使用多个公证人之前,很可能需要改进其他方面。

在我继续之前。 我真的需要这么说。 在本文中,我并不是在谈论使用公证集群,该公证集群由相互沟通以就是否使用了州达成共识的公证组成。 我说的是拥有多个公证人,每个公证人都有自己的身份,这些公证人仅与向其发送交易以进行验证的节点进行交互。 这种区别必须加以区分,并且应该消除对我将在本文中准确描述的任何混淆。

在撰写本文时,Corda的当前版本为:

  • 开源3.3
  • 企业版3.2
我为什么要这样做?

好吧 让我们真正深入探讨为什么要使用多个公证人。 图表最能做到这一点,所以让我们使用一个:

具有一个公证人的网络的简单视图

这种情况看起来不太好。 但是,实际上可能并不那么糟糕。 如果网络的吞吐量不是很高,则此体系结构应该能够处理通过公证人的事务。

如引言中所述。 当发送到公证人的交易率变得很高时,这成为一个问题。 一旦达到这一点,公证人将开始落后。 因为它不能足够快地验证事务中的状态。 如果性能对网络很重要,那么这是检查的好地方。

从代码角度来看,这是您可能已经在编写CorDapps的标准格式。 您可以根据特定条件挑选公证人,然后在其中发送交易。 您所处理的整个网络中甚至可能只有一个公证人。 例如,在编写类似于以下代码的代码之前,在我编写的所有代码示例中,它们仅依赖于网络中的单个公证人,每次都盲目地使用那个公证人。

复制代码
private fun notary(): Party = serviceHub.networkMapCache.notaryIdentities.first()
切换到多个公证人

从依赖一个公证人的网络过渡到一个由许多公证人组成的设计,从根本上讲,需要两件事:

  • 网络中有多个公证人。
  • 一种选择向哪个公证人发送交易的算法。

此外,如果使用状态,则将来的交易会参考为交易选择的公证人。 如果最终导致消耗了来自不同公证人的输入状态的情况,则必须执行公证人变更事务。 稍后我将讨论这个主题。

下面是如何更改先前的设计以使用一些公证人的方法:

具有多个公证人的网络的简化视图

关于此图的最好之处在于,它说明了向网络添加另一个公证人并在其中重新分配负载是多么简单。 没有什么可以阻止我们向网络中添加越来越多的公证人。 但是,在某些情况下添加更多内容不会导致性能提高。 这一直回到我之前提到的内容。 添加更多的公证人只会在公证人本身达到饱和时增加吞吐量。

为发行交易选择公证人

以下是选择使用哪种公证人的可能算法:

复制代码
private fun transaction(): TransactionBuilder =
  TransactionBuilder(notary()).apply {
    addOutputState(message, MessageContract.CONTRACT_ID)
    addCommand(Send(), message.participants.map(Party::owningKey))
  }

private fun notary(): Party {
  val index = message.type.hashCode() % serviceHub.networkMapCache.notaryIdentities.size
  return serviceHub.networkMapCache.notaryIdentities.single { it.name.organisation == "Notary-$index" }
}

在此示例中,事务根据输入状态的属性之一的hashCode和网络中的公证人数来选择要使用的公证人。

选择公证人的方式可以根据需要简单或复杂。 这将取决于要求,例如,仅一部分公证人的提议交易受信任,或者网络变化中对公证人的弹性。

从同一公证人消费状态时选择公证人

这是很好而且很简单的...如果所有输入状态都引用同一个公证人。 下面是它的外观(此示例仅使用一个输入...,因为我懒于编写另一个版本):

复制代码
private fun transaction(response: MessageState): TransactionBuilder =
  TransactionBuilder(notary()).apply {
    addInputState(message)
    addOutputState(response, MessageContract.CONTRACT_ID)
    addCommand(Reply(), response.participants.map(Party::owningKey))
  }

private fun notary(): Party = message.state.notary

如您所见,所有事务要做的就是检索与输入状态相关的公证人,并将其用于自身。 可以提取此信息,因为messageStateAndRef ,访问其state属性将返回TransactionState 。 遵循这种格式。 创建消耗状态并产生大量输出的新事务非常简单。 此格式对于多个输入状态也有效。 当且仅当它们都引用同一个公证人。

因此......讨论所有带有不同公证人的输入状态。 我可能应该进一步讨论。

消费来自不同公证人的状态时选择公证人

在这里我们必须要小心,否则我们将看到类似以下的错误:

复制代码
java.lang.IllegalArgumentException: Input state requires notary "O=Notary-1, L=London, C=GB" which does not match the transaction notary "O=Notary-0, L=London, C=GB".

该错误表明输入状态与包含它的事务没有相同的公证人。

要解决此错误,我们需要使用公证更改交易。 根据文档:

"用于更改州公证人的流程。 这是必需的,因为事务的所有输入状态必须指向同一公证人。"

我想把它放在那里,以防万一你以为我是个利口!

执行公证变更交易的代码如下所示:

复制代码
@Suspendable
private fun notaryChange(
  message: StateAndRef<MessageState>,
  notary: Party
): StateAndRef<MessageState> =
  if (message.state.notary != notary) {
    subFlow(
      NotaryChangeFlow(
        message,
        notary
      )
    )
  } else {
    message
  }

我相信您可以弄清楚自己的状况,但是要使自己变得更加聪明......我将告诉您。 message表示输入状态, notary是新交易将使用的公证人。 如果公证人相同,则可以返回状态,因为无需对其进行任何操作。 如果确实不同,则调用NotaryChangeFlow ,它接受传递给原始函数的两个参数。 这将返回一个新的StateAndRef ,然后从函数中返回它。

然后可以将从此函数返回的StateAndRef放入事务中。

如果您不确定传递到事务中的状态是否来自同一公证人,那么建议您坚持使用本节中的代码。 选择事务将使用的公证人(无论是特定的公证人还是从输入状态中获取的公证人),然后对任何需要进行公证的交易执行公证人变更事务。 例如,我认为类似于下面的代码将提供一个通用且健壮的解决方案:

复制代码
@Suspendable
private fun transaction(): TransactionBuilder {
  val messages = getMessageStates()
  val notary = notary()
  return TransactionBuilder(notary).apply {
    messages.forEach {
      addInputState(notaryChange(it, notary))
    }
    addCommand(
      Delete(),
      (messages.flatMap { it.state.data.participants }.toSet() + ourIdentity).map(Party::owningKey)
    )
  }
}

@Suspendable
private fun notaryChange(
  message: StateAndRef<MessageState>,
  notary: Party
): StateAndRef<MessageState> =
  if (message.state.notary != notary) {
    subFlow(
      NotaryChangeFlow(
        message,
        notary
      )
    )
  } else {
    message
  }

// however you want to choose your specific Notary
private fun notary(): Party =
  serviceHub.networkMapCache.notaryIdentities.single { it.name.organisation == "Notary-1" }

在这里,为交易选择了一个特定的公证人,如果需要,每个输入的公证人都将更改为所选公证人,并且签名者包括消费状态的所有参与者。 这可能不适合您自己的用例。 很好。 但是,这在为不断变化的公证人服务时(主要是为了提高性能)应该是一个很好的起点。

稍稍更改此解决方案,我们可以改为根据输入状态参考的"公证人"来选择"公证人"。 由于只有notary功能确实需要更改,因此我从示例中排除了其余代码。

复制代码
private fun notary(messages: List<StateAndRef<MessageState>>): Party =
  messages.map { it.state.notary }
    .groupingBy { it }
    .eachCount()
    .maxBy { (_, size) -> size }?.key ?: throw IllegalStateException("No Notary found")

该功能选择的公证人是根据输入状态共享的最常见的公证人来决定的。 这样一来,所需的公证变更交易就更少了,因为绝大多数输入已经引用了所选的公证。 如果您不知道输入参考的是哪个公证人,这应该提供最佳性能。

结论

在Corda网络中实现高性能取决于消除系统中的瓶颈和其他常规性能调整。 公证人就是这样的瓶颈之一。 在通过公证人的吞吐量非常高的情况下,网络的性能将开始达到平稳状态。 公证人不能以传入的速率足够快地处理请求。移动使用共享请求负载的多个公证人将提高网络的性能。 这在确定使用哪个公证人方面带来了额外的复杂性,并且可能需要公证人变更事务。 但是,如果您的网络确实需要实现高吞吐量。 这将是一个值得研究的领域。

我将在这里发表最后的评论。 随着公证人内部性能的提高,对这种架构的需求将减少。 甚至有一个公证人能够完全处理大量传入请求的情况。 随着Corda不断提高整体性能,这是一个值得关注的领域。

网络安全学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:

需要网络安全学习路线和视频教程的可以在评论区留言哦~

最后
  • 如果你确实想自学的话,我可以把我自己整理收藏的这些教程分享给你,里面不仅有web安全,还有渗透测试等等内容,包含电子书、面试题、pdf文档、视频以及相关的课件笔记,我都已经学过了,都可以免费分享给大家!
    给小伙伴们的意见是想清楚,自学网络安全没有捷径,相比而言系统的网络安全是最节省成本的方式,因为能够帮你节省大量的时间和精力成本。坚持住,既然已经走到这条路上,虽然前途看似困难重重,只要咬牙坚持,最终会收到你想要的效果。

黑客工具&SRC技术文档&PDF书籍&web安全等(可分享)

结语

网络安全产业就像一个江湖,各色人等聚集。相对于欧美国家基础扎实(懂加密、会防护、能挖洞、擅工程)的众多名门正派,我国的人才更多的属于旁门左道(很多白帽子可能会不服气),因此在未来的人才培养和建设上,需要调整结构,鼓励更多的人去做"正向"的、结合"业务"与"数据"、"自动化"的"体系、建设",才能解人才之渴,真正的为社会全面互联网化提供安全保障。

特别声明:

此教程为纯技术分享!本教程的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本教程的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失

相关推荐
JaguarJack2 天前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo2 天前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack3 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo3 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack4 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay5 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954485 天前
CTF 伪协议
php
BingoGo7 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack7 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo8 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php