diff --git a/contract/contracts/oracle/Deploy.sol b/contract/contracts/oracle/Deploy.sol index 63d7aa3..050c51b 100644 --- a/contract/contracts/oracle/Deploy.sol +++ b/contract/contracts/oracle/Deploy.sol @@ -11,107 +11,109 @@ import "@chainlink/contracts/src/v0.7/ConfirmedOwner.sol"; */ contract ContainerDeploy is ChainlinkClient, ConfirmedOwner { - using Chainlink for Chainlink.Request; + using Chainlink for Chainlink.Request; - uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 - string public currentDeployStatus; + uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 + string public currentDeployStatus; - event RequestContainerDeployFulfilled( - bytes32 indexed requestId, - string deployStatus - ); + event RequestContainerDeployFulfilled( + bytes32 indexed requestId, + string deployStatus + ); - /** - * Constructor FVM link token - * @dev LINK address in FVM network: _link_token_address + /** + * Constructor FVM link token + * @dev LINK address in FVM network: _link_token_address * @dev Check https://docs.chain.link/docs/link-token-contracts/ for LINK address for the right network */ - constructor(address _link_token_address) ConfirmedOwner(msg.sender) { - setChainlinkToken(_link_token_address); - } - - /** - * Request container cloud api to deploy. - */ - function requestContainerDeploy( - address _oracle, - string memory _jobId, - string memory _deploy_code, - string memory _request_url - ) public { - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillDeployStatus.selector - ); - req.add("post",_request_url); - req.add("yaml", _deploy_code); - address from = msg.sender; - req.add("sender",addressToString(from)); - sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - } - - function fulfillDeployStatus( - bytes32 _requestId, - string calldata _deploy_status - ) public recordChainlinkFulfillment(_requestId) { - emit RequestContainerDeployFulfilled(_requestId, _deploy_status); - currentDeployStatus = _deploy_status; + constructor(address _link_token_address) ConfirmedOwner(msg.sender) { + setChainlinkToken(_link_token_address); + } + + /** + * Request container cloud api to deploy. + */ + function requestContainerDeploy( + address _oracle, + string memory _jobId, + string memory _deploy_code, + string memory _request_url, + string memory _userId + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillDeployStatus.selector + ); + req.add("post",_request_url); + req.add("yaml", _deploy_code); + req.add("userid", _userId); + address from = msg.sender; + req.add("sender",addressToString(from)); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } + + function fulfillDeployStatus( + bytes32 _requestId, + string calldata _deploy_status + ) public recordChainlinkFulfillment(_requestId) { + emit RequestContainerDeployFulfilled(_requestId, _deploy_status); + currentDeployStatus = _deploy_status; + } + + function getChainlinkToken() public view returns (address) { + return chainlinkTokenAddress(); + } + + function withdrawLink() public onlyOwner { + LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); + require( + link.transfer(msg.sender, link.balanceOf(address(this))), + "Unable to transfer" + ); + } + + function cancelRequest( + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public onlyOwner { + cancelChainlinkRequest( + _requestId, + _payment, + _callbackFunctionId, + _expiration + ); + } + + function stringToBytes32( + string memory source + ) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; } - function getChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); + assembly { + // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) } + } - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require( - link.transfer(msg.sender, link.balanceOf(address(this))), - "Unable to transfer" - ); - } + function addressToString(address _addr) public pure returns (string memory) { + bytes32 value = bytes32(uint256(_addr)); + bytes memory alphabet = "0123456789abcdef"; + bytes memory str = new bytes(42); - function cancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public onlyOwner { - cancelChainlinkRequest( - _requestId, - _payment, - _callbackFunctionId, - _expiration - ); - } + str[0] = "0"; + str[1] = "x"; - function stringToBytes32( - string memory source - ) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { - // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } + for (uint256 i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; } - function addressToString(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - - str[0] = "0"; - str[1] = "x"; - - for (uint256 i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - - return string(str); - } + return string(str); + } } diff --git a/contract/contracts/oracle/MeshControl.sol b/contract/contracts/oracle/MeshControl.sol index 700a712..44965f3 100644 --- a/contract/contracts/oracle/MeshControl.sol +++ b/contract/contracts/oracle/MeshControl.sol @@ -9,153 +9,153 @@ import "@chainlink/contracts/src/v0.8/ConfirmedOwner.sol"; */ contract MeshControl is ChainlinkClient, ConfirmedOwner { - using Chainlink for Chainlink.Request; + using Chainlink for Chainlink.Request; - // Result data map: requestId => result - mapping (bytes32 => string) public _result; + // Result data map: requestId => result + mapping (bytes32 => string) public _result; - uint256 private fee; - bytes32 public currentKey; - string public currentData; + uint256 private fee; + bytes32 public currentKey; + string public currentData; - struct Site { - bytes32 jobId; - address oracle; - string host; - } - // site configuration - mapping (string => Site) public _sites; + struct Site { + bytes32 jobId; + address oracle; + string host; + } + // site configuration + mapping (string => Site) public _sites; - /** - * @notice Initialize the link token and target oracle + /** + * @notice Initialize the link token and target oracle * @dev The oracle address must be an Operator contract for multiword response * */ - constructor(uint256 _fee, address _link) ConfirmedOwner(msg.sender) { - setChainlinkToken(_link); - // setChainlinkOracle(_oracle); - fee = _fee; // 0,1 * 10**18 (Varies by network and job) - } - - // Register site configuration - function setSites(string memory _name, string memory _jobId, address _oracle, string memory host) public{ - require(msg.sender == owner()); - require(bytes(_name).length > 0); - require(bytes(_jobId).length > 0); - require(_oracle != address(0)); - require(bytes(host).length > 0); - _sites[_name] = Site(stringToBytes32(_jobId), _oracle, host); - } - - // Service circuit breaker - function fuseRule( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/fuse/rule")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - // Verify site metadata - modifier verificationSite( - string memory _siteName - ) { - require(_sites[_siteName].oracle != address(0), "This site does not exist"); - _; - } - - // Service throttling - function rateLimitRule( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/rate/rule")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - // Query data - function getResultData( - bytes32 _requestUID - ) public view returns (string memory){ - return _result[_requestUID]; - } - - /** - * @notice Request variable string from the oracle + constructor(uint256 _fee, address _link) ConfirmedOwner(msg.sender) { + setChainlinkToken(_link); + // setChainlinkOracle(_oracle); + fee = _fee; // 0,1 * 10**18 (Varies by network and job) + } + + // Register site configuration + function setSites(string memory _name, string memory _jobId, address _oracle, string memory host) public{ + require(msg.sender == owner()); + require(bytes(_name).length > 0); + require(bytes(_jobId).length > 0); + require(_oracle != address(0)); + require(bytes(host).length > 0); + _sites[_name] = Site(stringToBytes32(_jobId), _oracle, host); + } + + // Service circuit breaker + function fuseRule( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/fuse/rule")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + // Verify site metadata + modifier verificationSite( + string memory _siteName + ) { + require(_sites[_siteName].oracle != address(0), "This site does not exist"); + _; + } + + // Service throttling + function rateLimitRule( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/rate/rule")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + // Query data + function getResultData( + bytes32 _requestUID + ) public view returns (string memory){ + return _result[_requestUID]; + } + + /** + * @notice Request variable string from the oracle */ - function request( - string memory _method, - string memory _url, - string memory _headers, - string memory _requestData, - string memory _siteName, - bytes32 _requestUID - ) internal verificationSite(_siteName){ - _method = (bytes(_method).length > 0 ? _method : "GET"); - require(bytes(_url).length > 0); - _headers = (bytes(_headers).length > 0 ? _headers : "W10="); - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - - Chainlink.Request memory req = buildChainlinkRequest( - _sites[_siteName].jobId, - address(this), - this.fulfill.selector - ); - req.add("url", _url); - req.add("method", _method); - req.add("headers", _headers); - req.add("requestData", _requestData); - req.addBytes("requestUID", abi.encodePacked(_requestUID)); - sendChainlinkRequestTo(_sites[_siteName].oracle, req, fee); - } - - event RequestFulfilled(bytes32 indexed _requestUID, string data); - - /** - * @notice Fulfillment function for variable string + function request( + string memory _method, + string memory _url, + string memory _headers, + string memory _requestData, + string memory _siteName, + bytes32 _requestUID + ) internal verificationSite(_siteName){ + _method = (bytes(_method).length > 0 ? _method : "GET"); + require(bytes(_url).length > 0); + _headers = (bytes(_headers).length > 0 ? _headers : "W10="); + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + + Chainlink.Request memory req = buildChainlinkRequest( + _sites[_siteName].jobId, + address(this), + this.fulfill.selector + ); + req.add("url", _url); + req.add("method", _method); + req.add("headers", _headers); + req.add("requestData", _requestData); + req.addBytes("requestUID", abi.encodePacked(_requestUID)); + sendChainlinkRequestTo(_sites[_siteName].oracle, req, fee); + } + + event RequestFulfilled(bytes32 indexed _requestUID, string data); + + /** + * @notice Fulfillment function for variable string * @dev This is called by the oracle. recordChainlinkFulfillment must be used. */ - function fulfill( - bytes32 _requestId, - bytes32 _requestUID, - string memory _stringData - ) public recordChainlinkFulfillment(_requestId) { - emit RequestFulfilled(_requestUID, _stringData); - _result[_requestUID] = _stringData; - currentKey = _requestUID; - currentData = _stringData; + function fulfill( + bytes32 _requestId, + bytes32 _requestUID, + string memory _stringData + ) public recordChainlinkFulfillment(_requestId) { + emit RequestFulfilled(_requestUID, _stringData); + _result[_requestUID] = _stringData; + currentKey = _requestUID; + currentData = _stringData; + } + + function stringToBytes32( + string memory source + ) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; } - function stringToBytes32( - string memory source - ) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { - // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } + assembly { + // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) } + } } diff --git a/contract/contracts/oracle/Node.sol b/contract/contracts/oracle/Node.sol index 72861ef..c2ebea7 100644 --- a/contract/contracts/oracle/Node.sol +++ b/contract/contracts/oracle/Node.sol @@ -11,195 +11,195 @@ import "@chainlink/contracts/src/v0.7/ConfirmedOwner.sol"; */ contract ContainerNode is ChainlinkClient, ConfirmedOwner { - using Chainlink for Chainlink.Request; - - uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 - mapping(string => string) public currentNodeListResult; - mapping(string => string) public currentNodeSchedulingStatusMap; - mapping(string => string) public currentNodeSchedulingStatusResult; - - event RequestNodeListFulfilled( - bytes32 indexed requestId, - string indexed nodeListRawJson - ); - - event RequestNodeSchedulingStatusFulfilled( - bytes32 indexed requestId, - string indexed nodeSchedulingStatusRawJson - ); - - /** - * Constructor FVM link token - * @dev LINK address in FVM network: _link_token_address + using Chainlink for Chainlink.Request; + + uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 + mapping(string => string) public currentNodeListResult; + mapping(string => string) public currentNodeSchedulingStatusMap; + mapping(string => string) public currentNodeSchedulingStatusResult; + + event RequestNodeListFulfilled( + bytes32 indexed requestId, + string indexed nodeListRawJson + ); + + event RequestNodeSchedulingStatusFulfilled( + bytes32 indexed requestId, + string indexed nodeSchedulingStatusRawJson + ); + + /** + * Constructor FVM link token + * @dev LINK address in FVM network: _link_token_address * @dev Check https://docs.chain.link/docs/link-token-contracts/ for LINK address for the right network */ - constructor(address _link_token_address) ConfirmedOwner(msg.sender) { - setChainlinkToken(_link_token_address); - } + constructor(address _link_token_address) ConfirmedOwner(msg.sender) { + setChainlinkToken(_link_token_address); + } - /** - * Request container cloud api to deploy. - * @param _oracle deploy oracle contract address + /** + * Request container cloud api to deploy. + * @param _oracle deploy oracle contract address * @param _jobId chainlink job id by def in chainlink ui. * @param _page nodelist page num * @param _limit nodelist page size * @param _request_url backend server url to get nodelist. */ - function requestNodeList( - address _oracle, - string memory _jobId, - string memory _page, - string memory _limit, - string memory _request_url //nodelist url - ) public { - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillNodeList.selector - ); - req.add("api", _request_url); - req.add("page", _page); - req.add("limit", _limit); - sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - } - - /** - * @param _requestId is backfilled jobid by chainlink. + function requestNodeList( + address _oracle, + string memory _jobId, + string memory _page, + string memory _limit, + string memory _request_url //nodelist url + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillNodeList.selector + ); + req.add("api", _request_url); + req.add("page", _page); + req.add("limit", _limit); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } + + /** + * @param _requestId is backfilled jobid by chainlink. * @param _node_list_cid is container cloud returned nodes json data that is backfilled by chainlink. * @param _cid_update_timestamp is container cloud returned node list timestamp that is backfilled by chainlink. */ - function fulfillNodeList( - bytes32 _requestId, - string memory _node_list_cid, - string memory _cid_update_timestamp - ) public recordChainlinkFulfillment(_requestId) { - emit RequestNodeListFulfilled(_requestId, _node_list_cid); - if (bytes(_node_list_cid).length > 0) { - currentNodeListResult["cid"] = _node_list_cid; - currentNodeListResult["timestamp"] = _cid_update_timestamp; - } + function fulfillNodeList( + bytes32 _requestId, + string memory _node_list_cid, + string memory _cid_update_timestamp + ) public recordChainlinkFulfillment(_requestId) { + emit RequestNodeListFulfilled(_requestId, _node_list_cid); + if (bytes(_node_list_cid).length > 0) { + currentNodeListResult["cid"] = _node_list_cid; + currentNodeListResult["timestamp"] = _cid_update_timestamp; } + } - /** - * Request container cloud api to scheduling node. - * @param _oracle deploy oracle contract address + /** + * Request container cloud api to scheduling node. + * @param _oracle deploy oracle contract address * @param _jobId chainlink job id by def in chainlink ui. * @param _request_url backend server url to cordon node */ - function requestContainerNodeCordon( - address _oracle, - string memory _jobId, - string memory _request_url //nodecordon url - ) public { - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillNodeSchedulingStatus.selector - ); - req.add("api", _request_url); - sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - } + function requestContainerNodeCordon( + address _oracle, + string memory _jobId, + string memory _request_url //nodecordon url + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillNodeSchedulingStatus.selector + ); + req.add("api", _request_url); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } - /** - * Request container cloud api to scheduling node. - * @param _oracle deploy oracle contract address + /** + * Request container cloud api to scheduling node. + * @param _oracle deploy oracle contract address * @param _jobId chainlink job id by def in chainlink ui. * @param _request_url backend server url to uncordon node */ - function requestContainerNodeUncordon( - address _oracle, - string memory _jobId, - string memory _request_url //nodeuncordon url - ) public { - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillNodeSchedulingStatus.selector - ); - req.add("api", _request_url); - sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - } + function requestContainerNodeUncordon( + address _oracle, + string memory _jobId, + string memory _request_url //nodeuncordon url + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillNodeSchedulingStatus.selector + ); + req.add("api", _request_url); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } - /** - * @param _requestId is backfilled jobid by chainlink. + /** + * @param _requestId is backfilled jobid by chainlink. * @param _name is container cloud returned node name * @param _data is container cloud returned node scheduling status json data that is backfilled by chainlink. */ - function fulfillNodeSchedulingStatus( - bytes32 _requestId, - string memory _name, - string memory _data - ) public recordChainlinkFulfillment(_requestId) { - emit RequestNodeSchedulingStatusFulfilled(_requestId, _data); - if (bytes(_name).length > 0) { - currentNodeSchedulingStatusMap[_name] = _data; - } + function fulfillNodeSchedulingStatus( + bytes32 _requestId, + string memory _name, + string memory _data + ) public recordChainlinkFulfillment(_requestId) { + emit RequestNodeSchedulingStatusFulfilled(_requestId, _data); + if (bytes(_name).length > 0) { + currentNodeSchedulingStatusMap[_name] = _data; } + } - /** - * @param _node_scheduling_status_cid is container cloud returned cluster-info cid data that is backfilled by chainlink. + /** + * @param _node_scheduling_status_cid is container cloud returned cluster-info cid data that is backfilled by chainlink. * @param _cid_update_timestamp is container cloud returned node scheduling status timestamp that is backfilled by chainlink. */ - function fulfillAllNodeSchedulingStatus( - string memory _node_scheduling_status_cid, - string memory _cid_update_timestamp - ) public { - if (bytes(_node_scheduling_status_cid).length > 0) { - currentNodeSchedulingStatusResult["cid"] = _node_scheduling_status_cid; - currentNodeSchedulingStatusResult["timestamp"] = _cid_update_timestamp; - } - } - - function getChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); + function fulfillAllNodeSchedulingStatus( + string memory _node_scheduling_status_cid, + string memory _cid_update_timestamp + ) public { + if (bytes(_node_scheduling_status_cid).length > 0) { + currentNodeSchedulingStatusResult["cid"] = _node_scheduling_status_cid; + currentNodeSchedulingStatusResult["timestamp"] = _cid_update_timestamp; } + } - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require( - link.transfer(msg.sender, link.balanceOf(address(this))), - "Unable to transfer" - ); - } - - function cancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public onlyOwner { - cancelChainlinkRequest( - _requestId, - _payment, - _callbackFunctionId, - _expiration - ); - } + function getChainlinkToken() public view returns (address) { + return chainlinkTokenAddress(); + } - function stringToBytes32( - string memory source - ) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { - // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } + function withdrawLink() public onlyOwner { + LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); + require( + link.transfer(msg.sender, link.balanceOf(address(this))), + "Unable to transfer" + ); + } + + function cancelRequest( + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public onlyOwner { + cancelChainlinkRequest( + _requestId, + _payment, + _callbackFunctionId, + _expiration + ); + } + + function stringToBytes32( + string memory source + ) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; } - //merge strings - function mergeStrings( - string memory a, - string memory b - ) private pure returns (string memory newStr) { - bytes memory _a = bytes(a); - bytes memory _b = bytes(b); - bytes memory res = new bytes(_a.length + _b.length); - for (uint i = 0; i < _a.length; i++) res[i] = _a[i]; - for (uint j = 0; j < _b.length; j++) res[_a.length + j] = _b[j]; - newStr = string(res); + assembly { + // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) } + } + + //merge strings + function mergeStrings( + string memory a, + string memory b + ) private pure returns (string memory newStr) { + bytes memory _a = bytes(a); + bytes memory _b = bytes(b); + bytes memory res = new bytes(_a.length + _b.length); + for (uint i = 0; i < _a.length; i++) res[i] = _a[i]; + for (uint j = 0; j < _b.length; j++) res[_a.length + j] = _b[j]; + newStr = string(res); + } } diff --git a/contract/contracts/oracle/Pod.sol b/contract/contracts/oracle/Pod.sol index ad4b5e6..ea98b29 100644 --- a/contract/contracts/oracle/Pod.sol +++ b/contract/contracts/oracle/Pod.sol @@ -11,107 +11,139 @@ import "@chainlink/contracts/src/v0.7/ConfirmedOwner.sol"; */ contract ContainerPod is ChainlinkClient, ConfirmedOwner { - using Chainlink for Chainlink.Request; - - uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 - string public currentPodStatus; - - event RequestContainerPodFulfilled( - bytes32 indexed requestId, - string deployStatus - ); - - /** - * Constructor FVM link token - * @dev LINK address in FVM network: _link_token_address + using Chainlink for Chainlink.Request; + + uint256 private constant ORACLE_PAYMENT = (1 * LINK_DIVISIBILITY) / 10; // 0.1 * 10**18 + string public currentPodStatus; + string public currentDeleteStatus; + + event RequestContainerPodFulfilled( + bytes32 indexed requestId, + string deployStatus + ); + event RequestDeletePodFulfilled( + bytes32 indexed requestId, + string deleteStatus + ); + + /** + * Constructor FVM link token + * @dev LINK address in FVM network: _link_token_address * @dev Check https://docs.chain.link/docs/link-token-contracts/ for LINK address for the right network */ - constructor(address _link_token_address) ConfirmedOwner(msg.sender) { - setChainlinkToken(_link_token_address); - } - - /** - * Request container cloud api to deploy. + constructor(address _link_token_address) ConfirmedOwner(msg.sender) { + setChainlinkToken(_link_token_address); + } + + /** + * Request container cloud api to deploy. + */ + function requestContainerPod( + address _oracle, + string memory _jobId, + string memory _pod_code, + string memory _request_url, + string memory _userId + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillDeployStatus.selector + ); + req.add("post",_request_url); + req.add("yaml", _pod_code); + req.add("userid", _userId); + address from = msg.sender; + req.add("sender",addressToString(from)); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } + + function fulfillDeployStatus( + bytes32 _requestId, + string calldata _pod_status + ) public recordChainlinkFulfillment(_requestId) { + emit RequestContainerPodFulfilled(_requestId, _pod_status); + currentPodStatus = _pod_status; + } + + /** + * Request msp container cloud api to delete. */ - function requestContainerPod( - address _oracle, - string memory _jobId, - string memory _pod_code, - string memory _request_url - ) public { - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillDeployStatus.selector - ); - req.add("post",_request_url); - req.add("yaml", _pod_code); - address from = msg.sender; - req.add("sender",addressToString(from)); - sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - } - - function fulfillDeployStatus( - bytes32 _requestId, - string calldata _pod_status - ) public recordChainlinkFulfillment(_requestId) { - emit RequestContainerPodFulfilled(_requestId, _pod_status); - currentPodStatus = _pod_status; + function requestDeletePod( + address _oracle, + string memory _jobId, + string memory _request_url + ) public { + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillDeleteStatus.selector + ); + req.add("delete",_request_url); + sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + } + + function fulfillDeleteStatus( + bytes32 _requestId, + string calldata _pod_status + ) public recordChainlinkFulfillment(_requestId) { + emit RequestDeletePodFulfilled(_requestId, _pod_status); + currentDeleteStatus = _pod_status; + } + + function getChainlinkToken() public view returns (address) { + return chainlinkTokenAddress(); + } + + function withdrawLink() public onlyOwner { + LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); + require( + link.transfer(msg.sender, link.balanceOf(address(this))), + "Unable to transfer" + ); + } + + function cancelRequest( + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public onlyOwner { + cancelChainlinkRequest( + _requestId, + _payment, + _callbackFunctionId, + _expiration + ); + } + + function stringToBytes32( + string memory source + ) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; } - function getChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); + assembly { + // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) } + } - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require( - link.transfer(msg.sender, link.balanceOf(address(this))), - "Unable to transfer" - ); - } + function addressToString(address _addr) public pure returns (string memory) { + bytes32 value = bytes32(uint256(_addr)); + bytes memory alphabet = "0123456789abcdef"; + bytes memory str = new bytes(42); - function cancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public onlyOwner { - cancelChainlinkRequest( - _requestId, - _payment, - _callbackFunctionId, - _expiration - ); - } + str[0] = "0"; + str[1] = "x"; - function stringToBytes32( - string memory source - ) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { - // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } + for (uint256 i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; } - function addressToString(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - - str[0] = "0"; - str[1] = "x"; - - for (uint256 i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - - return string(str); - } + return string(str); + } } diff --git a/contract/contracts/oracle/ZtControl.sol b/contract/contracts/oracle/ZtControl.sol index 6a8f37d..bd377a8 100644 --- a/contract/contracts/oracle/ZtControl.sol +++ b/contract/contracts/oracle/ZtControl.sol @@ -9,219 +9,219 @@ import "@chainlink/contracts/src/v0.8/ConfirmedOwner.sol"; */ contract ZtControl is ChainlinkClient, ConfirmedOwner { - using Chainlink for Chainlink.Request; + using Chainlink for Chainlink.Request; - // Result data map: requestId => result - mapping (bytes32 => string) public _result; + // Result data map: requestId => result + mapping (bytes32 => string) public _result; - uint256 private fee; - bytes32 public currentKey; - string public currentData; + uint256 private fee; + bytes32 public currentKey; + string public currentData; - struct Site { - bytes32 jobId; - address oracle; - string host; - } - // site configuration - mapping (string => Site) public _sites; + struct Site { + bytes32 jobId; + address oracle; + string host; + } + // site configuration + mapping (string => Site) public _sites; - /** - * @notice Initialize the link token and target oracle + /** + * @notice Initialize the link token and target oracle * @dev The oracle address must be an Operator contract for multiword response * */ - constructor(uint256 _fee, address _link) ConfirmedOwner(msg.sender) { - setChainlinkToken(_link); - // setChainlinkOracle(_oracle); - fee = _fee; // 0,1 * 10**18 (Varies by network and job) - } - - // Register site configuration - function setSites(string memory _name, string memory _jobId, address _oracle, string memory host) public{ - require(msg.sender == owner()); - require(bytes(_name).length > 0); - require(bytes(_jobId).length > 0); - require(_oracle != address(0)); - require(bytes(host).length > 0); - _sites[_name] = Site(stringToBytes32(_jobId), _oracle, host); - } - - // Disable service tls - function forbidTls( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/forbid_unit")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - // Verify site metadata - modifier verificationSite( - string memory _siteName - ) { - require(_sites[_siteName].oracle != address(0), "This site does not exist"); - _; - } - - // Restore service tls - function recoverTls( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/recover_unit")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - // Revoke service certificate - function revokeCert( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/revoke")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - //Restoration of Services Certificate - function recoverCert( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/recover")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - //Switch communication method - function switchListen( - string memory _siteName, - string memory _requestData, - bytes32 _requestUID - ) public verificationSite(_siteName){ - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/listen")); - request( - "POST", - url, - "W10=", - _requestData, - _siteName, - _requestUID - ); - } - - // Query data - function getResultData( - bytes32 _requestUID - ) public view returns (string memory){ - return _result[_requestUID]; - } - - - /** - * @notice Request variable string from the oracle + constructor(uint256 _fee, address _link) ConfirmedOwner(msg.sender) { + setChainlinkToken(_link); + // setChainlinkOracle(_oracle); + fee = _fee; // 0,1 * 10**18 (Varies by network and job) + } + + // Register site configuration + function setSites(string memory _name, string memory _jobId, address _oracle, string memory host) public{ + require(msg.sender == owner()); + require(bytes(_name).length > 0); + require(bytes(_jobId).length > 0); + require(_oracle != address(0)); + require(bytes(host).length > 0); + _sites[_name] = Site(stringToBytes32(_jobId), _oracle, host); + } + + // Disable service tls + function forbidTls( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/forbid_unit")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + // Verify site metadata + modifier verificationSite( + string memory _siteName + ) { + require(_sites[_siteName].oracle != address(0), "This site does not exist"); + _; + } + + // Restore service tls + function recoverTls( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/recover_unit")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + // Revoke service certificate + function revokeCert( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/revoke")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + //Restoration of Services Certificate + function recoverCert( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/ca/workload/lifecycle/recover")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + //Switch communication method + function switchListen( + string memory _siteName, + string memory _requestData, + bytes32 _requestUID + ) public verificationSite(_siteName){ + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + string memory url = string(abi.encodePacked(_sites[_siteName].host, "/api/v1/govern/listen")); + request( + "POST", + url, + "W10=", + _requestData, + _siteName, + _requestUID + ); + } + + // Query data + function getResultData( + bytes32 _requestUID + ) public view returns (string memory){ + return _result[_requestUID]; + } + + + /** + * @notice Request variable string from the oracle */ - function request( - string memory _method, - string memory _url, - string memory _headers, - string memory _requestData, - string memory _siteName, - bytes32 _requestUID - ) internal verificationSite(_siteName){ - _method = (bytes(_method).length > 0 ? _method : "GET"); - require(bytes(_url).length > 0); - _headers = (bytes(_headers).length > 0 ? _headers : "W10="); - _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); - - Chainlink.Request memory req = buildChainlinkRequest( - _sites[_siteName].jobId, - address(this), - this.fulfill.selector - ); - req.add("url", _url); - req.add("method", _method); - req.add("headers", _headers); - req.add("requestData", _requestData); - req.addBytes("requestUID", abi.encodePacked(_requestUID)); - sendChainlinkRequestTo(_sites[_siteName].oracle, req, fee); - } - - event RequestFulfilled(bytes32 indexed _requestUID, string data); - - /** - * @notice Fulfillment function for variable string + function request( + string memory _method, + string memory _url, + string memory _headers, + string memory _requestData, + string memory _siteName, + bytes32 _requestUID + ) internal verificationSite(_siteName){ + _method = (bytes(_method).length > 0 ? _method : "GET"); + require(bytes(_url).length > 0); + _headers = (bytes(_headers).length > 0 ? _headers : "W10="); + _requestData = (bytes(_requestData).length > 0 ? _requestData : "e30="); + + Chainlink.Request memory req = buildChainlinkRequest( + _sites[_siteName].jobId, + address(this), + this.fulfill.selector + ); + req.add("url", _url); + req.add("method", _method); + req.add("headers", _headers); + req.add("requestData", _requestData); + req.addBytes("requestUID", abi.encodePacked(_requestUID)); + sendChainlinkRequestTo(_sites[_siteName].oracle, req, fee); + } + + event RequestFulfilled(bytes32 indexed _requestUID, string data); + + /** + * @notice Fulfillment function for variable string * @dev This is called by the oracle. recordChainlinkFulfillment must be used. */ - function fulfill( - bytes32 _requestId, - bytes32 _requestUID, - string memory _stringData - ) public recordChainlinkFulfillment(_requestId) { - emit RequestFulfilled(_requestUID, _stringData); - _result[_requestUID] = _stringData; - currentKey = _requestUID; - currentData = _stringData; - } - - /** - * Allow withdraw of Link tokens from the contract - */ - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require( - link.transfer(msg.sender, link.balanceOf(address(this))), - "Unable to transfer" - ); + function fulfill( + bytes32 _requestId, + bytes32 _requestUID, + string memory _stringData + ) public recordChainlinkFulfillment(_requestId) { + emit RequestFulfilled(_requestUID, _stringData); + _result[_requestUID] = _stringData; + currentKey = _requestUID; + currentData = _stringData; + } + + /** + * Allow withdraw of Link tokens from the contract + */ + function withdrawLink() public onlyOwner { + LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); + require( + link.transfer(msg.sender, link.balanceOf(address(this))), + "Unable to transfer" + ); + } + + function stringToBytes32( + string memory source + ) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; } - function stringToBytes32( - string memory source - ) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { - // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } + assembly { + // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) } + } } diff --git a/contract/hardhat.config.js b/contract/hardhat.config.js index bfda0cd..c268352 100644 --- a/contract/hardhat.config.js +++ b/contract/hardhat.config.js @@ -58,7 +58,7 @@ module.exports = { chainId: 11155111 } }, - defaultNetwork: "calibration", + defaultNetwork: "sepolia", gasReporter: { enabled: REPORT_GAS, currency: "USD", diff --git a/contract/tasks/container/createDeploy.js b/contract/tasks/container/createDeploy.js new file mode 100644 index 0000000..03cc943 --- /dev/null +++ b/contract/tasks/container/createDeploy.js @@ -0,0 +1,17 @@ +task("create-deploy", "Call deploy oracle contract to create a deploy") + .addParam("contract", "The deploy oracle contract to call") + .addParam("jobId", "") + .addParam("oracle", "") + .addParam("requestUrl", "") + .addParam("deployYaml", "") + .addParam("userid", "") + .setAction(async (taskArgs) => { + const deployContract = await ethers.getContractAt("ContainerDeploy",taskArgs.contract); + console.log("Create Deploy started"); + const result = await deployContract.requestContainerDeploy(taskArgs.oracle, taskArgs.jobId, taskArgs.deployYaml, + taskArgs.requestUrl, taskArgs.userid); + console.log("Create Deploy success, Transaction hash is ", result.hash); + }) + + +module.exports = {} diff --git a/contract/tasks/container/createPod.js b/contract/tasks/container/createPod.js new file mode 100644 index 0000000..a957a8e --- /dev/null +++ b/contract/tasks/container/createPod.js @@ -0,0 +1,17 @@ +task("create-pod", "Call pod oracle contract to create a pod") + .addParam("contract", "The pod oracle contract to call") + .addParam("jobId", "") + .addParam("oracle", "") + .addParam("requestUrl", "") + .addParam("podYaml", "") + .addParam("userid", "") + .setAction(async (taskArgs) => { + const podContract = await ethers.getContractAt("ContainerPod",taskArgs.contract); + console.log("Create Pod started"); + const result = await podContract.requestContainerPod(taskArgs.oracle, taskArgs.jobId, taskArgs.podYaml, + taskArgs.requestUrl, taskArgs.userid); + console.log("Create Pod success, Transaction hash is ", result.hash); + }) + + +module.exports = {} diff --git a/contract/tasks/container/deletePod.js b/contract/tasks/container/deletePod.js new file mode 100644 index 0000000..edcea73 --- /dev/null +++ b/contract/tasks/container/deletePod.js @@ -0,0 +1,15 @@ +task("delete-pod", "Call pod oracle contract to delete a pod") + .addParam("contract", "The pod oracle contract to call") + .addParam("jobId", "") + .addParam("oracle", "") + .addParam("requestUrl", "") + .setAction(async (taskArgs) => { + const podContract = await ethers.getContractAt("ContainerPod",taskArgs.contract); + console.log("Delete Pod started"); + const result = await podContract.requestDeletePod(taskArgs.oracle, taskArgs.jobId, + taskArgs.requestUrl); + console.log("Delete Pod success, Transaction hash is ", result.hash); + }) + + +module.exports = {} diff --git a/contract/tasks/container/index.js b/contract/tasks/container/index.js new file mode 100644 index 0000000..7c4efff --- /dev/null +++ b/contract/tasks/container/index.js @@ -0,0 +1,3 @@ +exports.createPod = require("./createPod") +exports.deletePod = require("./deletePod") +exports.createDeploy = require("./createDeploy") diff --git a/contract/tasks/index.js b/contract/tasks/index.js index e9c46a9..5976cb3 100644 --- a/contract/tasks/index.js +++ b/contract/tasks/index.js @@ -1,2 +1,5 @@ exports.stcMarket = require("./stc-market"); exports.stcMarketToken = require("./stc-market-token"); +exports.operator = require("./operator"); +exports.ztControl = require("./zt-control"); +exports.container = require("./container"); diff --git a/contract/tasks/operator/get-authorized-senders.js b/contract/tasks/operator/get-authorized-senders.js new file mode 100644 index 0000000..a241830 --- /dev/null +++ b/contract/tasks/operator/get-authorized-senders.js @@ -0,0 +1,18 @@ +const {networkConfig} = require("../../helper-hardhat-config"); +task("get-authorized-senders", "Calls Operator Contract to setAuthorizedSenders") + .addOptionalParam("contract", "The address of the Operator contract that you want to call") + .setAction(async (taskArgs, hre) => { + const networkId = network.config.chainId + + const contractAddress = taskArgs.contract || networkConfig[networkId]["oracle"]; + console.log("Calling Operator contract ", contractAddress, " on network ", network.name) + + const Operator = await ethers.getContractFactory("Operator") + + const operatorContract = await Operator.attach(contractAddress) + + let result = await operatorContract.getAuthorizedSenders() + + console.log("Call getAuthorizedSenders contract, The AuthorizedSenders is", result) + }) +module.exports = {} diff --git a/contract/tasks/operator/index.js b/contract/tasks/operator/index.js index 26c2ec1..a4aadaf 100644 --- a/contract/tasks/operator/index.js +++ b/contract/tasks/operator/index.js @@ -1 +1,2 @@ exports.setAuthorizedSenders = require("./set-authorized-senders.js") +exports.getAuthorizedSenders = require("./get-authorized-senders.js")