Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #268 from keep-network/refactor-keep-bridge
Browse files Browse the repository at this point in the history
Refactor IKeep/KeepBridge

Here we move functions implemented in a KeepBridge contract 
responsible for communication with keep to be directly executed 
by a deposit.

We pull interfaces from keep-tecdsa to communicate with the 
contracts deployed as part of keep system.

There still remained IKeep interface which holds functions which
 are not yet implemented on the keep side. As it's done this interface 
should be replaced by IECDSAKeep calls.
  • Loading branch information
pdyraga authored Sep 30, 2019
2 parents 1f49d0a + e9d3724 commit bc7384a
Show file tree
Hide file tree
Showing 33 changed files with 698 additions and 767 deletions.
126 changes: 72 additions & 54 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,72 @@ jobs:
lint_js:
executor: docker-node
steps:
- checkout
- run:
name: Lint JS
command: |
cd implementation/
npm install
npm run js:lint
- checkout
- run:
name: Authenticate GitHub Package Registry
working_directory: ~/project/implementation
command: echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc
- run:
name: Lint JS
working_directory: ~/project/implementation
command: |
npm install
npm run js:lint
lint_solidity:
executor: docker-node
steps:
- checkout
- run:
name: Lint Solidity
working_directory: ~/project/implementation
command: |
set -ex
npm install
npm run sol:lint
- checkout
- run:
name: Authenticate GitHub Package Registry
working_directory: ~/project/implementation
command: echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc
- run:
name: Lint Solidity
working_directory: ~/project/implementation
command: |
set -ex
npm install
npm run sol:lint
unit_test_contracts:
executor: docker-node
steps:
- checkout
- run: sudo npm install -g [email protected]
- run:
name: Running testrpc
command: ganache-cli
background: true
- run:
name: Run NPM tests
working_directory: ~/project/implementation/contracts
command: npm install && npm run test
- checkout
- run: sudo npm install -g [email protected]
- run:
name: Running testrpc
working_directory: ~/project/implementation
command: ganache-cli
background: true
- run:
name: Authenticate GitHub Package Registry
working_directory: ~/project/implementation
command: echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc
- run:
name: Run NPM tests
working_directory: ~/project/implementation
command: npm install && npm run test
integration_test_contracts:
executor: docker-node
steps:
- checkout
- run: sudo npm install -g [email protected]
- run:
name: Running testrpc
command: ganache-cli
background: true
- run:
name: Deploy Uniswap
working_directory: ~/project/implementation/scripts
command: ./deploy_uniswap.sh
- run:
name: Run NPM tests
working_directory: ~/project/implementation/contracts
command: npm install && npm run integration-test
- checkout
- run: sudo npm install -g [email protected]
- run:
name: Running testrpc
working_directory: ~/project/implementation
command: ganache-cli
background: true
- run:
name: Authenticate GitHub Package Registry
working_directory: ~/project/implementation
command: echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc
- run:
name: Deploy Uniswap
working_directory: ~/project/implementation/scripts
command: ./deploy_uniswap.sh
- run:
name: Run NPM tests
working_directory: ~/project/implementation
command: npm install && npm run integration-test
generate_pngs:
docker:
- image: keepnetwork/texlive:15
Expand Down Expand Up @@ -208,21 +226,21 @@ jobs:
image: initcontainer-provision-tbtc-maintainers
tag: latest
publish_contract_data:
executor: gcp-cli/default
steps:
- attach_workspace:
at: /tmp/tbtc
- gcp-cli/install
- gcp-cli/initialize:
google-project-id: GOOGLE_PROJECT_ID
google-compute-zone: GOOGLE_COMPUTE_ZONE_A
# This param doesn't actually set anything, leaving here as a reminder to check when they fix it.
gcloud-service-key: GCLOUD_SERVICE_KEY
- run:
name: Upload contract data
command: |
cd /tmp/tbtc/contracts
gsutil -m cp * gs://keep-dev-contract-data/tbtc
executor: gcp-cli/default
steps:
- attach_workspace:
at: /tmp/tbtc
- gcp-cli/install
- gcp-cli/initialize:
google-project-id: GOOGLE_PROJECT_ID
google-compute-zone: GOOGLE_COMPUTE_ZONE_A
# This param doesn't actually set anything, leaving here as a reminder to check when they fix it.
gcloud-service-key: GCLOUD_SERVICE_KEY
- run:
name: Upload contract data
command: |
cd /tmp/tbtc/contracts
gsutil -m cp * gs://keep-dev-contract-data/tbtc
workflows:
version: 2
Expand Down
1 change: 1 addition & 0 deletions implementation/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@keep-network:registry=https://npm.pkg.github.com/keep-network
2 changes: 0 additions & 2 deletions implementation/contracts/deposit/Deposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,11 @@ contract Deposit {
function createNewDeposit(
address _TBTCSystem,
address _TBTCToken,
address _KeepBridge,
uint256 _m,
uint256 _n
) public payable returns (bool) {
self.TBTCSystem = _TBTCSystem;
self.TBTCToken = _TBTCToken;
self.KeepBridge = _KeepBridge;
self.createNewDeposit(_m, _n);
return true;
}
Expand Down
30 changes: 12 additions & 18 deletions implementation/contracts/deposit/DepositFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ pragma solidity ^0.5.10;
import {SafeMath} from "bitcoin-spv/contracts/SafeMath.sol";
import {BytesLib} from "bitcoin-spv/contracts/BytesLib.sol";
import {BTCUtils} from "bitcoin-spv/contracts/BTCUtils.sol";

import {IECDSAKeep} from "@keep-network/keep-tecdsa/contracts/api/IECDSAKeep.sol";

import {TBTCToken} from "../system/TBTCToken.sol";
import {IKeep} from "../interfaces/IKeep.sol";
import {TBTCSystem} from "../system/TBTCSystem.sol";
import {DepositUtils} from "./DepositUtils.sol";
import {DepositLiquidation} from "./DepositLiquidation.sol";
import {DepositStates} from "./DepositStates.sol";
Expand Down Expand Up @@ -39,17 +42,6 @@ library DepositFunding {
_d.signingGroupPubkeyY = bytes32(0);
}

/// @notice get the signer pubkey for our keep
/// @dev calls out to the keep contract, should get 64 bytes back
/// @return the 64 byte pubkey
function getKeepPubkeyResult(DepositUtils.Deposit storage _d) public view returns (bytes memory) {
IKeep _keep = IKeep(_d.KeepBridge);
bytes memory _pubkey = _keep.getKeepPubkey(_d.keepAddress);
/* solium-disable-next-line */
require(_pubkey.length == 64, "public key not set or not 64-bytes long");
return _pubkey;
}

/// @notice The system can spin up a new deposit
/// @dev This should be called by an approved contract, not a developer
/// @param _d deposit storage pointer
Expand All @@ -63,10 +55,10 @@ library DepositFunding {
) public returns (bool) {
require(_d.inStart(), "Deposit setup already requested");

IKeep _keep = IKeep(_d.KeepBridge);
// TODO: Whole value is stored as funder bond in the deposit, but part
// of it should be transferred to keep: https://github.com/keep-network/tbtc/issues/297
_d.keepAddress = TBTCSystem(_d.TBTCSystem).requestNewKeep(_m, _n);

/* solium-disable-next-line value-in-payable */
_d.keepAddress = _keep.requestNewKeep(_m, _n); // kinda gross but
_d.signingGroupRequestedAt = block.timestamp;

_d.setAwaitingSignerSetup();
Expand Down Expand Up @@ -150,10 +142,12 @@ library DepositFunding {
/// @return True if successful, otherwise revert
function retrieveSignerPubkey(DepositUtils.Deposit storage _d) public {
require(_d.inAwaitingSignerSetup(), "Not currently awaiting signer setup");
bytes memory _keepResult = getKeepPubkeyResult(_d);

_d.signingGroupPubkeyX = _keepResult.slice(0, 32).toBytes32();
_d.signingGroupPubkeyY = _keepResult.slice(32, 32).toBytes32();
bytes memory _publicKey = IECDSAKeep(_d.keepAddress).getPublicKey();
require(_publicKey.length == 64, "public key not set or not 64-bytes long");

_d.signingGroupPubkeyX = _publicKey.slice(0, 32).toBytes32();
_d.signingGroupPubkeyY = _publicKey.slice(32, 32).toBytes32();
require(_d.signingGroupPubkeyY != bytes32(0) && _d.signingGroupPubkeyX != bytes32(0), "Keep returned bad pubkey");
_d.fundingProofTimerStart = block.timestamp;

Expand Down
4 changes: 2 additions & 2 deletions implementation/contracts/deposit/DepositLiquidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {BTCUtils} from "bitcoin-spv/contracts/BTCUtils.sol";
import {DepositStates} from "./DepositStates.sol";
import {DepositUtils} from "./DepositUtils.sol";
import {TBTCConstants} from "./TBTCConstants.sol";
import {IKeep} from "../interfaces/IKeep.sol";
import {IBondedECDSAKeep} from "../external/IBondedECDSAKeep.sol";
import {OutsourceDepositLogging} from "./OutsourceDepositLogging.sol";
import {TBTCToken} from "../system/TBTCToken.sol";

Expand Down Expand Up @@ -42,7 +42,7 @@ library DepositLiquidation {
bytes32 _signedDigest,
bytes memory _preimage
) public returns (bool _isFraud) {
IKeep _keep = IKeep(_d.KeepBridge);
IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);
return _keep.submitSignatureFraud(_d.keepAddress, _v, _r, _s, _signedDigest, _preimage);
}

Expand Down
28 changes: 16 additions & 12 deletions implementation/contracts/deposit/DepositRedemption.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {BytesLib} from "bitcoin-spv/contracts/BytesLib.sol";
import {ValidateSPV} from "bitcoin-spv/contracts/ValidateSPV.sol";
import {CheckBitcoinSigs} from "bitcoin-spv/contracts/SigCheck.sol";
import {DepositUtils} from "./DepositUtils.sol";
import {IKeep} from "../interfaces/IKeep.sol";
import {IBondedECDSAKeep} from "../external/IBondedECDSAKeep.sol";
import {IECDSAKeep} from "@keep-network/keep-tecdsa/contracts/api/IECDSAKeep.sol";
import {DepositStates} from "./DepositStates.sol";
import {OutsourceDepositLogging} from "./OutsourceDepositLogging.sol";
import {TBTCConstants} from "./TBTCConstants.sol";
Expand All @@ -33,19 +34,20 @@ library DepositRedemption {
address _tbtcTokenAddress = _d.TBTCToken;
TBTCToken _tbtcToken = TBTCToken(_tbtcTokenAddress);

IKeep _keep = IKeep(_d.KeepBridge);
IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);

_tbtcToken.approve(_d.KeepBridge, DepositUtils.signerFee());
_tbtcToken.approve(_d.keepAddress, DepositUtils.signerFee());
_keep.distributeERC20ToKeepGroup(_d.keepAddress, _tbtcTokenAddress, DepositUtils.signerFee());
}

/// @notice approves a digest for signing by our keep group
/// @dev calls out to the keep contract
/// @param _digest the digest to approve
/// @return true if approved, otherwise revert
function approveDigest(DepositUtils.Deposit storage _d, bytes32 _digest) public returns (bool) {
IKeep _keep = IKeep(_d.KeepBridge);
return _keep.approveDigest(_d.keepAddress, _digest);
/// @notice Approves digest for signing by a keep
/// @dev Calls given keep to sign the digest. Records a current timestamp
/// for given digest
/// @param _digest Digest to approve
function approveDigest(DepositUtils.Deposit storage _d, bytes32 _digest) internal {
IECDSAKeep(_d.keepAddress).sign(_digest);

_d.approvedDigests[_digest] = block.timestamp;
}

function redemptionTBTCBurn(DepositUtils.Deposit storage _d) private {
Expand Down Expand Up @@ -93,7 +95,8 @@ library DepositRedemption {
_d.initialRedemptionFee = _requestedFee;
_d.withdrawalRequestTime = block.timestamp;
_d.lastRequestedDigest = _sighash;
require(approveDigest(_d, _sighash), "Keep returned false");

approveDigest(_d, _sighash);

_d.setAwaitingWithdrawalSignature();
_d.logRedemptionRequested(
Expand Down Expand Up @@ -168,7 +171,8 @@ library DepositRedemption {
// Ratchet the signature and redemption proof timeouts
_d.withdrawalRequestTime = block.timestamp;
_d.lastRequestedDigest = _sighash;
require(approveDigest(_d, _sighash), "Keep returned false");

approveDigest(_d, _sighash);

// Go back to waiting for a signature
_d.setAwaitingWithdrawalSignature();
Expand Down
26 changes: 15 additions & 11 deletions implementation/contracts/deposit/DepositUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {BytesLib} from "bitcoin-spv/contracts/BytesLib.sol";
import {TBTCConstants} from "./TBTCConstants.sol";
import {ITBTCSystem} from "../interfaces/ITBTCSystem.sol";
import {IERC721} from "openzeppelin-solidity/contracts/token/ERC721/IERC721.sol";
import {IKeep} from "../interfaces/IKeep.sol";
import {IBondedECDSAKeep} from "../external/IBondedECDSAKeep.sol";
import {TBTCToken} from "../system/TBTCToken.sol";

library DepositUtils {
Expand All @@ -24,7 +24,6 @@ library DepositUtils {
// SET DURING CONSTRUCTION
address TBTCSystem;
address TBTCToken;
address KeepBridge;
uint8 currentState;

// SET ON FRAUD
Expand All @@ -51,6 +50,11 @@ library DepositUtils {
bytes8 utxoSizeBytes; // LE uint. the size of the deposit UTXO in satoshis
uint256 fundedAt; // timestamp when funding proof was received
bytes utxoOutpoint; // the 36-byte outpoint of the custodied UTXO

/// @notice Map of timestamps for transaction digests approved for signing
/// @dev Holds a timestamp from the moment when the transaction digest
/// was approved for signing
mapping (bytes32 => uint256) approvedDigests;
}

/// @notice Gets the current block difficulty
Expand Down Expand Up @@ -363,7 +367,7 @@ library DepositUtils {
/// @dev Calls the keep contract to do so
/// @return The amount of bonded ETH in wei
function fetchBondAmount(Deposit storage _d) public view returns (uint256) {
IKeep _keep = IKeep(_d.KeepBridge);
IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);
return _keep.checkBondAmount(_d.keepAddress);
}

Expand All @@ -374,13 +378,13 @@ library DepositUtils {
return abi.encodePacked(_b).reverseEndianness().bytesToUint();
}

/// @notice determines whether a digest has been approved for our keep group
/// @dev calls out to the keep contract, storing a 256bit int costs the same as a bool
/// @param _digest the digest to check approval time for
/// @return the time it was approved. 0 if unapproved
/// @notice Gets timestamp of digest approval for signing
/// @dev Identifies entry in the recorded approvals by keep ID and digest pair
/// @param _digest Digest to check approval for
/// @return Timestamp from the moment of recording the digest for signing.
/// Returns 0 if the digest was not approved for signing
function wasDigestApprovedForSigning(Deposit storage _d, bytes32 _digest) public view returns (uint256) {
IKeep _keep = IKeep(_d.KeepBridge);
return _keep.wasDigestApprovedForSigning(_d.keepAddress, _digest);
return _d.approvedDigests[_digest];
}

/// @notice Looks up the deposit beneficiary by calling the tBTC system
Expand All @@ -406,7 +410,7 @@ library DepositUtils {
/// @return the amount of ether seized
function seizeSignerBonds(Deposit storage _d) public returns (uint256) {
uint256 _preCallBalance = address(this).balance;
IKeep _keep = IKeep(_d.KeepBridge);
IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);
_keep.seizeSignerBonds(_d.keepAddress);
uint256 _postCallBalance = address(this).balance;
require(_postCallBalance > _preCallBalance, "No funds received, unexpected");
Expand All @@ -428,7 +432,7 @@ library DepositUtils {
/// @return true if successful, otherwise revert
function pushFundsToKeepGroup(Deposit storage _d, uint256 _ethValue) public returns (bool) {
require(address(this).balance >= _ethValue, "Not enough funds to send");
IKeep _keep = IKeep(_d.KeepBridge);
IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);
return _keep.distributeEthToKeepGroup.value(_ethValue)(_d.keepAddress);
}
}
Loading

0 comments on commit bc7384a

Please sign in to comment.