Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nonergodic committed Jan 5, 2025
1 parent 3c3f5b1 commit b0590b6
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 54 deletions.
71 changes: 35 additions & 36 deletions src/libraries/CoreBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,47 +25,46 @@ library CoreBridgeLib {
uint8 consistencyLevel,
bytes calldata payload
) { unchecked {
//The following implementation looks better on the surface, but due to the extra external
// function calls and having to drag the large guardian set around, it is actually more
// expensive than using the suboptimal verifyVM call directly.
//
// IWormhole iwormhole = IWormhole(wormhole);
// ( uint32 guardianSetIndex,
// GuardianSignature[] memory guardianSignatures,
// uint envelopeOffset
// ) = encodedVaa.decodeVaaHeaderCdUnchecked();

// IWormhole.Signature[] memory legacySigs = VaaLib.asIWormholeSignatures(guardianSignatures);
// IWormhole.GuardianSet memory guardianSet = iwormhole.getGuardianSet(guardianSetIndex);
// uint expirationTime = guardianSet.expirationTime;
// if (eagerAnd(expirationTime != 0, expirationTime < block.timestamp))
// //if the specified guardian set is expired, we try using the current guardian set as an adhoc
// // repair attempt (there's almost certainly never more than 2 valid guardian sets at a time)
// guardianSet = iwormhole.getGuardianSet(iwormhole.getCurrentGuardianSetIndex());

// bytes32 vaaHash = encodedVaa.calcVaaDoubleHashCd(envelopeOffset);
// //see https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/Messages.sol#L111
// (bool valid, ) = iwormhole.verifySignatures(vaaHash, legacySigs, guardianSet);

// if (eagerOr(legacySigs.length < minSigsForQuorum(guardianSet.keys.length), !valid))
// revert VerificationFailed();
IWormhole iwormhole = IWormhole(wormhole);

// return encodedVaa.decodeVaaBodyCd(envelopeOffset);
uint offset = VaaLib.checkVaaVersionCd(encodedVaa);
uint32 guardianSetIndex;
(guardianSetIndex, offset) = encodedVaa.asUint32CdUnchecked(offset);

IWormhole.VM memory vm = encodedVaa.decodeVmStructCd();
(bool valid, ) = IWormhole(wormhole).verifyVM(vm);
IWormhole.GuardianSet memory guardianSet = iwormhole.getGuardianSet(guardianSetIndex);
uint expirationTime = guardianSet.expirationTime;
if (eagerAnd(expirationTime != 0, expirationTime < block.timestamp))
//if the specified guardian set is expired, we try using the current guardian set as an adhoc
// repair attempt (there's almost certainly never more than 2 valid guardian sets at a time)
guardianSet = iwormhole.getGuardianSet(iwormhole.getCurrentGuardianSetIndex());

if (!valid)
uint signatureCount;
(signatureCount, offset) = encodedVaa.asUint8CdUnchecked(offset);
//this check will also handle empty guardian sets, because minSigsForQuorum(0) is 1 and so
// subsequent signature verification will fail
if (signatureCount < minSigsForQuorum(guardianSet.keys.length))
revert VerificationFailed();

timestamp = vm.timestamp;
nonce = vm.nonce;
emitterChainId = vm.emitterChainId;
emitterAddress = vm.emitterAddress;
sequence = vm.sequence;
consistencyLevel = vm.consistencyLevel;
uint payloadOffset = encodedVaa.skipVaaHeaderCd() + VaaLib.ENVELOPE_SIZE;
(payload, ) = encodedVaa.sliceCdUnchecked(payloadOffset, encodedVaa.length - payloadOffset);
uint envelopeOffset = offset + signatureCount * VaaLib.GUARDIAN_SIGNATURE_SIZE;
bytes32 vaaHash = encodedVaa.calcVaaDoubleHashCd(envelopeOffset);
uint prevGuardianIndex = 0;
uint guardianCount = guardianSet.keys.length;
for (uint i = 0; i < signatureCount; ++i) {
uint guardianIndex; bytes32 r; bytes32 s; uint8 v;
(guardianIndex, r, s, v, offset) = encodedVaa.decodedGuardianSignatureCdUnchecked(offset);
address signatory = ecrecover(vaaHash, v, r, s);
if (eagerOr(
eagerOr(
!eagerOr(i == 0, guardianIndex > prevGuardianIndex),
guardianIndex >= guardianCount
),
signatory != guardianSet.keys[guardianIndex]
))
revert VerificationFailed();
prevGuardianIndex = guardianIndex;
}

return encodedVaa.decodeVaaBodyCd(envelopeOffset);
}}

function verifyHashIsGuardianSigned(
Expand Down
95 changes: 77 additions & 18 deletions src/libraries/VaaLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,23 @@ library VaaLib {
uint internal constant HEADER_SIGNATURE_ARRAY_OFFSET =
HEADER_SIGNATURE_COUNT_OFFSET + HEADER_SIGNATURE_COUNT_SIZE;

uint internal constant HEADER_GUARDIAN_SIGNATURE_SIZE =
1 /*guardianSetIndex*/ + 65 /*signaturesize*/;
uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET = 0;
uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE = 1;

uint internal constant GUARDIAN_SIGNATURE_R_OFFSET =
GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET + GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE;
uint internal constant GUARDIAN_SIGNATURE_R_SIZE = 32;

uint internal constant GUARDIAN_SIGNATURE_S_OFFSET =
GUARDIAN_SIGNATURE_R_OFFSET + GUARDIAN_SIGNATURE_R_SIZE;
uint internal constant GUARDIAN_SIGNATURE_S_SIZE = 32;

uint internal constant GUARDIAN_SIGNATURE_V_OFFSET =
GUARDIAN_SIGNATURE_S_OFFSET + GUARDIAN_SIGNATURE_S_SIZE;
uint internal constant GUARDIAN_SIGNATURE_V_SIZE = 1;

uint internal constant GUARDIAN_SIGNATURE_SIZE =
GUARDIAN_SIGNATURE_V_OFFSET + GUARDIAN_SIGNATURE_V_SIZE;

uint internal constant ENVELOPE_TIMESTAMP_OFFSET = 0;
uint internal constant ENVELOPE_TIMESTAMP_SIZE = 4;
Expand Down Expand Up @@ -450,7 +465,7 @@ library VaaLib {
bytes calldata encodedVaa
) internal pure returns (uint envelopeOffset) { unchecked {
(uint sigCount, uint offset) = encodedVaa.asUint8CdUnchecked(HEADER_SIGNATURE_COUNT_OFFSET);
envelopeOffset = offset + sigCount * HEADER_GUARDIAN_SIGNATURE_SIZE;
envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
}}

function skipVaaHeaderMemUnchecked(
Expand All @@ -460,7 +475,7 @@ library VaaLib {
uint offset = headerOffset + HEADER_SIGNATURE_COUNT_OFFSET;
uint sigCount;
(sigCount, offset) = encoded.asUint8MemUnchecked(offset);
envelopeOffset = offset + sigCount * HEADER_GUARDIAN_SIGNATURE_SIZE;
envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
}}

//see WARNING box at the top
Expand Down Expand Up @@ -696,13 +711,9 @@ library VaaLib {
(signersLen, offset) = encodedVaa.asUint8CdUnchecked(offset);

signatures = new GuardianSignature[](signersLen);
for (uint i = 0; i < signersLen; ++i) {
(signatures[i].guardianIndex, offset) = encodedVaa.asUint8CdUnchecked(offset);
(signatures[i].r, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(signatures[i].s, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(signatures[i].v, offset) = encodedVaa.asUint8CdUnchecked(offset);
signatures[i].v += SIGNATURE_RECOVERY_MAGIC;
}
for (uint i = 0; i < signersLen; ++i)
(signatures[i], offset) = decodedGuardianSignatureStructCdUnchecked(encodedVaa, offset);

envelopeOffset = offset;
}}

Expand Down Expand Up @@ -730,13 +741,9 @@ library VaaLib {
(signersLen, offset) = encoded.asUint8MemUnchecked(offset);

signatures = new GuardianSignature[](signersLen);
for (uint i = 0; i < signersLen; ++i) {
(signatures[i].guardianIndex, offset) = encoded.asUint8MemUnchecked(offset);
(signatures[i].r, offset) = encoded.asBytes32MemUnchecked(offset);
(signatures[i].s, offset) = encoded.asBytes32MemUnchecked(offset);
(signatures[i].v, offset) = encoded.asUint8MemUnchecked(offset);
signatures[i].v += SIGNATURE_RECOVERY_MAGIC;
}
for (uint i = 0; i < signersLen; ++i)
(signatures[i], offset) = decodedGuardianSignatureStructMemUnchecked(encoded, offset);

envelopeOffset = offset;
}}

Expand All @@ -750,6 +757,58 @@ library VaaLib {
) = decodeVaaHeaderMemUnchecked(encoded, offset);
}

function decodedGuardianSignatureCdUnchecked(
bytes calldata encodedVaa,
uint offset
) internal pure returns (
uint8 guardianIndex,
bytes32 r,
bytes32 s,
uint8 v,
uint newOffset
) { unchecked {
(guardianIndex, offset) = encodedVaa.asUint8CdUnchecked(offset);
(r, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(s, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(v, offset) = encodedVaa.asUint8CdUnchecked(offset);
v += SIGNATURE_RECOVERY_MAGIC;
newOffset = offset;
}}

function decodedGuardianSignatureStructCdUnchecked(
bytes calldata encodedVaa,
uint offset
) internal pure returns (GuardianSignature memory ret, uint newOffset) {
(ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
decodedGuardianSignatureCdUnchecked(encodedVaa, offset);
}

function decodedGuardianSignatureMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (
uint8 guardianIndex,
bytes32 r,
bytes32 s,
uint8 v,
uint newOffset
) { unchecked {
(guardianIndex, offset) = encoded.asUint8MemUnchecked(offset);
(r, offset) = encoded.asBytes32MemUnchecked(offset);
(s, offset) = encoded.asBytes32MemUnchecked(offset);
(v, offset) = encoded.asUint8MemUnchecked(offset);
v += SIGNATURE_RECOVERY_MAGIC;
newOffset = offset;
}}

function decodedGuardianSignatureStructMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (GuardianSignature memory ret, uint newOffset) {
(ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
decodedGuardianSignatureMemUnchecked(encoded, offset);
}

function decodeVaaPayloadCd(
bytes calldata encodedVaa,
uint offset
Expand Down

0 comments on commit b0590b6

Please sign in to comment.