首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Opensea源代码

Opensea源代码
EN

Ethereum用户
提问于 2022-04-26 10:09:52
回答 1查看 223关注 0票数 0
代码语言:javascript
复制
for (i = 0; i < words; i++) {
    /* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
    assembly {
        let commonIndex := mul(0x20, add(1, i))
        let maskValue := mload(add(mask, commonIndex))
        mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
    }
}

有人能帮我解释一下这些密码吗?谢谢

EN

回答 1

Ethereum用户

发布于 2022-04-26 12:46:11

好的,

这段代码是guardedArrayReplace函数的一部分,该函数实质上用另一个字节数组的内容覆盖字节数组的内容,但它可能会根据所提供的掩码而有所不同。

作为对按位操作的提醒,使用两个字节值作为解释:

假设我们有一个array值为0x1234,一个期望值为0xaabb,掩码为0x00FF。掩码将用于选择要从desired中获取哪些位以写入array。反转掩码可以让您从array中保留哪些位。

array & not(mask) = 0x1200:丢弃array中掩码未指向的值。

desired & mask = 0x00bb:只保留掩码在desired中指向的值。

将这两者结合起来:or(array & not(mask), desired & mask,我们得到0x12bb。在这里,我们有效地用来自arraydesired值更新了mask所指出的值。

代码语言:javascript
复制
for (i = 0; i < words; i++) {
    /* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
    assembly {
        let commonIndex := mul(0x20, add(1, i))
        let maskValue := mload(add(mask, commonIndex))
        mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
    }
}

这个部分正在处理32个字节块,即使底层数据是以字节划分的。只要有可能,这只是一种一次性处理32种元素的方法。

代码语言:javascript
复制
let commonIndex := mul(0x20, add(1, i))

计算在循环的特定迭代中处理的32个字节块的内存索引(或地址)。在第一次迭代中,我们的目标是内存索引0x20 (32) * (i + 1)的数据。+ 1只是用来跳过包含数组长度的前32个字节。

代码语言:javascript
复制
let maskValue := mload(add(mask, commonIndex))

使用以下事实:arraymaskdesired必须具有相同的长度(请参阅函数中的require语句),只需从mask数组加载当用desired中的特定部分覆盖array的特定部分时应该应用的32个字节。

代码语言:javascript
复制
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))

我们会把它拆开的:

mstore参数是:

  • add(array, commonIndex)
  • or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex))))

第一个是我们将要写入修改后的32个字节的地址,第二个是要写入的值。

or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex))))

其中,and(not(maskValue), mload(add(array, commonIndex)))接受来自array的值,并且只保留未被maskValue标记的字节。另一方面,and(maskValue, mload(add(desired, commonIndex)))接受来自desired的值,并且只保留由maskValue标记的字节。周围的or融合了我们想要从array中保留的东西和我们想从desired获取的东西。

然后在适当的32字节槽处用array写入此值。

这个过程被重复了尽可能多次,这样的话,更新一个大小为64字节(32 * 2)的数组只需要2次迭代,而不是64次,如果你要逐字节进行的话。

我希望这能回答你的问题。

票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/126929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档