Optimism的挑战期

1. 引言

前序博客:

  • Optimism的Fault proof

用户将资产从OP主网转移到以太坊主网时需要等待一周的时间。这段时间称为挑战期,有助于保护 OP 主网上存储的资产。
而OP测试网的挑战期仅为60秒,以简化开发过程。

在这里插入图片描述

2. OP与L1数据交互

在这里插入图片描述

L1(以太坊)上的合约,可通过“bridging”,与L2(OP主网)上合约,进行交互。

同一网络内的Solidity合约调用,类似为:

contract MyContract {function doTheThing(address myContractAddress, uint256 myFunctionParam) public {MyOtherContract(myContractAddress).doSomething(myFunctionParam);}
}

MyContract.doTheThing会触发调用MyOtherContract.doSomething。在底层,Solidity通过向MyOtherContract合约发送ABI encoded call来触发调用doSomething函数。为简化开发者体验,此处抽象掉了很多这种复杂性。也可手工encoding(以更底层callabi.encodeCall函数)来实现相同的功能,如:

contract MyContract {function doTheThing(address myContractAddress, uint256 myFunctionParam) public {myContractAddress.call(abi.encodeCall(MyOtherContract.doSomething,(myFunctionParam)));}
}

以上两种调用方式等价。由于Solidity的限制,OP Stack的bridging接口被设计为看起来像第二个代码片段(即采用更底层的表达方式)。

2.1 L1与L2之间的基础通讯

从高层来看,L1与L2之间的数据发送流程,与以太坊上2个合约间的发送流程类似。L1与L2的通讯,可通过一组特殊的名为“messenger”的合约来实现。L1和L2有各自的messenger合约,用于抽象掉一些更底层的通讯细节,非常像HTTP库抽象掉物理网络连接。

每个messenger合约都有sendMessage函数,来向另一层的合约发送一个消息:

function sendMessage(address _target, //所调用的目标层上的合约bytes memory _message, //所发送的内容uint32 _minGasLimit //在目标层执行内容的最小gas limit
) public;

其等价为:

address(_target).call{gas: _gasLimit}(_message);

从而可调用个不同网络上的合约。
这掩盖了许多技术细节,这些细节使整件事在幕后运作,但这应该足以让你开始。想从以太坊上的合约调用OP主网上的合约吗?非常简单:

// Pretend this is on L2
contract MyOptimisticContract {function doSomething(uint256 myFunctionParam) public {// ... some sort of code goes here}
}// And pretend this is on L1
contract MyContract {function doTheThing(address myOptimisticContractAddress, uint256 myFunctionParam) public {messenger.sendMessage(myOptimisticContractAddress,abi.encodeCall(MyOptimisticContract.doSomething,(myFunctionParam)),1000000 // or use whatever gas limit you want)}
}

具体可查看OP主网和测试网上合约地址 中的L1CrossDomainMessenger合约 和 L2CrossDomainMessenger合约。

2.2 通讯速度

不同于同一链上的合约调用,以太坊和OP主网间的调用不是即时的。跨链交易的通讯速度取决于方向:

  • 1)对于由L1->L2的交易:交易由L1(以太坊)到L2(OP主网),需约1到3分钟。因Sequencer需等待(包含该L1->L2交易区块之后的)一定数量的L1区块,以避免烦人的reorg问题。
  • 2)对于由L2->L1的交易:交易由L2(OP主网)到L1(以太坊),需要约7天。原因在于L1上的bridge合约,需等待该L2状态to be proven to the L1 chain之后,才能relay该message。
    由L2->L1的交易,分为4个不同的步骤:
    • 2.1)Step 1:将“给L1发送message”的L2交易,发送给Sequencer。这与其它L2交易类似,仅需数秒就可由Sequencer确认。
    • 2.2)Step 2:包含该L2交易的L2区块被提交给L1。这通常用时20分钟。
    • 2.3)Step 3:向L1上的OptimismPortal合约 提交该交易的proof。可在上面Step 2完成之后的任意时间提交。
    /// @notice Proves a withdrawal transaction.
    /// @param _tx              Withdrawal transaction to finalize.
    /// @param _l2OutputIndex   L2 output index to prove against.
    /// @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.
    /// @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.
    function proveWithdrawalTransaction(Types.WithdrawalTransaction memory _tx,uint256 _l2OutputIndex,Types.OutputRootProof calldata _outputRootProof,bytes[] calldata _withdrawalProof
    )externalwhenNotPaused
    {// Prevent users from creating a deposit transaction where this address is the message// sender on L2. Because this is checked here, we do not need to check again in// `finalizeWithdrawalTransaction`.require(_tx.target != address(this), "OptimismPortal: you cannot send messages to the portal contract");// Get the output root and load onto the stack to prevent multiple mloads. This will// revert if there is no output root for the given block number.bytes32 outputRoot = l2Oracle.getL2Output(_l2OutputIndex).outputRoot;// Verify that the output root can be generated with the elements in the proof.require(outputRoot == Hashing.hashOutputRootProof(_outputRootProof), "OptimismPortal: invalid output root proof");// Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];// We generally want to prevent users from proving the same withdrawal multiple times// because each successive proof will update the timestamp. A malicious user can take// advantage of this to prevent other users from finalizing their withdrawal. However,// since withdrawals are proven before an output root is finalized, we need to allow users// to re-prove their withdrawal only in the case that the output root for their specified// output index has been updated.require(provenWithdrawal.timestamp == 0|| l2Oracle.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot != provenWithdrawal.outputRoot,"OptimismPortal: withdrawal hash has already been proven");// Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.// Refer to the Solidity documentation for more information on how storage layouts are// computed for mappings.bytes32 storageKey = keccak256(abi.encode(withdrawalHash,uint256(0) // The withdrawals mapping is at the first slot in the layout.));// Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract// on L2. If this is true, under the assumption that the SecureMerkleTrie does not have// bugs, then we know that this withdrawal was actually triggered on L2 and can therefore// be relayed on L1.require(SecureMerkleTrie.verifyInclusionProof(abi.encode(storageKey), hex"01", _withdrawalProof, _outputRootProof.messagePasserStorageRoot),"OptimismPortal: invalid withdrawal inclusion proof");// Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and// `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be// proven once unless it is submitted again with a different outputRoot.provenWithdrawals[withdrawalHash] = ProvenWithdrawal({outputRoot: outputRoot,timestamp: uint128(block.timestamp),l2OutputIndex: uint128(_l2OutputIndex)});// Emit a `WithdrawalProven` event.emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);
    }
    
    • 2.4)Step 4:仅当fault挑战期(当前OP主网为7天) 结束之后,该交易才在L1上固化。该等待期是OP Stack安全模型的核心,无法规避。

2.3 访问msg.sender

合约会频繁使用msg.sender来基于calling address做决定。如,许多合约使用Ownable模式来选择性地约束对特定函数的访问。因为消息本质上是通过messenger合约在L1和L2之间穿梭的,所以当你接收到其中一条消息时,你会看到的 msg.sender将是与你所在的层相对应的messenger合约。
为此,每个messenger合约内均有xDomainMessageSender函数:

	/// @notice Retrieves the address of the contract or wallet that initiated the currently///         executing message on the other chain. Will throw an error if there is no message///         currently being executed. Allows the recipient of a call to see who triggered it./// @return Address of the sender of the currently executing message on the other chain.function xDomainMessageSender() external view returns (address) {require(xDomainMsgSender != Constants.DEFAULT_L2_SENDER, "CrossDomainMessenger: xDomainMessageSender is not set");return xDomainMsgSender;}

若你的合约被其中一个messenger合约调用,则可使用该函数来看实际上究竟是谁在发送该消息。在L2上实现onlyOwner modifier示例为:

modifier onlyOwner() {require(msg.sender == address(messenger)&& messenger.xDomainMessageSender() == owner);_;
}

2.4 L1与L2之间发送数据的手续费

对于L1->L2交易:

  • L1->L2交易的大部分开销,源自L1上合约的执行。当发送L1->L2交易时,实际是调用了L1上的L1CrossDomainMessenger合约,然后调用L1上的OptimismPortal合约。这些在L1上的执行,会花费gas。L1->L2交易的总开销,最终由以太坊上的gas费决定。
  • L1->L2交易,会触发L2上的合约执行。OptimismPortal合约,会为L2执行,代为收取费用——burn掉动态量的L1 gas,具体量取决于所请求L2的gas limit。当更多人发送L1->L2交易时,所收取的L1 gas费会增加。当更少发送L1->L2交易时,所收取的L1 gas费会减少。
    • 由于代收取的L2执行gas量是动态的,所burn的gas在各个区块会各不相同。为避免gas燃尽,应总是为L1->L2交易gas limit增加至少20%的buffer。

对于L2->L1方向:

  • 由L2->L1的每个消息,需要3笔交易:
    • 1)L2交易:发起L2->L1启动交易,其定价与OP主网上的任何其他交易相同。
    • 2)L1证明交易:证明该L2交易。只有在L1上提交了包括该L2交易在内的L2区块后,才能提交此L1证明交易。该交易是昂贵的,因为它包括验证L1上的Merkle trie包含证明。
    • 3)L1固化交易:用于固化该L2交易。仅在该L2交易超过7天挑战期之后,才能提交L1固化交易。
  • L2->L1发送单个消息的总开销,包括:1笔L2启动交易和2笔L1交易开销。L1 proof交易和L1固化交易,通常要比L2启动交易贵得多。

2.5 挑战期

由L2->L1的消息,至少需要7天才能relay。这即意味着由L2发送的任意消息,只能过了一周的挑战期之后,才能在L1上收到。称其为“挑战期”的原因在于,在该期间,交易可被a fault proof挑战。
Optimistic Rollups是“乐观的”,因为其核心思想为:将某交易的结果发送到以太坊,而不在以太坊上实际执行该交易。在“乐观”情况下,该交易结果是正确的,可完全避免在以太坊上执行复杂(且昂贵)的逻辑。

但是,仍需要某种方式,来避免发布不正确的,而不是正确的,交易结果。为此,引入了“fault proof”。当某交易结果发布后,可将其看成“pending”一段时间,又名挑战期。在挑战期,任何人都可在以太坊上重新执行该交易,以试图证明所发布的结果是不正确的。

若某人证明该交易结果是错误的,则该结果将被删除,任何人都可以在该位置发布另一个结果(希望这次是正确的结果,经济惩罚会使错误的结果对发布者来说代价高昂)。一旦给定交易结果的窗口完全通过而没有受到质疑,则该结果可被视为完全有效(否则会有人对其提出质疑)。

无论如何,这里的重点是,在这个挑战期结束之前,不从L1上的智能合约内部对L1交易结果做出决定。否则,可能会根据无效的交易结果做出决策。结果,L2->L1 使用standard messenger合约发送的L1消息在等待整个挑战期之后才能被relay。

3. OP原理

为使L1gas开销最小化,OP Bedrock中的L2区块存储在以太坊链的非合约地址内:https://etherscan.io/address/0xff00000000000000000000000000000000000010。
这些L2区块作为交易calldata提交到以太坊,当该“交易”被包含在某具有足够attestations的区块内,则没法对其仅需修改或审查。从而OP主网可继承以太坊的可用性和完整性。

为降低开销,写入L1内的L2区块为压缩格式:
在这里插入图片描述
以压缩格式来在以太坊上存储L2区块,这很重要,因为写入到L1是OP主网交易的主要开销。

3.1 区块生成

Optimism区块生产主要由称为“Sequencer”的单一方管理,Sequencer主要提供如下服务:

  • 提供交易确认和状态更新。
  • 构建和执行 L2 区块。
  • 将用户交易提交到 L1。

在 Bedrock 中,Sequencer确实像以太坊那样有一个mempool,但该内存池是私有的,以避免为 MEV 提供机会。在 OP 主网中,区块每两秒生成一次,无论它们是空的(无交易)、被交易填充到区块 Gas limit、还是介于两者之间。

交易通过两种方式到达Sequencer:

  • 1)在 L1 上提交的交易(称为存款)包含在适当的 L2 链区块中。每个 L2 块都由“epoch”(它对应的 L1 块,通常发生在 L2 区块之前几分钟)及其在该epoch内的序列号来标识。该epoch的第一个区块包含其对应的 L1 区块中发生的所有存款。如果epoch试图忽略合法的 L1 交易,它最终会得到与Verifier不一致的状态,就像epoch试图通过其他方式伪造状态一样。这为 OP 主网提供了 L1 以太坊级别的抗审查能力。 可在协议规范Deriving the Transaction List中阅读有关此机制的更多信息。
  • 2)交易直接提交给Sequencer。这些交易的提交成本要低得多(因为不需要单独的 L1 交易费用),但它们当然不能抵抗审查,因为Sequencer是唯一了解它们的参与者。

目前,Optimism基金会在 OP 主网上运行唯一的区块生产者。有关未来计划对 Sequencer 角色进行去中心化。

在这里插入图片描述
基本工作流程为:

  • 1)用户将交易发送到主处理程序(Sequencer),然后主处理程序在其版本的第 2 层 (L2) 链上处理这些交易。
  • 2)处理后,Sequencer将交易详细信息和更新的第 2 层状态发送到第 1 层 (L1)。
  • 3)然后,其他第 2 层节点使用此交易更新其第 2 层链的版本。
  • 4)为了检查准确性,Verifier验证者节点将其更新状态与排序器提交的状态进行比较。

3.2 区块执行

op-geth组件所实现的执行引擎,使用两种机制接收区块:

  • 1)执行引擎可以使用对等网络与其他执行引擎进行自我更新。这与 L1 执行客户端通过网络同步状态的方式相同。具体见happy-path sync。
  • 2)op_node组件所实现的rollup节点从 L1 派生出 L2 区块。这种机制速度较慢,但​​具有抗审查性。具体见Worst-case sync。

3.3 在各层之间bridge ETH或token

Optimism 的设计目的是让用户可以在 L2(OP 主网、OP Sepolia 等)和底层 L1(以太坊主网、Sepolia 等)上的智能合约之间发送任意消息。这使得在两个网络之间传输 ETH 或代币(包括 ERC20 代币)成为可能。这种通信发生的确切机制根据消息发送的方向而有所不同。

OP 主网在标准桥中使用此功能,允许用户将代币从以太坊存入 OP 主网,也允许将代币从 OP 主网提取回以太坊。详情见Using the Standard Bridge。

  • 1)从以太坊迁移到 OP 主网:从以太坊(L1)到 OP 主网(L2)的交易称为存款。使用L1CrossDomainMessenger合约 或 L1StandardBridge合约,存款交易成为与存款所在的 L1 区块相对应的“epoch”的第一个 L2 区块中规范区块链的一部分。该 L2 块通常会在相应的 L1 块几分钟后创建。详情见Deposits。
  • 2)从 OP 主网迁移到以太坊:提款分为3个阶段:【详情见Withdrawals】
    • 2.1)通过 L2 交易初始化提款。
    • 2.2)等待下一个输出根提交到L1,然后使用 提交提款证明proveWithdrawalTransaction。这一新步骤可以对提款进行链下监控,从而更容易识别不正确的提款或输出根。这可保护 OP 主网用户免受一系列潜在的桥接漏洞的影响。
    • 2.3)故障挑战期结束后(主网一周,比测试网短),完成提现。

3.4 Fault proof 故障证明

在 Optimistic Rollup 中,状态承诺被发布到 L1(OP 主网的以太坊),没有任何直接证据证明这些承诺的有效性。相反,这些承诺被视为在一段时间内悬而未决(称为“挑战窗口”)。如果拟议的状态承诺在挑战窗口(当前设置为 7 天)期间没有受到挑战,则该承诺将被视为最终承诺。一旦承诺被认为是最终的,以太坊上的智能合约就可以安全地接受基于该承诺的有关 OP 主网状态的提款证明。

当状态承诺受到质疑时,可以通过“fault proof”过程使其无效。如果该承诺被成功质疑,那么它将被从承诺中删除,StateCommitmentChain(SCC)最终被另一个提议的承诺所取代。值得注意的是,成功的挑战不会回滚 OP 主网本身,只会回滚有关链状态的已发布承诺。交易的顺序和 OP 主网的状态不会因故障证明挑战而改变。

在这里插入图片描述

  • SCC:状态承诺链(SCC)合约包含提议的状态根列表,提议者断言这些状态根是规范交易链(CTC)中每笔交易的结果。这里的元素与CTC中的交易一一对应。
  • CTC:规范交易链(CTC)是必须应用于 OVM 状态的交易协议。
  • OVM:乐观虚拟机是一个符合第 2 层 (L2) 要求的执行框架,使汇总实现能够与以太坊的主区块链进行通信。
  • GETH:Geth 是以太坊区块链的执行客户端,用于处理交易。智能合约的部署和执行包括内置的 EVM。

作为 2021 年 11 月 11 日EVM 等效性的副作用,fault proof流程目前正在进行重大重新开发更新。

4. 为什么 Optimistic Rollup 挑战期为 7 天?

提款延迟是 Optimistic Rollup 的基本组成部分。当用户向以太坊提出有关 Optimistic Rollup 状态的声明时,就会开始提款。 如,这个声明可能是“我在 Optimism 上烧掉了 20 个代币,所以让我在以太坊上提取 20 个代币。”
由于 Optimistic Rollup 的重点在于 L1 并未实际执行 L2 链,因此 L1 不知道此声明是否有效。ZK Rollups 通过为 L1 提供一个加密证明来证明给定的声明是有效的,从而解决了这个问题。乐观汇总通过要求声明必须通过挑战期才能被视为有效来解决此问题。每个claim必须等待一段挑战期,在此期间挑战者可以声明该claim无效。如果有人对某个主张提出质疑,那么就会开始一些链上游戏来确定该主张是否真正有效。

由于某人检测无效声明并提交挑战可能需要一些时间,因此我们不可避免地需要挑战期大于零。毕竟,如果挑战期的持续时间是零秒,那么就没有机会提交挑战了。那么我们的问题就变成了:挑战期应该是多长?

最终状态的现代乐观汇总挑战游戏本质上采取提出主张的用户和质疑该主张的用户之间来回的形式(实际上,这些协议通常被设计为允许任何人参与要么是“团队”,但现在让我们保持简单)。为了举例,我们假设整个过程中有大约 10 个来回步骤(确切的数量有所不同,但在这里并不重要)。

如果双方都非常非常快,那么整个挑战过程至少需要 10 个以太坊区块(2 分钟)。当然,用户并不是像这样完全快,因此您可能需要添加一些至少是基线数字 10 倍的填充,即大约 100 个块(20 分钟)。尽管如此,100 个区块还是比进入 7 天挑战期的 50400 多个区块要短得多。这里一定还有别的东西。

攻击者可以用他们的钱做什么?攻击者的目标是阻止挑战者将他们的挑战交易包含在链上。毕竟,如果挑战交易成功,那么攻击就会失败。攻击者基本上有三种潜在的策略:

  • 1)对挑战者进行直接 DoS 攻击,首先阻止他们与 L1 网络交互
  • 2)通过昂贵的交易向 L1 网络发送垃圾邮件,以推高 Gas 价格并阻止挑战者进行交易
  • 3)通过控制大量验证者来直接审查挑战者

为什么挑战期是7天?

  • 因为它比保守的餐巾纸数学下限要长得多,也许更重要的是,它为整个以太坊社区留下了足够的时间陷入大规模困境。简而言之,利用 Optimistic Rollup 所需的攻击类型会在很长一段时间内显着降低以太坊上的交易体验。每个人都会非常生气。诚实的验证者会突然出现,愿意提交挑战交易以阻止攻击。一周给了我们足够的时间来协调社交层面的这种恢复。

更多详细内容,见:

  • Why is the Optimistic Rollup challenge period 7 days?

5. OP发展历程

OP发展历程为:

  • 2019年
    • 6 月,Plasma Group 开发人员创建了一个名为 Optimism Rollup 的可扩展性解决方案
  • 2020年
    • 2月,兼容EVM的乐观虚拟机(OVM)上线测试阶段
    • 9月,推出带有Optimism Rollup解决方案的测试网
  • 2021年
    • 一月份,Optimism 推出了 Alpha 版本
    • 10月,EVM主网升级启动
    • 8 月,以太坊和 Optimism 之间的成熟区块链桥梁启动。该桥此前只允许传输已启用的 ERC-20 代币
    • 12 月,加密世界庆祝 Optimism 主网发布
  • 2022年
    • 4月,宣布成立乐观集体(治理实验),并进行了多次空投。由于这一治理变化,乐观主义人民银行被解散,并创建了一个非营利组织——乐观主义基金会
    • 5 月,$OP 币开始分配

参考资料

[1] 2023年4月 为什么从 OP 主网转出资产需要等待一周?
[2] Sending Data Between L1 and L2
[3] L2IV RESEARCH 2024年1月29日 Why we invested in Rome Protocol? The Solana-Based Shared Sequencer
[4] Dispute Game
[5] Rollup Protocol Overview
[6] Withdrawal Flow
[7] Why is the Optimistic Rollup challenge period 7 days?
[8] 2023年10月博客 Ethereum’s Optimistic Future: An Introduction to Optimistic Rollups
[9] Optimism

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索智能巡检机器人深度学习的奥秘

机器人深度学习(Robot Deep Learning)是指利用深度学习技术,使机器人能够从大量数据中学习和提取特征,进而实现自主感知、决策和行动的能力。通过深度学习算法,机器人可以从传感器获取的数据中自动学习模式和规律&…

微信开放平台第三方开发,实现代小程序认证申请

大家好,我是小悟 微信小程序认证整体流程总共分为五个环节:认证信息填写、平台初审、管理员验证、供应商审核和认证成功。 服务商可以代小程序发起认证申请。平台将对认证基础信息进行初步校验。通过后,平台将向管理员微信下发模板消息&…

Redis(十)SpringBoot集成Redis

文章目录 连接单机mvnYMLController.javaRedisConfig.java 连接集群YML问题复现 RedisTemplate方式 连接单机 mvn <!--Redis--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</art…

SRC实战 | 信息泄露挖掘

本文由掌控安全学院 - 叴龙 投稿 1. 信息搜集 首先老语法先搜集一波&#xff0c;毕竟没有钓鱼和sg的能力&#xff0c;只能找注册站去挖挖了。 web.title”XX大学”&&web.body”忘记密码”&&web.body”注册” 2. 漏洞挖掘 这里找到一个可以注册网站接口&…

蓝桥杯 第 1 场 小白入门赛

目录 1.蘑菇炸弹 2.构造数字 3.小蓝的金牌梦 4.合并石子加强版 5.简单的LIS问题 6.期望次数 1.蘑菇炸弹 我们直接依照题目 在中间位置的数进行模拟即可 void solve(){cin>>n;vector<int> a(n1);for(int i1;i<n;i) cin>>a[i];int ans0;for(int i2;i…

XSS haozi靶场通关笔记

XSS靶场地址&#xff1a;alert(1) 靶场的要求是输出一个内容为1的弹窗&#xff1b;这个靶场限制了输入位置只能是input code&#xff1b;而且浏览器发送内容时会自动进行url编码&#xff1b;所以重点考察的是代码的分析和基础payload构造&#xff1b;一切完成在当前页面&#…

【数据结构】链表(单链表实现+测试+原码)

1.链表 1.1 链表的概念及结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。 现实中&#xff1a;链表就像是一列动车&#xff0c;一节连着一节 数据结构中的链表 注意: 1.从上图可看出…

React16源码: React中LegacyContext的源码实现

LegacyContext 老的 contextAPI 也就是我们使用 childContextTypes 这种声明方式来从父节点为它的子树提供 context 内容的这么一种方式遗留的contextAPI 在 react 17 被彻底移除了&#xff0c;就无法使用了那么为什么要彻底移除这个contextAPI的使用方式呢&#xff1f;因为它…

知识点积累系列(一)golang语言篇【持续更新】

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 知识点积累 系列文章的第一篇&#xff0c;记录golang语言相关的知识点 1.结构体的mapstructure是什么 mapstructure:"default" mapstructure是一个Go语言的库&#xff0c;用于将一个map中的值映射到…

C语言王道第八周一题

Description 初始化顺序表&#xff08;顺序表中元素为整型&#xff09;&#xff0c;里边的元素是 1,2,3&#xff0c;然后通过 scanf 读取一个元素&#xff08;假如插入的是 6&#xff09;&#xff0c;插入到第 2 个位置&#xff0c;打印输出顺序表&#xff0c;每个 元素占 3 个…

添加了gateway之后远程调用失败

前端提示500&#xff0c;后端提示[400 ] during [GET] to [http://userservice/user/1] 原因是这个&#xff0c;因为在请求地址写了两个参数&#xff0c;实际上只传了一个参数 解决方案&#xff1a;加上(required false)并重启所有相关服务

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson13(买东西)(餐厅点餐事宜;询问有无座位;食物如何调理:牛排、咖啡等;菜单等相关)

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 13 At the Restaurant 在餐厅会话A会话B笔记餐厅询问有无座位&#xff1b;餐厅电话订座其他餐厅询问有无座位的问法 吸烟区与非吸烟区&#xff08;smo…

[力扣 Hot100]Day18 矩阵置零

题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 出处 思路 在原数组上直接操作势必会出现“冗余”的0&#xff0c;即原本[i,j]处不是0&#xff0c;例如由于i行的其他位置有0导致[i,j]…

Shell中的AWK

1.awk的工作原理 逐行读取文本&#xff0c;默认以空格或tab键为分隔符进行分隔&#xff0c;将分隔所得的各个字段保存到内建变量中&#xff0c;并按模式或者条件执行编辑命令。awk倾向于将一行分成多个"字段"然后再进行处理。awk信息的读入也是逐行读取的&#xff0…

day38_MySQL

今日内容 0 复习昨日 1 引言 2 数据库 3 数据库管理系统 4 MySQL 5 SQL语言 0 复习昨日 1 引言 1.1 现有的数据存储方式有哪些&#xff1f; Java程序存储数据&#xff08;变量、对象、数组、集合&#xff09;&#xff0c;数据保存在内存中&#xff0c;属于瞬时状态存储。文件&…

删除有序数组中的重复项[简单]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个非严格递增排列的数组nums&#xff0c;请你原地删除重复出现的元素&#xff0c;使每个元素只出现一次&#xff0c;返回删除后数组的新长度。元素的相对顺序应该保持一致。然后返回nums中唯一元素的个数。 考虑nums的唯一元素…

Source Insight 4的使用经验

问题1 函数结束提示符<<end tagDebugData>> 在source insight里的options→preference→syntax decorations→auto annotations→annotate closing braceswith end-comments关闭或启动显示. 但是有的有有的没有&#xff0c;奇怪! 参照网络答案&#xff1a; Sou…

DataX介绍

一、介绍 DataX 是一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 github地址 详细文档 操作手册 支持数据框架如下&#xff1a; 架构 Reader&#xff1…

IPV4 转 IPV6 解决方案大全

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

App全测试扫描漏洞工具

APP 有漏洞被测要下架&#xff0c;怎么处理&#xff1f; 如题&#xff0c;今天被问到&#xff1a;市面上有什么好的 APP 漏洞扫描工具推荐&#xff1f;我们的 APP 有漏洞&#xff0c;需要下架 APP&#xff1f; 前言 事情的经过是这样的&#xff1a; 1&#xff1a;学员公司测试…