mirror of https://github.com/nucypher/nucypher.git
[KMS-ETH]- Merge branch 'master' into upgradeable-contracts
commit
270ab83565
|
@ -233,7 +233,7 @@ contract MinersEscrow is Issuer, Ownable {
|
|||
internal view returns (uint256)
|
||||
{
|
||||
MinerInfo storage info = minerInfo[_owner];
|
||||
return _lockedTokens.divCeil(info.releaseRate).sub(1);
|
||||
return _lockedTokens.divCeil(info.releaseRate).sub(uint(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -447,7 +447,7 @@ contract MinersEscrow is Issuer, Ownable {
|
|||
* @notice Mint tokens for sender for previous periods if he locked his tokens and confirmed activity
|
||||
**/
|
||||
function mint() external onlyTokenOwner {
|
||||
uint256 previousPeriod = getCurrentPeriod().sub(1);
|
||||
uint256 previousPeriod = getCurrentPeriod().sub(uint(1));
|
||||
MinerInfo storage info = minerInfo[msg.sender];
|
||||
uint256 numberPeriodsForMinting = info.numberConfirmedPeriods;
|
||||
require(numberPeriodsForMinting > 0 &&
|
||||
|
|
|
@ -4,6 +4,7 @@ pragma solidity ^0.4.18;
|
|||
import "./zeppelin/token/ERC20/SafeERC20.sol";
|
||||
import "./zeppelin/math/SafeMath.sol";
|
||||
import "./zeppelin/math/Math.sol";
|
||||
import "./lib/AdditionalMath.sol";
|
||||
import "./MinersEscrow.sol";
|
||||
import "./NuCypherKMSToken.sol";
|
||||
import "./proxy/Upgradeable.sol";
|
||||
|
@ -15,38 +16,61 @@ import "./proxy/Upgradeable.sol";
|
|||
contract PolicyManager is Upgradeable {
|
||||
using SafeERC20 for NuCypherKMSToken;
|
||||
using SafeMath for uint256;
|
||||
using AdditionalMath for uint256;
|
||||
using AdditionalMath for int256;
|
||||
|
||||
event PolicyCreated(
|
||||
bytes20 indexed policyId,
|
||||
address indexed client,
|
||||
address indexed node
|
||||
address[] indexed nodes
|
||||
);
|
||||
event PolicyRevoked(
|
||||
bytes20 indexed policyId,
|
||||
address indexed client,
|
||||
uint256 value
|
||||
);
|
||||
event ArrangementRevoked(
|
||||
bytes20 indexed policyId,
|
||||
address indexed client,
|
||||
address indexed node,
|
||||
uint256 value
|
||||
);
|
||||
event PolicyRevoked(bytes20 indexed policyId);
|
||||
event Withdrawn(address indexed node, uint256 value);
|
||||
event Refunded(
|
||||
event RefundForArrangement(
|
||||
bytes20 indexed policyId,
|
||||
address indexed client,
|
||||
address indexed node,
|
||||
uint256 value
|
||||
);
|
||||
event RefundForPolicy(
|
||||
bytes20 indexed policyId,
|
||||
address indexed client,
|
||||
uint256 value
|
||||
);
|
||||
|
||||
// enum PolicyState { Pending, Active }
|
||||
// enum PolicyType { Periods }
|
||||
struct ArrangementInfo {
|
||||
uint256 indexOfDowntimePeriods;
|
||||
uint256 lastRefundedPeriod;
|
||||
bool disabled;
|
||||
}
|
||||
|
||||
struct Policy {
|
||||
address client;
|
||||
address node;
|
||||
// PolicyState state;
|
||||
mapping(address => ArrangementInfo) arrangements;
|
||||
address[] nodes;
|
||||
|
||||
// policy for activity periods
|
||||
uint256 rate;
|
||||
uint256 startPeriod;
|
||||
uint256 lastPeriod;
|
||||
uint256 indexOfDowntimePeriods;
|
||||
bool disabled;
|
||||
}
|
||||
|
||||
struct NodeInfo {
|
||||
uint256 reward;
|
||||
mapping (uint256 => uint256) rewardByPeriod;
|
||||
uint256 lastRewardByPeriod;
|
||||
uint256 lastMinedPeriod;
|
||||
mapping (uint256 => int256) rewardChanges;
|
||||
}
|
||||
|
||||
bytes20 constant RESERVED_POLICY_ID = bytes20(0);
|
||||
|
@ -73,53 +97,51 @@ contract PolicyManager is Upgradeable {
|
|||
* @notice Create policy by client
|
||||
* @dev Generate policy id before creation
|
||||
* @param _policyId Policy id
|
||||
* @param _node Node that will handle policy
|
||||
* @param _numberOfPeriods Duration of the policy in periods
|
||||
* @param _nodes Nodes that will handle policy
|
||||
**/
|
||||
function createPolicy(
|
||||
bytes20 _policyId,
|
||||
address _node,
|
||||
uint256 _numberOfPeriods
|
||||
uint256 _numberOfPeriods,
|
||||
address[] _nodes
|
||||
)
|
||||
public payable
|
||||
{
|
||||
require(
|
||||
policies[_policyId].rate == 0 &&
|
||||
_node != RESERVED_NODE &&
|
||||
_numberOfPeriods != 0 &&
|
||||
escrow.getLockedTokens(_node) != 0 &&
|
||||
msg.value > 0 &&
|
||||
msg.value % _numberOfPeriods == 0 &&
|
||||
msg.value % _numberOfPeriods % _nodes.length == 0 &&
|
||||
_policyId != RESERVED_POLICY_ID
|
||||
);
|
||||
Policy storage policy = policies[_policyId];
|
||||
policy.client = msg.sender;
|
||||
policy.node = _node;
|
||||
// policy.state = PolicyState.Pending;
|
||||
policy.nodes = _nodes;
|
||||
uint256 currentPeriod = escrow.getCurrentPeriod();
|
||||
policy.startPeriod = currentPeriod.add(1);
|
||||
policy.startPeriod = currentPeriod.add(uint(1));
|
||||
policy.lastPeriod = currentPeriod.add(_numberOfPeriods);
|
||||
uint256 feeByPeriod = msg.value.div(_numberOfPeriods);
|
||||
uint256 feeByPeriod = msg.value.div(_numberOfPeriods).div(_nodes.length);
|
||||
policy.rate = feeByPeriod;
|
||||
uint256 endPeriod = policy.lastPeriod.add(uint(1));
|
||||
|
||||
NodeInfo storage node = nodes[_node];
|
||||
for (uint256 i = policy.startPeriod; i <= policy.lastPeriod; i++) {
|
||||
node.rewardByPeriod[i] = node.rewardByPeriod[i].add(feeByPeriod);
|
||||
policy.nodes = _nodes;
|
||||
for (uint256 i = 0; i < _nodes.length; i++) {
|
||||
require(escrow.getLockedTokens(_nodes[i]) != 0 &&
|
||||
_nodes[i] != RESERVED_NODE);
|
||||
NodeInfo storage node = nodes[_nodes[i]];
|
||||
node.rewardChanges[policy.startPeriod] = node.rewardChanges[policy.startPeriod]
|
||||
.add(feeByPeriod);
|
||||
node.rewardChanges[endPeriod] = node.rewardChanges[endPeriod].sub(feeByPeriod);
|
||||
// TODO node should pay for this
|
||||
if (node.lastMinedPeriod == 0) {
|
||||
node.lastMinedPeriod = currentPeriod;
|
||||
}
|
||||
ArrangementInfo storage arrangement = policy.arrangements[_nodes[i]];
|
||||
arrangement.indexOfDowntimePeriods = escrow.getDowntimePeriodsLength(_nodes[i]);
|
||||
}
|
||||
policy.indexOfDowntimePeriods = escrow.getDowntimePeriodsLength(_node);
|
||||
PolicyCreated(_policyId, msg.sender, _node);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @notice Confirm policy by node
|
||||
// * @param _policyId Policy id
|
||||
// **/
|
||||
// function confirmPolicy(bytes20 _policyId) public {
|
||||
// Policy policy = policies[_policyId];
|
||||
// require(policy.state == PolicyState.Pending &&
|
||||
// policy.node == msg.sender);
|
||||
// policy.state = PolicyState.Active;
|
||||
// }
|
||||
PolicyCreated(_policyId, msg.sender, _nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Update node reward
|
||||
|
@ -129,8 +151,15 @@ contract PolicyManager is Upgradeable {
|
|||
function updateReward(address _node, uint256 _period) external {
|
||||
require(msg.sender == address(escrow));
|
||||
NodeInfo storage node = nodes[_node];
|
||||
node.reward = node.reward.add(node.rewardByPeriod[_period]);
|
||||
delete node.rewardByPeriod[_period];
|
||||
if (node.lastMinedPeriod == 0) {
|
||||
return;
|
||||
}
|
||||
for (uint256 i = node.lastMinedPeriod + 1; i <= _period; i++) {
|
||||
node.lastRewardByPeriod = node.lastRewardByPeriod.add(node.rewardChanges[i]);
|
||||
// delete node.rewardChanges[i];
|
||||
}
|
||||
node.lastMinedPeriod = _period;
|
||||
node.reward = node.reward.add(node.lastRewardByPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,19 +180,63 @@ contract PolicyManager is Upgradeable {
|
|||
**/
|
||||
function revokePolicy(bytes20 _policyId) public {
|
||||
Policy storage policy = policies[_policyId];
|
||||
require(policy.client == msg.sender);
|
||||
uint256 refund = calculateRefund(_policyId);
|
||||
NodeInfo storage node = nodes[policy.node];
|
||||
for (uint256 i = policy.startPeriod; i <= policy.lastPeriod; i++) {
|
||||
node.rewardByPeriod[i] = node.rewardByPeriod[i].sub(policy.rate);
|
||||
refund = refund.add(policy.rate);
|
||||
require(policy.client == msg.sender && !policy.disabled);
|
||||
uint256 refundValue = 0;
|
||||
uint256 endPeriod = policy.lastPeriod.add(uint(1));
|
||||
for (uint256 i = 0; i < policy.nodes.length; i++) {
|
||||
address node = policy.nodes[i];
|
||||
if (policy.arrangements[node].disabled) {
|
||||
continue;
|
||||
}
|
||||
uint256 nodeRefundValue = revokeArrangement(policy, node, endPeriod);
|
||||
refundValue = refundValue.add(nodeRefundValue);
|
||||
ArrangementRevoked(_policyId, msg.sender, node, nodeRefundValue);
|
||||
}
|
||||
delete policies[_policyId];
|
||||
if (refund > 0) {
|
||||
msg.sender.transfer(refund);
|
||||
Refunded(_policyId, msg.sender, refund);
|
||||
policy.disabled = true;
|
||||
if (refundValue > 0) {
|
||||
msg.sender.transfer(refundValue);
|
||||
}
|
||||
PolicyRevoked(_policyId);
|
||||
PolicyRevoked(_policyId, msg.sender, refundValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Revoke arrangement by client
|
||||
* @param _policyId Policy id
|
||||
* @param _node Node that will be excluded
|
||||
**/
|
||||
function revokeArrangement(bytes20 _policyId, address _node)
|
||||
public returns (uint256 refundValue)
|
||||
{
|
||||
Policy storage policy = policies[_policyId];
|
||||
require(policy.client == msg.sender &&
|
||||
!policy.disabled &&
|
||||
!policy.arrangements[_node].disabled);
|
||||
uint256 endPeriod = policy.lastPeriod.add(uint(1));
|
||||
refundValue = revokeArrangement(policy, _node, endPeriod);
|
||||
if (refundValue > 0) {
|
||||
msg.sender.transfer(refundValue);
|
||||
}
|
||||
ArrangementRevoked(_policyId, msg.sender, _node, refundValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Revoke arrangement by client
|
||||
* @param _policy Policy
|
||||
* @param _node Node that will be excluded
|
||||
* @param _endPeriod Pre-calculated end of period value
|
||||
**/
|
||||
function revokeArrangement(Policy storage _policy, address _node, uint256 _endPeriod)
|
||||
internal returns (uint256 refundValue)
|
||||
{
|
||||
refundValue = calculateRefund(_policy, _node);
|
||||
NodeInfo storage node = nodes[_node];
|
||||
ArrangementInfo storage arrangement = _policy.arrangements[_node];
|
||||
node.rewardChanges[arrangement.lastRefundedPeriod] =
|
||||
node.rewardChanges[arrangement.lastRefundedPeriod].sub(_policy.rate);
|
||||
node.rewardChanges[_endPeriod] = node.rewardChanges[_endPeriod].add(_policy.rate);
|
||||
refundValue = refundValue.add(
|
||||
_endPeriod.sub(arrangement.lastRefundedPeriod).mul(_policy.rate));
|
||||
_policy.arrangements[_node].disabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,79 +245,139 @@ contract PolicyManager is Upgradeable {
|
|||
**/
|
||||
function refund(bytes20 _policyId) public {
|
||||
Policy storage policy = policies[_policyId];
|
||||
// require(policy.state == PolicyState.Active &&
|
||||
// msg.sender == policy.client);
|
||||
require(msg.sender == policy.client);
|
||||
|
||||
uint256 refundValue = calculateRefund(_policyId);
|
||||
address client = policy.client;
|
||||
if (policy.startPeriod > policy.lastPeriod) {
|
||||
delete policies[_policyId];
|
||||
require(msg.sender == policy.client && !policy.disabled);
|
||||
uint256 refundValue = 0;
|
||||
uint256 numberOfActive = policy.nodes.length;
|
||||
for (uint256 i = 0; i < policy.nodes.length; i++) {
|
||||
address node = policy.nodes[i];
|
||||
if (policy.arrangements[node].disabled) {
|
||||
numberOfActive--;
|
||||
continue;
|
||||
}
|
||||
uint256 nodeRefundValue = calculateRefund(policy, node);
|
||||
if (policy.arrangements[node].lastRefundedPeriod > policy.lastPeriod) {
|
||||
policy.arrangements[node].disabled = true;
|
||||
numberOfActive--;
|
||||
}
|
||||
refundValue = refundValue.add(nodeRefundValue);
|
||||
RefundForArrangement(_policyId, msg.sender, node, nodeRefundValue);
|
||||
}
|
||||
if (refundValue > 0) {
|
||||
client.transfer(refundValue);
|
||||
Refunded(_policyId, client, refundValue);
|
||||
msg.sender.transfer(refundValue);
|
||||
}
|
||||
if (numberOfActive == 0) {
|
||||
policy.disabled = true;
|
||||
}
|
||||
RefundForPolicy(_policyId, msg.sender, refundValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Refund part of one node's fee by client
|
||||
* @param _policyId Policy id
|
||||
* @param _node Node address
|
||||
**/
|
||||
function refund(bytes20 _policyId, address _node)
|
||||
public returns (uint256 refundValue)
|
||||
{
|
||||
Policy storage policy = policies[_policyId];
|
||||
require(msg.sender == policy.client &&
|
||||
!policy.disabled &&
|
||||
!policy.arrangements[_node].disabled);
|
||||
refundValue = calculateRefund(policy, _node);
|
||||
if (policy.arrangements[_node].lastRefundedPeriod > policy.lastPeriod) {
|
||||
policy.arrangements[_node].disabled = true;
|
||||
}
|
||||
if (refundValue > 0) {
|
||||
msg.sender.transfer(refundValue);
|
||||
}
|
||||
RefundForArrangement(_policyId, msg.sender, _node, refundValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of refund
|
||||
* @param _policyId Policy id
|
||||
* @param _policy Policy
|
||||
* @param _node Node for calculation
|
||||
**/
|
||||
//TODO extract checkRefund method
|
||||
function calculateRefund(bytes20 _policyId) internal returns (uint256) {
|
||||
Policy storage policy = policies[_policyId];
|
||||
uint256 currentPeriod = escrow.getCurrentPeriod();
|
||||
uint256 maxPeriod = Math.min256(currentPeriod, policy.lastPeriod);
|
||||
uint256 minPeriod = policy.startPeriod;
|
||||
function calculateRefund(Policy storage _policy, address _node) internal returns (uint256) {
|
||||
ArrangementInfo storage arrangement = _policy.arrangements[_node];
|
||||
uint256 maxPeriod = Math.min256(escrow.getCurrentPeriod(), _policy.lastPeriod);
|
||||
uint256 minPeriod = Math.max256(_policy.startPeriod, arrangement.lastRefundedPeriod);
|
||||
uint256 downtimePeriods = 0;
|
||||
uint256 length = escrow.getDowntimePeriodsLength(policy.node);
|
||||
for (uint256 i = policy.indexOfDowntimePeriods; i < length; i++) {
|
||||
uint256 length = escrow.getDowntimePeriodsLength(_node);
|
||||
for (uint256 i = arrangement.indexOfDowntimePeriods; i < length; i++) {
|
||||
uint256 startPeriod;
|
||||
uint256 endPeriod;
|
||||
(startPeriod, endPeriod) = escrow.getDowntimePeriods(policy.node, i);
|
||||
(startPeriod, endPeriod) = escrow.getDowntimePeriods(_node, i);
|
||||
if (startPeriod > maxPeriod) {
|
||||
break;
|
||||
} else if (endPeriod < minPeriod) {
|
||||
continue;
|
||||
}
|
||||
uint256 max = Math.min256(maxPeriod, endPeriod);
|
||||
uint256 min = Math.max256(minPeriod, startPeriod);
|
||||
downtimePeriods = downtimePeriods.add(max.sub(min).add(1));
|
||||
downtimePeriods = downtimePeriods.add(
|
||||
Math.min256(maxPeriod, endPeriod)
|
||||
.sub(Math.max256(minPeriod, startPeriod))
|
||||
.add(uint(1)));
|
||||
if (maxPeriod <= endPeriod) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
policy.indexOfDowntimePeriods = i;
|
||||
uint256 lastActivePeriod = escrow.getLastActivePeriod(policy.node);
|
||||
arrangement.indexOfDowntimePeriods = i;
|
||||
uint256 lastActivePeriod = escrow.getLastActivePeriod(_node);
|
||||
if (i == length && lastActivePeriod < maxPeriod) {
|
||||
min = Math.max256(minPeriod.sub(1), lastActivePeriod);
|
||||
downtimePeriods = downtimePeriods.add(maxPeriod.sub(min));
|
||||
downtimePeriods = downtimePeriods.add(
|
||||
maxPeriod.sub(Math.max256(
|
||||
minPeriod.sub(uint(1)), lastActivePeriod)));
|
||||
}
|
||||
policy.startPeriod = maxPeriod.add(1);
|
||||
arrangement.lastRefundedPeriod = maxPeriod.add(uint(1));
|
||||
|
||||
return policy.rate.mul(downtimePeriods);
|
||||
return _policy.rate.mul(downtimePeriods);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get number of nodes in policy
|
||||
* @param _policyId Policy id
|
||||
**/
|
||||
function getPolicyNodesLength(bytes20 _policyId)
|
||||
public view returns (uint256)
|
||||
{
|
||||
return policies[_policyId].nodes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get node from policy
|
||||
* @param _policyId Policy id
|
||||
* @param _index Index of node
|
||||
**/
|
||||
function getPolicyNode(bytes20 _policyId, uint256 _index)
|
||||
public view returns (address)
|
||||
{
|
||||
return policies[_policyId].nodes[_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Used only in verifyState(address) method
|
||||
**/
|
||||
function getPolicyField(bytes20 _policyId, uint8 _field)
|
||||
function getPolicyField(bytes20 _policyId, uint8 _field, address _node)
|
||||
public view returns (bytes32)
|
||||
{
|
||||
Policy storage policy = policies[_policyId];
|
||||
if (_field == 0) {
|
||||
return bytes32(policy.client);
|
||||
} else if (_field == 1) {
|
||||
return bytes32(policy.node);
|
||||
} else if (_field == 2) {
|
||||
return bytes32(policy.rate);
|
||||
} else if (_field == 3) {
|
||||
} else if (_field == 2) {
|
||||
return bytes32(policy.startPeriod);
|
||||
} else if (_field == 4) {
|
||||
} else if (_field == 3) {
|
||||
return bytes32(policy.lastPeriod);
|
||||
} else if (_field == 4) {
|
||||
return policy.disabled ? bytes32(1) : bytes32(0);
|
||||
} else if (_field == 5) {
|
||||
return bytes32(policy.indexOfDowntimePeriods);
|
||||
return bytes32(policy.arrangements[_node].indexOfDowntimePeriods);
|
||||
} else if (_field == 6) {
|
||||
return bytes32(policy.arrangements[_node].lastRefundedPeriod);
|
||||
} else if (_field == 7) {
|
||||
return policy.arrangements[_node].disabled ? bytes32(1) : bytes32(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,38 +385,55 @@ contract PolicyManager is Upgradeable {
|
|||
* @dev Used only in verifyState(address) method
|
||||
**/
|
||||
function getNodeInfoField(address _node, uint8 _field, uint256 _period)
|
||||
public view returns (uint256)
|
||||
public view returns (bytes32)
|
||||
{
|
||||
NodeInfo storage nodeInfo = nodes[_node];
|
||||
if (_field == 0) {
|
||||
return nodeInfo.reward;
|
||||
return bytes32(nodeInfo.reward);
|
||||
} else if (_field == 1) {
|
||||
return nodeInfo.rewardByPeriod[_period];
|
||||
return bytes32(nodeInfo.lastRewardByPeriod);
|
||||
} else if (_field == 2) {
|
||||
return bytes32(nodeInfo.lastMinedPeriod);
|
||||
} else if (_field == 3) {
|
||||
return bytes32(nodeInfo.rewardChanges[_period]);
|
||||
}
|
||||
}
|
||||
|
||||
function verifyState(address _testTarget) public onlyOwner {
|
||||
require(address(delegateGet(_testTarget, "escrow()")) == address(escrow));
|
||||
Policy storage policy = policies[RESERVED_POLICY_ID];
|
||||
require(address(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 0)) == policy.client);
|
||||
require(address(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 1)) == policy.node);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 2)) == policy.rate);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 3)) == policy.startPeriod);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 4)) == policy.lastPeriod);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8)",
|
||||
RESERVED_POLICY_ID, 5)) == policy.indexOfDowntimePeriods);
|
||||
require(address(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 0, 0x0)) == policy.client);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 1, 0x0)) == policy.rate);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 2, 0x0)) == policy.startPeriod);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 3, 0x0)) == policy.lastPeriod);
|
||||
require((delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 4, 0x0) == bytes32(1)) == policy.disabled);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 5, bytes32(RESERVED_NODE))) ==
|
||||
policy.arrangements[RESERVED_NODE].indexOfDowntimePeriods);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 6, bytes32(RESERVED_NODE))) ==
|
||||
policy.arrangements[RESERVED_NODE].lastRefundedPeriod);
|
||||
require((delegateGet(_testTarget, "getPolicyField(bytes20,uint8,address)",
|
||||
RESERVED_POLICY_ID, 7, bytes32(RESERVED_NODE)) == bytes32(1)) ==
|
||||
policy.arrangements[RESERVED_NODE].disabled);
|
||||
require(uint256(delegateGet(_testTarget, "getPolicyNodesLength(bytes20)",
|
||||
RESERVED_POLICY_ID)) == policy.nodes.length);
|
||||
require(address(delegateGet(_testTarget, "getPolicyNode(bytes20,uint256)",
|
||||
RESERVED_POLICY_ID, 0)) == policy.nodes[0]);
|
||||
NodeInfo storage nodeInfo = nodes[RESERVED_NODE];
|
||||
require(uint256(delegateGet(_testTarget, "getNodeInfoField(address,uint8,uint256)",
|
||||
bytes32(RESERVED_NODE), 0, 0)) == nodeInfo.reward);
|
||||
require(uint256(delegateGet(_testTarget, "getNodeInfoField(address,uint8,uint256)",
|
||||
bytes32(RESERVED_NODE), 1, 22)) == nodeInfo.rewardByPeriod[22]);
|
||||
bytes32(RESERVED_NODE), 1, 0)) == nodeInfo.lastRewardByPeriod);
|
||||
require(uint256(delegateGet(_testTarget, "getNodeInfoField(address,uint8,uint256)",
|
||||
bytes32(RESERVED_NODE), 1, 44)) == nodeInfo.rewardByPeriod[44]);
|
||||
bytes32(RESERVED_NODE), 2, 0)) == nodeInfo.lastMinedPeriod);
|
||||
require(int256(delegateGet(_testTarget, "getNodeInfoField(address,uint8,uint256)",
|
||||
bytes32(RESERVED_NODE), 3, 11)) == nodeInfo.rewardChanges[11]);
|
||||
}
|
||||
|
||||
function finishUpgrade(address _target) public onlyOwner {
|
||||
|
@ -292,15 +442,18 @@ contract PolicyManager is Upgradeable {
|
|||
// Create fake Policy and NodeInfo to use them in verifyState(address)
|
||||
Policy storage policy = policies[RESERVED_POLICY_ID];
|
||||
policy.client = owner;
|
||||
policy.node = owner;
|
||||
policy.startPeriod = 1;
|
||||
policy.lastPeriod = 2;
|
||||
policy.rate = 3;
|
||||
policy.indexOfDowntimePeriods = 4;
|
||||
policy.disabled = true;
|
||||
policy.nodes.push(RESERVED_NODE);
|
||||
policy.arrangements[RESERVED_NODE].indexOfDowntimePeriods = 11;
|
||||
policy.arrangements[RESERVED_NODE].lastRefundedPeriod = 22;
|
||||
policy.arrangements[RESERVED_NODE].disabled = true;
|
||||
NodeInfo storage nodeInfo = nodes[RESERVED_NODE];
|
||||
nodeInfo.reward = 100;
|
||||
nodeInfo.rewardByPeriod[22] = 33;
|
||||
nodeInfo.rewardByPeriod[44] = 55;
|
||||
nodeInfo.lastRewardByPeriod = 33;
|
||||
nodeInfo.lastMinedPeriod = 44;
|
||||
nodeInfo.rewardChanges[11] = 55;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -17,4 +17,44 @@ library AdditionalMath {
|
|||
return (a.add(b) - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds unsigned value to signed value, throws on overflow.
|
||||
*/
|
||||
function add(int256 a, uint256 b) internal pure returns (int256) {
|
||||
int256 c = a + int256(b);
|
||||
assert(c >= a);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two numbers, throws on overflow.
|
||||
*/
|
||||
function sub(int256 a, uint256 b) internal pure returns (int256) {
|
||||
int256 c = a - int256(b);
|
||||
assert(c <= a);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds signed value to unsigned value, throws on overflow.
|
||||
*/
|
||||
function add(uint256 a, int256 b) internal pure returns (uint256) {
|
||||
if (b >= 0) {
|
||||
return a.add(uint256(b));
|
||||
} else {
|
||||
return a.sub(uint256(-b));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts signed value from unsigned value, throws on overflow.
|
||||
*/
|
||||
function sub(uint256 a, int256 b) internal pure returns (uint256) {
|
||||
if (b >= 0) {
|
||||
return a.sub(uint256(b));
|
||||
} else {
|
||||
return a.add(uint256(-b));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@ A simple Python script to deploy contracts and then estimate gas for different m
|
|||
from nkms_eth.blockchain import TesterBlockchain
|
||||
from nkms_eth.escrow import Escrow
|
||||
from nkms_eth.token import NuCypherKMSToken
|
||||
import os
|
||||
|
||||
|
||||
def main():
|
||||
testerchain = TesterBlockchain()
|
||||
chain, web3 = testerchain._chain, testerchain._chain.web3
|
||||
creator, ursula1, ursula2, ursula3, *everyone_else = web3.eth.accounts
|
||||
creator, ursula1, ursula2, ursula3, alice1, *everyone_else = web3.eth.accounts
|
||||
|
||||
print("Web3 providers are", web3.providers)
|
||||
|
||||
|
@ -37,7 +38,7 @@ def main():
|
|||
# Pre deposit tokens
|
||||
tx = token.transact({'from': creator}).approve(escrow.contract.address, 10 ** 7)
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Pre-deposit tokens fro 5 owners = " +
|
||||
print("Pre-deposit tokens for 5 owners = " +
|
||||
str(escrow.contract.estimateGas({'from': creator}).preDeposit(
|
||||
web3.eth.accounts[4:9], [10 ** 6] * 5, [1] * 5)))
|
||||
|
||||
|
@ -179,6 +180,109 @@ def main():
|
|||
tx = escrow.transact({'from': ursula3}).mint()
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create policy
|
||||
policy_id_1 = os.urandom(20)
|
||||
policy_id_2 = os.urandom(20)
|
||||
number_of_periods = 10
|
||||
print("First creating policy (1 node, 10 periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula1])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000})\
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula1])
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Second creating policy (1 node, 10 periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula1])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000}) \
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula1])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Revoke policy
|
||||
print("Revoking policy = " +
|
||||
str(policy_manager.estimateGas({'from': alice1}).revokePolicy(policy_id_1)))
|
||||
tx = policy_manager.transact({'from': alice1}).revokePolicy(policy_id_1)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = policy_manager.transact({'from': alice1}).revokePolicy(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create policy with more periods
|
||||
policy_id_1 = os.urandom(20)
|
||||
policy_id_2 = os.urandom(20)
|
||||
policy_id_3 = os.urandom(20)
|
||||
number_of_periods = 100
|
||||
print("First creating policy (1 node, " + str(number_of_periods) + " periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula2])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000})\
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula2])
|
||||
chain.wait.for_receipt(tx)
|
||||
testerchain.wait_time(1)
|
||||
print("Second creating policy (1 node, " + str(number_of_periods) + " periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula2])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000}) \
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula2])
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Third creating policy (1 node, " + str(number_of_periods) + " periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_3, number_of_periods, [ursula1])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000}) \
|
||||
.createPolicy(policy_id_3, number_of_periods, [ursula1])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Mine and revoke policy
|
||||
testerchain.wait_time(10)
|
||||
tx = escrow.transact({'from': ursula2}).confirmActivity()
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact({'from': ursula1}).confirmActivity()
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
testerchain.wait_time(1)
|
||||
print("First mining after downtime = " + str(escrow.contract.estimateGas({'from': ursula1}).mint()))
|
||||
tx = escrow.transact({'from': ursula1}).mint()
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Second mining after downtime = " + str(escrow.contract.estimateGas({'from': ursula2}).mint()))
|
||||
tx = escrow.transact({'from': ursula2}).mint()
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
testerchain.wait_time(10)
|
||||
print("First revoking policy after downtime = " +
|
||||
str(policy_manager.estimateGas({'from': alice1}).revokePolicy(policy_id_1)))
|
||||
tx = policy_manager.transact({'from': alice1}).revokePolicy(policy_id_1)
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Second revoking policy after downtime = " +
|
||||
str(policy_manager.estimateGas({'from': alice1}).revokePolicy(policy_id_2)))
|
||||
tx = policy_manager.transact({'from': alice1}).revokePolicy(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Second revoking policy after downtime = " +
|
||||
str(policy_manager.estimateGas({'from': alice1}).revokePolicy(policy_id_3)))
|
||||
tx = policy_manager.transact({'from': alice1}).revokePolicy(policy_id_3)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create policy with multiple nodes
|
||||
policy_id_1 = os.urandom(20)
|
||||
policy_id_2 = os.urandom(20)
|
||||
policy_id_3 = os.urandom(20)
|
||||
number_of_periods = 100
|
||||
print("First creating policy (3 nodes, 100 periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 30000})
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula1, ursula2, ursula3])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 30000}) \
|
||||
.createPolicy(policy_id_1, number_of_periods, [ursula1, ursula2, ursula3])
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Second creating policy (3 nodes, 100 periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 10000})
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula1, ursula2, ursula3])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 10000}) \
|
||||
.createPolicy(policy_id_2, number_of_periods, [ursula1, ursula2, ursula3])
|
||||
chain.wait.for_receipt(tx)
|
||||
print("Third creating policy (2 nodes, 100 periods) = " +
|
||||
str(policy_manager.estimateGas({'from': alice1, 'value': 20000})
|
||||
.createPolicy(policy_id_3, number_of_periods, [ursula1, ursula2])))
|
||||
tx = policy_manager.transact({'from': alice1, 'value': 20000}) \
|
||||
.createPolicy(policy_id_3, number_of_periods, [ursula1, ursula2])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
print("All done!")
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pragma solidity ^0.4.8;
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
|
||||
import "contracts/PolicyManager.sol";
|
||||
|
@ -16,16 +16,18 @@ contract MinersEscrowForPolicyMock {
|
|||
|
||||
PolicyManager public policyManager;
|
||||
uint256 public secondsPerPeriod;
|
||||
address public node;
|
||||
mapping(address => bool) public nodes;
|
||||
uint256 public lastActivePeriod;
|
||||
Downtime[] public downtime;
|
||||
|
||||
/**
|
||||
* @param _node Address of node that allow to use policy manager
|
||||
* @param _nodes Addresses of nodes that allow to use policy manager
|
||||
* @param _minutesPerPeriod Size of period in minutes
|
||||
**/
|
||||
function MinersEscrowForPolicyMock(address _node, uint256 _minutesPerPeriod) public {
|
||||
node = _node;
|
||||
function MinersEscrowForPolicyMock(address[] _nodes, uint256 _minutesPerPeriod) public {
|
||||
for (uint256 i = 0; i < _nodes.length; i++) {
|
||||
nodes[_nodes[i]] = true;
|
||||
}
|
||||
secondsPerPeriod = _minutesPerPeriod * 1 minutes;
|
||||
}
|
||||
|
||||
|
@ -35,7 +37,7 @@ contract MinersEscrowForPolicyMock {
|
|||
function getLockedTokens(address _owner)
|
||||
public view returns (uint256)
|
||||
{
|
||||
if (_owner == node) {
|
||||
if (nodes[_owner]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -67,7 +69,7 @@ contract MinersEscrowForPolicyMock {
|
|||
* @param _period Period for minting
|
||||
**/
|
||||
function mint(uint256 _period) external {
|
||||
policyManager.updateReward(node, _period);
|
||||
policyManager.updateReward(msg.sender, _period);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,10 +6,13 @@ import os
|
|||
@pytest.fixture()
|
||||
def escrow(web3, chain):
|
||||
creator = web3.eth.accounts[0]
|
||||
node = web3.eth.accounts[1]
|
||||
node1 = web3.eth.accounts[3]
|
||||
node2 = web3.eth.accounts[4]
|
||||
node3 = web3.eth.accounts[5]
|
||||
# Creator deploys the escrow
|
||||
escrow, _ = chain.provider.get_or_deploy_contract(
|
||||
'MinersEscrowForPolicyMock', deploy_args=[node, MINUTES_IN_PERIOD],
|
||||
'MinersEscrowForPolicyMock',
|
||||
deploy_args=[[node1, node2, node3], MINUTES_IN_PERIOD],
|
||||
deploy_transaction={'from': creator})
|
||||
return escrow
|
||||
|
||||
|
@ -17,7 +20,7 @@ def escrow(web3, chain):
|
|||
@pytest.fixture()
|
||||
def policy_manager(web3, chain, escrow):
|
||||
creator = web3.eth.accounts[0]
|
||||
client = web3.eth.accounts[2]
|
||||
client = web3.eth.accounts[1]
|
||||
|
||||
# Creator deploys the policy manager
|
||||
policy_manager, _ = chain.provider.get_or_deploy_contract(
|
||||
|
@ -44,6 +47,7 @@ def wait_time(chain, wait_periods):
|
|||
MINUTES_IN_PERIOD = 10
|
||||
policy_id = os.urandom(20)
|
||||
policy_id_2 = os.urandom(20)
|
||||
policy_id_3 = os.urandom(20)
|
||||
rate = 20
|
||||
number_of_periods = 10
|
||||
value = rate * number_of_periods
|
||||
|
@ -51,35 +55,43 @@ value = rate * number_of_periods
|
|||
|
||||
def test_create_revoke(web3, chain, escrow, policy_manager):
|
||||
creator = web3.eth.accounts[0]
|
||||
node = web3.eth.accounts[1]
|
||||
client = web3.eth.accounts[2]
|
||||
bad_node = web3.eth.accounts[3]
|
||||
client = web3.eth.accounts[1]
|
||||
bad_node = web3.eth.accounts[2]
|
||||
node1 = web3.eth.accounts[3]
|
||||
node2 = web3.eth.accounts[4]
|
||||
node3 = web3.eth.accounts[5]
|
||||
client_balance = web3.eth.getBalance(client)
|
||||
|
||||
# Try create policy for bad node
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client, 'value': value})\
|
||||
.createPolicy(policy_id, bad_node, 1)
|
||||
.createPolicy(policy_id, 1, [bad_node])
|
||||
chain.wait.for_receipt(tx)
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client, 'value': value})\
|
||||
.createPolicy(policy_id, 1, [node1, bad_node])
|
||||
chain.wait.for_receipt(tx)
|
||||
# Try create policy with no ETH
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client})\
|
||||
.createPolicy(policy_id, node, 1)
|
||||
.createPolicy(policy_id, 1, [node1])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create policy
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = policy_manager.transact({'from': client, 'value': value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
.createPolicy(policy_id, number_of_periods, [node1])
|
||||
chain.wait.for_receipt(tx)
|
||||
policy = policy_manager.call().policies(policy_id)
|
||||
assert 200 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 200 == web3.eth.getBalance(client)
|
||||
assert client == policy[0]
|
||||
assert node == policy[1]
|
||||
assert rate == policy[2]
|
||||
assert period + 1 == policy[3]
|
||||
assert period + 10 == policy[4]
|
||||
assert rate == policy[1]
|
||||
assert period + 1 == policy[2]
|
||||
assert period + 10 == policy[3]
|
||||
assert not policy[4]
|
||||
assert 1 == policy_manager.call().getPolicyNodesLength(policy_id)
|
||||
assert node1 == policy_manager.call().getPolicyNode(policy_id, 0)
|
||||
|
||||
events = policy_manager.pastEvents('PolicyCreated').get()
|
||||
assert 1 == len(events)
|
||||
|
@ -87,12 +99,12 @@ def test_create_revoke(web3, chain, escrow, policy_manager):
|
|||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node.lower() == event_args['node'].lower()
|
||||
# assert node.lower() == event_args['nodes'][0].lower()
|
||||
|
||||
# Try to create policy again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client, 'value': value}) \
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
.createPolicy(policy_id, number_of_periods, [node1])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Only client can revoke policy
|
||||
|
@ -102,27 +114,46 @@ def test_create_revoke(web3, chain, escrow, policy_manager):
|
|||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).revokePolicy(policy_id)
|
||||
chain.wait.for_receipt(tx)
|
||||
policy = policy_manager.call().policies(policy_id)
|
||||
assert '0x' + '0' * 40 == policy[0]
|
||||
assert policy[4]
|
||||
|
||||
events = policy_manager.pastEvents('PolicyRevoked').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert value == event_args['value']
|
||||
events = policy_manager.pastEvents('ArrangementRevoked').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert value == event_args['value']
|
||||
|
||||
# Can't revoke again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).revokePolicy(policy_id)
|
||||
chain.wait.for_receipt(tx)
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).revokeArrangement(policy_id, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create another policy
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = policy_manager.transact({'from': client, 'value': value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id_2, node, number_of_periods)
|
||||
tx = policy_manager.transact({'from': client, 'value': 3 * value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id_2, number_of_periods, [node1, node2, node3])
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 3 * value == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 3 * value == web3.eth.getBalance(client)
|
||||
policy = policy_manager.call().policies(policy_id_2)
|
||||
assert 200 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 200 == web3.eth.getBalance(client)
|
||||
assert client == policy[0]
|
||||
assert node == policy[1]
|
||||
assert rate == policy[2]
|
||||
assert period + 1 == policy[3]
|
||||
assert period + 10 == policy[4]
|
||||
assert rate == policy[1]
|
||||
assert period + 1 == policy[2]
|
||||
assert period + 10 == policy[3]
|
||||
assert not policy[4]
|
||||
# assert node.lower() == event_args['node'].lower()
|
||||
|
||||
events = policy_manager.pastEvents('PolicyCreated').get()
|
||||
assert 2 == len(events)
|
||||
|
@ -130,80 +161,148 @@ def test_create_revoke(web3, chain, escrow, policy_manager):
|
|||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node.lower() == event_args['node'].lower()
|
||||
# assert node.lower() == event_args['node'].lower()
|
||||
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
assert 1 == len(events)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0})\
|
||||
.revokeArrangement(policy_id_2, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 2 * value == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 2 * value == web3.eth.getBalance(client)
|
||||
assert not policy[4]
|
||||
|
||||
events = policy_manager.pastEvents('ArrangementRevoked').get()
|
||||
assert 2 == len(events)
|
||||
event_args = events[1]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert value == event_args['value']
|
||||
|
||||
# Can't revoke again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).revokeArrangement(policy_id_2, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).revokePolicy(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 0 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance == web3.eth.getBalance(client)
|
||||
assert not policy[4]
|
||||
|
||||
events = policy_manager.pastEvents('ArrangementRevoked').get()
|
||||
assert 4 == len(events)
|
||||
event_args = events[2]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node2.lower() == event_args['node'].lower()
|
||||
assert value == event_args['value']
|
||||
event_args = events[3]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node3.lower() == event_args['node'].lower()
|
||||
assert value == event_args['value']
|
||||
events = policy_manager.pastEvents('PolicyRevoked').get()
|
||||
assert 2 == len(events)
|
||||
event_args = events[1]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert 2 * value == event_args['value']
|
||||
|
||||
# Can't revoke again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).revokePolicy(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).revokeArrangement(policy_id_2, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 0 == len(events)
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 0 == len(events)
|
||||
|
||||
|
||||
def test_reward(web3, chain, escrow, policy_manager):
|
||||
node = web3.eth.accounts[1]
|
||||
client = web3.eth.accounts[2]
|
||||
node_balance = web3.eth.getBalance(node)
|
||||
client = web3.eth.accounts[1]
|
||||
node1 = web3.eth.accounts[3]
|
||||
node2 = web3.eth.accounts[4]
|
||||
node3 = web3.eth.accounts[5]
|
||||
node_balance = web3.eth.getBalance(node1)
|
||||
|
||||
# Mint period without policies
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = escrow.transact({'from': node1, 'gas_price': 0}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 0 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
# Create policy
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = policy_manager.transact({'from': client, 'value': value})\
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
tx = policy_manager.transact({'from': client, 'value': 3 * value})\
|
||||
.createPolicy(policy_id, number_of_periods, [node1, node2, node3])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Nothing to withdraw
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': node}).withdraw()
|
||||
tx = policy_manager.transact({'from': node1}).withdraw()
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Can't update reward directly
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': node}).updateReward(node, period + 1)
|
||||
tx = policy_manager.transact({'from': node1}).updateReward(node1, period + 1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Mint some periods
|
||||
for x in range(5):
|
||||
tx = escrow.transact({'from': node, 'gas_price': 0}).mint(period)
|
||||
tx = escrow.transact({'from': node1, 'gas_price': 0}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
period += 1
|
||||
assert 80 == policy_manager.call().nodes(node)
|
||||
assert 80 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
# Withdraw
|
||||
tx = policy_manager.transact({'from': node, 'gas_price': 0}).withdraw()
|
||||
tx = policy_manager.transact({'from': node1, 'gas_price': 0}).withdraw()
|
||||
chain.wait.for_receipt(tx)
|
||||
assert node_balance + 80 == web3.eth.getBalance(node)
|
||||
assert 120 == web3.eth.getBalance(policy_manager.address)
|
||||
assert node_balance + 80 == web3.eth.getBalance(node1)
|
||||
assert 120 + 2 * value == web3.eth.getBalance(policy_manager.address)
|
||||
|
||||
events = policy_manager.pastEvents('Withdrawn').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
assert node.lower() == event_args['node'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 80 == event_args['value']
|
||||
|
||||
# Mint more periods
|
||||
for x in range(20):
|
||||
tx = escrow.transact({'from': node, 'gas_price': 0}).mint(period)
|
||||
tx = escrow.transact({'from': node1, 'gas_price': 0}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
period += 1
|
||||
assert 120 == policy_manager.call().nodes(node)
|
||||
assert 120 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
# Withdraw
|
||||
tx = policy_manager.transact({'from': node, 'gas_price': 0}).withdraw()
|
||||
tx = policy_manager.transact({'from': node1, 'gas_price': 0}).withdraw()
|
||||
chain.wait.for_receipt(tx)
|
||||
assert node_balance + 200 == web3.eth.getBalance(node)
|
||||
assert 0 == web3.eth.getBalance(policy_manager.address)
|
||||
assert node_balance + value == web3.eth.getBalance(node1)
|
||||
assert 2 * value == web3.eth.getBalance(policy_manager.address)
|
||||
|
||||
events = policy_manager.pastEvents('Withdrawn').get()
|
||||
assert 2 == len(events)
|
||||
event_args = events[1]['args']
|
||||
assert node.lower() == event_args['node'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 120 == event_args['value']
|
||||
|
||||
|
||||
def test_refund(web3, chain, escrow, policy_manager):
|
||||
node = web3.eth.accounts[1]
|
||||
client = web3.eth.accounts[2]
|
||||
client = web3.eth.accounts[1]
|
||||
node1 = web3.eth.accounts[3]
|
||||
node2 = web3.eth.accounts[4]
|
||||
node3 = web3.eth.accounts[5]
|
||||
client_balance = web3.eth.getBalance(client)
|
||||
|
||||
# Create policy
|
||||
tx = policy_manager.transact({'from': client, 'value': value, 'gas_price': 0}) \
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
.createPolicy(policy_id, number_of_periods, [node1])
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().setLastActivePeriod(escrow.call().getCurrentPeriod())
|
||||
chain.wait.for_receipt(tx)
|
||||
|
@ -216,7 +315,15 @@ def test_refund(web3, chain, escrow, policy_manager):
|
|||
assert client_balance - 20 == web3.eth.getBalance(client)
|
||||
assert client == policy_manager.call().policies(policy_id)[0]
|
||||
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 180 == event_args['value']
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
|
@ -229,9 +336,17 @@ def test_refund(web3, chain, escrow, policy_manager):
|
|||
chain.wait.for_receipt(tx)
|
||||
assert 0 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance == web3.eth.getBalance(client)
|
||||
assert '0x' + '0' * 40 == policy_manager.call().policies(policy_id)[0]
|
||||
assert policy_manager.call().policies(policy_id)[4]
|
||||
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 2 == len(events)
|
||||
event_args = events[1]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 20 == event_args['value']
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 2 == len(events)
|
||||
event_args = events[1]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
|
@ -239,68 +354,145 @@ def test_refund(web3, chain, escrow, policy_manager):
|
|||
assert client.lower() == event_args['client'].lower()
|
||||
assert 20 == event_args['value']
|
||||
|
||||
# Can't refund again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).refund(policy_id)
|
||||
chain.wait.for_receipt(tx)
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).refund(policy_id, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Create policy again
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = policy_manager.transact({'from': client, 'value': value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
tx = policy_manager.transact({'from': client, 'value': 3 * value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id_2, number_of_periods, [node1, node2, node3])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Nothing to refund
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 200 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 200 == web3.eth.getBalance(client)
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
assert 2 == len(events)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id_2, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 3 * value == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 3 * value == web3.eth.getBalance(client)
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 6 == len(events)
|
||||
event_args = events[2]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 0 == event_args['value']
|
||||
event_args = events[3]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node2.lower() == event_args['node'].lower()
|
||||
assert 0 == event_args['value']
|
||||
event_args = events[4]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node3.lower() == event_args['node'].lower()
|
||||
assert 0 == event_args['value']
|
||||
event_args = events[5]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 0 == event_args['value']
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 3 == len(events)
|
||||
event_args = events[2]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert 0 == event_args['value']
|
||||
|
||||
# Try to refund nonexistent policy
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).refund(policy_id_2)
|
||||
tx = policy_manager.transact({'from': client}).refund(policy_id_3)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Node try to refund by node
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': node}).refund(policy_id)
|
||||
tx = policy_manager.transact({'from': node1}).refund(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Mint some periods and mark others as downtime periods
|
||||
period += 1
|
||||
tx = escrow.transact().mint(period)
|
||||
tx = escrow.transact({'from': node1}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().mint(period + 1)
|
||||
tx = escrow.transact({'from': node1}).mint(period + 1)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().pushDowntimePeriod(period + 2, period + 3)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().mint(period + 4)
|
||||
tx = escrow.transact({'from': node1}).mint(period + 4)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().pushDowntimePeriod(period + 5, period + 7)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().mint(period + 8)
|
||||
tx = escrow.transact({'from': node1}).mint(period + 8)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().setLastActivePeriod(period + 8)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 80 == policy_manager.call().nodes(node)
|
||||
assert 80 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
# Wait and refund
|
||||
wait_time(chain, 10)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id_2, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 80 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 80 == web3.eth.getBalance(client)
|
||||
assert '0x' + '0' * 40 == policy_manager.call().policies(policy_id)[0]
|
||||
assert 2 * value + 80 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - (2 * value + 80) == web3.eth.getBalance(client)
|
||||
assert not policy_manager.call().policies(policy_id_2)[4]
|
||||
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
assert 3 == len(events)
|
||||
event_args = events[2]['args']
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 7 == len(events)
|
||||
event_args = events[6]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 120 == event_args['value']
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 3 == len(events)
|
||||
|
||||
# Can't refund arrangement again
|
||||
with pytest.raises(TransactionFailed):
|
||||
tx = policy_manager.transact({'from': client}).refund(policy_id, node1)
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# But can refund others
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).refund(policy_id_2)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 3 * 80 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 3 * 80 == web3.eth.getBalance(client)
|
||||
assert policy_manager.call().policies(policy_id_2)[4]
|
||||
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 9 == len(events)
|
||||
event_args = events[7]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node2.lower() == event_args['node'].lower()
|
||||
assert 120 == event_args['value']
|
||||
event_args = events[8]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node3.lower() == event_args['node'].lower()
|
||||
assert 120 == event_args['value']
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 4 == len(events)
|
||||
event_args = events[3]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_2 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert 2 * 120 == event_args['value']
|
||||
|
||||
# Create policy again
|
||||
period = escrow.call().getCurrentPeriod()
|
||||
tx = policy_manager.transact({'from': client, 'value': value, 'gas_price': 0})\
|
||||
.createPolicy(policy_id, node, number_of_periods)
|
||||
.createPolicy(policy_id_3, number_of_periods, [node1])
|
||||
chain.wait.for_receipt(tx)
|
||||
|
||||
# Mint some periods
|
||||
|
@ -309,37 +501,47 @@ def test_refund(web3, chain, escrow, policy_manager):
|
|||
chain.wait.for_receipt(tx)
|
||||
for x in range(3):
|
||||
period += 1
|
||||
tx = escrow.transact({'from': node}).mint(period)
|
||||
tx = escrow.transact({'from': node1}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
tx = escrow.transact().setLastActivePeriod(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 140 == policy_manager.call().nodes(node)
|
||||
assert 140 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
# Client revokes policy
|
||||
wait_time(chain, 4)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).revokePolicy(policy_id)
|
||||
tx = policy_manager.transact({'from': client, 'gas_price': 0}).revokePolicy(policy_id_3)
|
||||
chain.wait.for_receipt(tx)
|
||||
policy = policy_manager.call().policies(policy_id)
|
||||
assert 140 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - 140 == web3.eth.getBalance(client)
|
||||
assert '0x' + '0' * 40 == policy[0]
|
||||
policy = policy_manager.call().policies(policy_id_3)
|
||||
assert 60 + 3 * 80 == web3.eth.getBalance(policy_manager.address)
|
||||
assert client_balance - (60 + 3 * 80) == web3.eth.getBalance(client)
|
||||
assert policy[4]
|
||||
|
||||
events = policy_manager.pastEvents('Refunded').get()
|
||||
events = policy_manager.pastEvents('RefundForArrangement').get()
|
||||
assert 9 == len(events)
|
||||
events = policy_manager.pastEvents('RefundForPolicy').get()
|
||||
assert 4 == len(events)
|
||||
event_args = events[3]['args']
|
||||
events = policy_manager.pastEvents('ArrangementRevoked').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id == event_args['policyId'].encode('latin-1')
|
||||
assert policy_id_3 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert node1.lower() == event_args['node'].lower()
|
||||
assert 140 == event_args['value']
|
||||
events = policy_manager.pastEvents('PolicyRevoked').get()
|
||||
assert 1 == len(events)
|
||||
event_args = events[0]['args']
|
||||
# TODO change when v4 of web3.py is released
|
||||
assert policy_id_3 == event_args['policyId'].encode('latin-1')
|
||||
assert client.lower() == event_args['client'].lower()
|
||||
assert 140 == event_args['value']
|
||||
|
||||
# Minting is useless after revoke
|
||||
for x in range(20):
|
||||
period += 1
|
||||
tx = escrow.transact({'from': node}).mint(period)
|
||||
tx = escrow.transact({'from': node1}).mint(period)
|
||||
chain.wait.for_receipt(tx)
|
||||
assert 140 == policy_manager.call().nodes(node)
|
||||
assert 140 == policy_manager.call().nodes(node1)[0]
|
||||
|
||||
events = policy_manager.pastEvents('PolicyCreated').get()
|
||||
assert 3 == len(events)
|
||||
events = policy_manager.pastEvents('PolicyRevoked').get()
|
||||
assert 1 == len(events)
|
||||
|
|
Loading…
Reference in New Issue