lay0_update
42 removals
110 lines
32 additions
103 lines
// SPDX-License-Identifier: BUSL-1.1
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.6;
pragma solidity 0.7.6;
pragma abicoder v2;
pragma abicoder v2;
import "./utility/LayerZeroPacket.sol";
import "./LayerZeroPacket.sol";
import "./utility/Buffer.sol";
import "./Buffer.sol";
import "./ILayerZeroValidationLibrary.sol";
import "./ILayerZeroValidationLibrary.sol";
import "./utility/UltraLightNodeEVMDecoder.sol";
import "./UltraLightNodeEVMDecoder.sol";
contract MPTValidator is ILayerZeroValidationLibrary {
contract MPTValidatorV2 is ILayerZeroValidationLibrary {
using RLPDecode for RLPDecode.RLPItem;
using RLPDecode for RLPDecode.RLPItem;
using RLPDecode for RLPDecode.Iterator;
using RLPDecode for RLPDecode.Iterator;
using Buffer for Buffer.buffer;
using Buffer for Buffer.buffer;
using SafeMath for uint;
using SafeMath for uint;
bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;
bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;
struct ULNLog{
struct ULNLog{
bytes32 contractAddress;
bytes32 contractAddress;
bytes32 topicZeroSig;
bytes32 topicZeroSig;
bytes data;
bytes data;
}
}
function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external pure override returns (LayerZeroPacket.Packet memory packet) {
function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external pure override returns (LayerZeroPacket.Packet memory packet) {
(uint16 remoteChainId, bytes[] memory proof, uint[] memory pointers, uint receiptIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes[], uint[], uint, uint));
(uint16 remoteChainId, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes[], uint[], uint));
ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptIndex, logIndex, proof, pointers);
ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);
require(log.topicZeroSig == PACKET_SIGNATURE, "LayerZero: packet not recognized"); //data
require(log.topicZeroSig == PACKET_SIGNATURE, "ProofLib: packet not recognized"); //data
return getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);
return _getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);
}
}
function _getVerifiedLog(bytes32 hashRoot, uint receiptSlotIndex, uint logIndex, bytes[] memory proof, uint[] memory pointers) internal pure returns(ULNLog memory) {
function _getVerifiedLog(bytes32 hashRoot, uint[] memory paths, uint logIndex, bytes[] memory proof) internal pure returns(ULNLog memory) {
// walk and assert the hash links of MPT
require(paths.length == proof.length, "ProofLib: invalid proof size");
uint pointer;
RLPDecode.RLPItem memory item;
bytes memory proofBytes;
bytes memory proofBytes;
for (uint i = 0; i < proof.length; i++) {
for (uint i = 0; i < proof.length; i++) {
proofBytes = proof[i];
proofBytes = proof[i];
require(hashRoot == keccak256(proofBytes), "LayerZero: invalid hashlink");
require(hashRoot == keccak256(proofBytes), "ProofLib: invalid hashlink");
if (i < pointers.length) {
item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);
pointer = pointers[i];
if (i < proof.length - 1) hashRoot = bytes32(item.toUint());
assembly { hashRoot := mload(add(add(proofBytes, pointer), 32)) }
}
}
}
// build the iterator for the proofBytes
// burning status + gasUsed + logBloom
RLPDecode.Iterator memory it = RLPDecode.toRlpItem(proofBytes).iterator();
RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);
RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();
// get the receipt item from either branch or leaf node
RLPDecode.RLPItem memory receiptItem = it.item.getItemByIndex(receiptSlotIndex);
// it = targetReceiptIter
it = receiptItem.typeOffset().iterator();
it.next(); // status
it.next(); // gasUsed
it.next(); // logBloom
// it = targetLogIter
it = it.next().getItemByIndex(logIndex).iterator();
ULNLog memory log;
ULNLog memory log;
log.contractAddress = bytes32(it.next().toUint());
log.contractAddress = bytes32(it.next().toUint());
log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());
log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());
log.data = it.next().toBytes();
log.data = it.next().toBytes();
return log;
return log;
}
}
// profiling and test
// profiling and test
function getVerifyLog(bytes32 hashRoot, uint receiptSlotIndex, uint logIndex, bytes[] memory proof, uint[] memory pointers) external pure returns(ULNLog memory){
function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external pure returns(ULNLog memory){
return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof, pointers);
return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);
}
}
function getPacket(
function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external pure returns(LayerZeroPacket.Packet memory) {
return _getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);
}
function _getPacket(
bytes memory data,
bytes memory data,
uint16 srcChain,
uint16 srcChain,
uint sizeOfSrcAddress,
uint sizeOfSrcAddress,
bytes32 ulnAddress
bytes32 ulnAddress
) internal pure returns (LayerZeroPacket.Packet memory) {
) internal pure returns (LayerZeroPacket.Packet memory) {
uint16 dstChainId;
uint16 dstChainId;
address dstAddress;
address dstAddress;
uint size;
uint size;
uint64 nonce;
uint64 nonce;
// The log consists of the destination chain id and then a bytes payload
// The log consists of the destination chain id and then a bytes payload
// 0--------------------------------------------31
// 0--------------------------------------------31
// 0 | destination chain id
// 0 | destination chain id
// 32 | defines bytes array
// 32 | defines bytes array
// 64 |
// 64 |
// 96 | bytes array size
// 96 | bytes array size
// 128 | payload
// 128 | payload
assembly {
assembly {
dstChainId := mload(add(data, 32))
dstChainId := mload(add(data, 32))
size := mload(add(data, 96)) /// size of the byte array
size := mload(add(data, 96)) /// size of the byte array
nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24
nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24
dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8
dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8
}
}
Buffer.buffer memory srcAddressBuffer;
Buffer.buffer memory srcAddressBuffer;
srcAddressBuffer.init(sizeOfSrcAddress);
srcAddressBuffer.init(sizeOfSrcAddress);
srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8
srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8
uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);
uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);
Buffer.buffer memory payloadBuffer;
Buffer.buffer memory payloadBuffer;
payloadBuffer.init(payloadSize);
payloadBuffer.init(payloadSize);
payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8
payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8
// LayerZeroPacket.Packet memory packet = LayerZeroPacket.Packet(srcChain, dstChainId, nonce, address(dstAddress), srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);
return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);
return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, address(dstAddress), srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);
}
}
}
}