Skip to content

Commit

Permalink
Merge pull request #153 from tellor-io/nickEVM
Browse files Browse the repository at this point in the history
Nick evm
  • Loading branch information
themandalore authored May 31, 2024
2 parents 040db9c + dca6096 commit 8d3601c
Show file tree
Hide file tree
Showing 160 changed files with 1,535 additions and 2,960,887 deletions.
22 changes: 22 additions & 0 deletions evm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Tellor EVM Contracts

## Pieces


### Data Bridge

### Forking Contract Examples

### Token Bridge

### UsingTellor



## Compiling Testing


```
npx hardhat compile
npx hardhat test
```
180 changes: 68 additions & 112 deletions evm/contracts/bridge/BlobstreamO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,60 @@ pragma solidity 0.8.22;

import "./ECDSA.sol";
import "./Constants.sol";
//import "hardhat/console.sol";

struct Validator {
address addr;
uint256 power;
}

struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
struct OracleAttestationData {
bytes32 queryId;
ReportData report;
uint256 attestationTimestamp;//timestamp of validatorSignatures on report
}

struct ReportData {
bytes value;
uint256 timestamp;
uint256 timestamp;//timestamp of reporter signature aggregation
uint256 aggregatePower;
uint256 previousTimestamp;
uint256 nextTimestamp;
}

struct OracleAttestationData {
bytes32 queryId;
ReportData report;
uint256 attestationTimestamp;
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}

struct Validator {
address addr;
uint256 power;
}


/// @title BlobstreamO: Tellor Layer -> EVM, Oracle relay.
/// @dev The relay relies on a set of signers to attest to some event on
/// Tellor Layer. These signers are the validator set, who sign over every
/// block. At least 2/3 of the voting power of the current
/// view of the validator set must sign off on new relayed events.
contract BlobstreamO is ECDSA {

/*Storage*/
address public guardian; /// Able to reset the validator set only if the validator set becomes stale.
bytes32 public lastValidatorSetCheckpoint; ///Domain-separated commitment to the latest validator set.
uint256 public powerThreshold; /// Voting power required to submit a new update.
uint256 public validatorTimestamp; /// Timestamp of the block where validator set is updated.
uint256 public unbondingPeriod; /// Time period after which a validator can withdraw their stake.
address public guardian; /// Able to reset the validator set only if the validator set becomes stale.
uint256 public validatorTimestamp; /// Timestamp of the block where validator set is updated.

/*Events*/
event ValidatorSetUpdated(
uint256 _powerThreshold,
uint256 _validatorTimestamp,
bytes32 _validatorSetHash
);
event ValidatorSetUpdated(uint256 _powerThreshold, uint256 _validatorTimestamp, bytes32 _validatorSetHash);

/*Errors*/
error InsufficientVotingPower();
error InvalidSignature();
error MalformedCurrentValidatorSet();
error NotConsensusValue();
error NotGuardian();
error StaleValidatorSet();
error SuppliedValidatorSetInvalid();
error ValidatorSetNotStale();
error NotConsensusValue();

/*Functions*/
/// @param _powerThreshold Initial voting power that is needed to approve operations
Expand Down Expand Up @@ -117,9 +117,7 @@ contract BlobstreamO is ECDSA {
revert MalformedCurrentValidatorSet();
}
// Check that the supplied current validator set matches the saved checkpoint.
bytes32 _currentValidatorSetHash = _computeValidatorSetHash(
_currentValidatorSet
);
bytes32 _currentValidatorSetHash = keccak256(abi.encode(_currentValidatorSet));
if (
_domainSeparateValidatorSetHash(
powerThreshold,
Expand Down Expand Up @@ -150,25 +148,50 @@ contract BlobstreamO is ECDSA {
_newValidatorSetHash
);
}

/*Getter functions*/
/// @notice This getter verifies a given piece of data vs Validator signatures
/// @param _attestData The data being verified
/// @param _currentValidatorSet array of current validator set
/// @param _sigs Signatures.
function verifyOracleData(
OracleAttestationData calldata _attest,
Validator[] calldata _currentValidatorSet,
Signature[] calldata _sigs
) external view returns (bool) {
return _verifyOracleData(_attest, _currentValidatorSet, _sigs);
}

function verifyConsensusOracleData(
OracleAttestationData calldata _attest,
OracleAttestationData calldata _attestData,
Validator[] calldata _currentValidatorSet,
Signature[] calldata _sigs
) external view returns (bool) {
if (_attest.report.aggregatePower < powerThreshold) {
revert NotConsensusValue();
) external view{
if (_currentValidatorSet.length != _sigs.length) {
revert MalformedCurrentValidatorSet();
}
return _verifyOracleData(_attest, _currentValidatorSet, _sigs);
// Check that the supplied current validator set matches the saved checkpoint.
bytes32 _currentValidatorSetHash = keccak256(abi.encode(_currentValidatorSet));
if (
_domainSeparateValidatorSetHash(
powerThreshold,
validatorTimestamp,
_currentValidatorSetHash
) != lastValidatorSetCheckpoint
) {
revert SuppliedValidatorSetInvalid();
}
bytes32 _dataDigest = keccak256(
abi.encode(
NEW_REPORT_ATTESTATION_DOMAIN_SEPARATOR,
_attestData.queryId,
_attestData.report.value,
_attestData.report.timestamp,
_attestData.report.aggregatePower,
_attestData.report.previousTimestamp,
_attestData.report.nextTimestamp,
lastValidatorSetCheckpoint,
_attestData.attestationTimestamp
)
);
_checkValidatorSignatures(
_currentValidatorSet,
_sigs,
_dataDigest,
powerThreshold
);
}

/*Internal functions*/
Expand All @@ -189,16 +212,16 @@ contract BlobstreamO is ECDSA {
revert StaleValidatorSet();
}
uint256 _cumulativePower = 0;
for (uint256 i = 0; i < _currentValidators.length; i++) {
for (uint256 _i = 0; _i < _currentValidators.length; _i++) {
// If the signature is nil, then it's not present so continue.
if (_sigs[i].r == 0 && _sigs[i].s == 0 && _sigs[i].v == 0) {
if (_sigs[_i].r == 0 && _sigs[_i].s == 0 && _sigs[_i].v == 0) {
continue;
}
// Check that the current validator has signed off on the hash.
if (!_verifySig(_currentValidators[i].addr, _digest, _sigs[i])) {
if (!_verifySig(_currentValidators[_i].addr, _digest, _sigs[_i])) {
revert InvalidSignature();
}
_cumulativePower += _currentValidators[i].power;
_cumulativePower += _currentValidators[_i].power;
// Break early to avoid wasting gas.
if (_cumulativePower >= _powerThreshold) {
break;
Expand All @@ -209,37 +232,6 @@ contract BlobstreamO is ECDSA {
}
}

/// @dev Computes the hash of a validator set.
/// @param _validators The validator set to hash.
/// @return The hash of the validator set.
function _computeValidatorSetHash(
Validator[] calldata _validators
) internal pure returns (bytes32) {
return keccak256(abi.encode(_validators));
}

/// @dev A hash of all relevant information about the oracle attestation.
/// @param _attest The oracle attestation.
/// @return The domain separated hash of the oracle attestation.
function _domainSeparateOracleAttestationData(
OracleAttestationData calldata _attest
) internal view returns (bytes32) {
return
keccak256(
abi.encode(
NEW_REPORT_ATTESTATION_DOMAIN_SEPARATOR,
_attest.queryId,
_attest.report.value,
_attest.report.timestamp,
_attest.report.aggregatePower,
_attest.report.previousTimestamp,
_attest.report.nextTimestamp,
lastValidatorSetCheckpoint,
_attest.attestationTimestamp
)
);
}

/// @dev A hash of all relevant information about the validator set.
/// @param _powerThreshold Amount of voting power needed to approve operations. (2/3 of total)
/// @param _validatorTimestamp The timestamp of the block where validator set is updated.
Expand All @@ -260,42 +252,6 @@ contract BlobstreamO is ECDSA {
)
);
}

/// @notice Used for verifying oracle data attestations
/// @param _attestData The oracle attestation data
/// @param _currentValidatorSet The current validator set
/// @param _sigs The attestations
function _verifyOracleData(
OracleAttestationData calldata _attestData,
Validator[] calldata _currentValidatorSet,
Signature[] calldata _sigs
) internal view returns (bool) {
if (_currentValidatorSet.length != _sigs.length) {
revert MalformedCurrentValidatorSet();
}
// Check that the supplied current validator set matches the saved checkpoint.
bytes32 _currentValidatorSetHash = _computeValidatorSetHash(
_currentValidatorSet
);
if (
_domainSeparateValidatorSetHash(
powerThreshold,
validatorTimestamp,
_currentValidatorSetHash
) != lastValidatorSetCheckpoint
) {
revert SuppliedValidatorSetInvalid();
}
bytes32 _dataDigest = _domainSeparateOracleAttestationData(_attestData);
_checkValidatorSignatures(
_currentValidatorSet,
_sigs,
_dataDigest,
powerThreshold
);
return true;
}

/// @notice Utility function to verify Tellor Layer signatures
/// @param _signer The address that signed the message.
/// @param _digest The digest that was signed.
Expand All @@ -306,7 +262,7 @@ contract BlobstreamO is ECDSA {
bytes32 _digest,
Signature calldata _sig
) internal pure returns (bool) {
bytes32 _digestSha256 = sha256(abi.encodePacked(_digest));
return _signer == ECDSA.recover(_digestSha256, _sig.v, _sig.r, _sig.s);
_digest = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _digest));
return _signer == ecrecover(_digest, _sig.v, _sig.r, _sig.s);
}
}
9 changes: 5 additions & 4 deletions evm/contracts/bridge/Constants.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

/// @dev bytes32 encoding of the string "checkpoint"
bytes32 constant VALIDATOR_SET_HASH_DOMAIN_SEPARATOR =
0x636865636b706f696e7400000000000000000000000000000000000000000000;

/// @dev bytes32 encoding of the string "transactionBatch"
bytes32 constant DATA_ROOT_TUPLE_ROOT_DOMAIN_SEPARATOR =
0x7472616e73616374696f6e426174636800000000000000000000000000000000;

/// @dev bytes32 encoding of the string "tellorNewReport"
bytes32 constant NEW_REPORT_ATTESTATION_DOMAIN_SEPARATOR =
0x74656c6c6f7243757272656e744174746573746174696f6e0000000000000000;

/// @dev bytes32 encoding of the string "checkpoint"
bytes32 constant VALIDATOR_SET_HASH_DOMAIN_SEPARATOR =
0x636865636b706f696e7400000000000000000000000000000000000000000000;


1 change: 0 additions & 1 deletion evm/contracts/bridge/ECDSA.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
Expand Down
2 changes: 1 addition & 1 deletion evm/contracts/bridge/mock/BridgeCaller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract BridgeCaller {
Validator[] calldata _currentValidatorSet,
Signature[] calldata _sigs
) public {
require(bridge.verifyOracleData(_attest, _currentValidatorSet, _sigs));
bridge.verifyOracleData(_attest, _currentValidatorSet, _sigs);
oracleData = _attest.report.value;
oracleDataTimestamp = _attest.report.timestamp;
}
Expand Down
4 changes: 2 additions & 2 deletions evm/contracts/interfaces/IBridgeProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
pragma solidity 0.8.22;

interface IBridgeProxy {
function paused() external returns (bool);
function updateImplementation(address _newImplementation) external;
function pauseBridge() external;
function paused() external returns (bool);
function unpauseBridge() external;
function updateImplementation(address _newImplementation) external;
}
Loading

0 comments on commit 8d3601c

Please sign in to comment.