|
@@ -15,7 +15,8 @@ contract Messages is Getters {
|
|
|
/// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption
|
|
/// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption
|
|
|
function parseAndVerifyVM(bytes calldata encodedVM) public view returns (Structs.VM memory vm, bool valid, string memory reason) {
|
|
function parseAndVerifyVM(bytes calldata encodedVM) public view returns (Structs.VM memory vm, bool valid, string memory reason) {
|
|
|
vm = parseVM(encodedVM);
|
|
vm = parseVM(encodedVM);
|
|
|
- (valid, reason) = verifyVM(vm);
|
|
|
|
|
|
|
+ /// setting checkHash to false as we can trust the hash field in this case given that parseVM computes and then sets the hash field above
|
|
|
|
|
+ (valid, reason) = verifyVMInternal(vm, false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -24,11 +25,46 @@ contract Messages is Getters {
|
|
|
* - it aims to ensure the guardianSet is not expired
|
|
* - it aims to ensure the guardianSet is not expired
|
|
|
* - it aims to ensure the VM has reached quorum
|
|
* - it aims to ensure the VM has reached quorum
|
|
|
* - it aims to verify the signatures provided against the guardianSet
|
|
* - it aims to verify the signatures provided against the guardianSet
|
|
|
|
|
+ * - it aims to verify the hash field provided against the contents of the vm
|
|
|
*/
|
|
*/
|
|
|
function verifyVM(Structs.VM memory vm) public view returns (bool valid, string memory reason) {
|
|
function verifyVM(Structs.VM memory vm) public view returns (bool valid, string memory reason) {
|
|
|
|
|
+ (valid, reason) = verifyVMInternal(vm, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @dev `verifyVMInternal` serves to validate an arbitrary vm against a valid Guardian set
|
|
|
|
|
+ * if checkHash is set then the hash field of the vm is verified against the hash of its contents
|
|
|
|
|
+ * in the case that the vm is securely parsed and the hash field can be trusted, checkHash can be set to false
|
|
|
|
|
+ * as the check would be redundant
|
|
|
|
|
+ */
|
|
|
|
|
+ function verifyVMInternal(Structs.VM memory vm, bool checkHash) internal view returns (bool valid, string memory reason) {
|
|
|
/// @dev Obtain the current guardianSet for the guardianSetIndex provided
|
|
/// @dev Obtain the current guardianSet for the guardianSetIndex provided
|
|
|
Structs.GuardianSet memory guardianSet = getGuardianSet(vm.guardianSetIndex);
|
|
Structs.GuardianSet memory guardianSet = getGuardianSet(vm.guardianSetIndex);
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Verify that the hash field in the vm matches with the hash of the contents of the vm if checkHash is set
|
|
|
|
|
+ * WARNING: This hash check is critical to ensure that the vm.hash provided matches with the hash of the body.
|
|
|
|
|
+ * Without this check, it would not be safe to call verifyVM on it's own as vm.hash can be a valid signed hash
|
|
|
|
|
+ * but the body of the vm could be completely different from what was actually signed by the guardians
|
|
|
|
|
+ */
|
|
|
|
|
+ if(checkHash){
|
|
|
|
|
+ bytes memory body = abi.encodePacked(
|
|
|
|
|
+ vm.timestamp,
|
|
|
|
|
+ vm.nonce,
|
|
|
|
|
+ vm.emitterChainId,
|
|
|
|
|
+ vm.emitterAddress,
|
|
|
|
|
+ vm.sequence,
|
|
|
|
|
+ vm.consistencyLevel,
|
|
|
|
|
+ vm.payload
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes32 vmHash = keccak256(abi.encodePacked(keccak256(body)));
|
|
|
|
|
+
|
|
|
|
|
+ if(vmHash != vm.hash){
|
|
|
|
|
+ return (false, "vm.hash doesn't match body");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* @dev Checks whether the guardianSet has zero keys
|
|
* @dev Checks whether the guardianSet has zero keys
|
|
|
* WARNING: This keys check is critical to ensure the guardianSet has keys present AND to ensure
|
|
* WARNING: This keys check is critical to ensure the guardianSet has keys present AND to ensure
|
|
@@ -65,6 +101,7 @@ contract Messages is Getters {
|
|
|
return (true, "");
|
|
return (true, "");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* @dev verifySignatures serves to validate arbitrary sigatures against an arbitrary guardianSet
|
|
* @dev verifySignatures serves to validate arbitrary sigatures against an arbitrary guardianSet
|
|
|
* - it intentionally does not solve for expectations within guardianSet (you should use verifyVM if you need these protections)
|
|
* - it intentionally does not solve for expectations within guardianSet (you should use verifyVM if you need these protections)
|