[KMS-ETH]- Added DHT key publishing

pull/195/head^2
szotov 2018-02-22 17:18:57 +03:00
parent 9643667c11
commit ae15b4ac35
2 changed files with 94 additions and 37 deletions

View File

@ -1,4 +1,4 @@
pragma solidity ^0.4.8;
pragma solidity ^0.4.18;
import "./zeppelin/token/SafeERC20.sol";
@ -29,7 +29,7 @@ contract MinersEscrow is Issuer, Ownable {
uint256 endPeriod;
}
struct TokenInfo {
struct MinerInfo {
uint256 value;
uint256 decimals;
uint256 lockedValue;
@ -42,13 +42,14 @@ contract MinersEscrow is Issuer, Ownable {
// downtime
uint256 lastActivePeriod;
Downtime[] downtime;
bytes[] dhtKeys;
}
uint256 constant MAX_PERIODS = 10;
uint256 constant MAX_OWNERS = 50000;
mapping (address => TokenInfo) public tokenInfo;
LinkedList.Data public tokenOwners;
mapping (address => MinerInfo) public minerInfo;
LinkedList.Data public miners;
mapping (uint256 => uint256) public lockedPerPeriod;
uint256 public minReleasePeriods;
@ -96,7 +97,7 @@ contract MinersEscrow is Issuer, Ownable {
**/
modifier onlyTokenOwner()
{
require(tokenOwners.valueExists(msg.sender));
require(miners.valueExists(msg.sender));
_;
}
@ -107,7 +108,7 @@ contract MinersEscrow is Issuer, Ownable {
function getTokens(address _owner)
public constant returns (uint256)
{
return tokenInfo[_owner].value;
return minerInfo[_owner].value;
}
/**
@ -118,7 +119,7 @@ contract MinersEscrow is Issuer, Ownable {
public constant returns (uint256)
{
var currentPeriod = getCurrentPeriod();
var info = tokenInfo[_owner];
var info = minerInfo[_owner];
var numberConfirmedPeriods = info.numberConfirmedPeriods;
// no confirmed periods, so current period may be release period
@ -174,7 +175,7 @@ contract MinersEscrow is Issuer, Ownable {
)
internal constant returns (uint256)
{
var info = tokenInfo[_owner];
var info = minerInfo[_owner];
if ((_forceRelease || info.release) && _periods != 0) {
var unlockedTokens = _periods.mul(info.releaseRate);
return unlockedTokens <= _lockedTokens ? _lockedTokens.sub(unlockedTokens) : 0;
@ -196,7 +197,7 @@ contract MinersEscrow is Issuer, Ownable {
var currentPeriod = getCurrentPeriod();
var nextPeriod = currentPeriod.add(_periods);
var info = tokenInfo[_owner];
var info = minerInfo[_owner];
var numberConfirmedPeriods = info.numberConfirmedPeriods;
if (numberConfirmedPeriods > 0 &&
info.confirmedPeriods[numberConfirmedPeriods - 1].period >= currentPeriod) {
@ -223,7 +224,7 @@ contract MinersEscrow is Issuer, Ownable {
)
internal constant returns (uint256)
{
var info = tokenInfo[_owner];
var info = minerInfo[_owner];
return _lockedTokens.divCeil(info.releaseRate).sub(1);
}
@ -237,7 +238,7 @@ contract MinersEscrow is Issuer, Ownable {
public isInitialized onlyOwner
{
require(_owners.length != 0 &&
tokenOwners.sizeOf().add(_owners.length) <= MAX_OWNERS &&
miners.sizeOf().add(_owners.length) <= MAX_OWNERS &&
_owners.length == _values.length &&
_owners.length == _periods.length);
var currentPeriod = getCurrentPeriod();
@ -247,13 +248,13 @@ contract MinersEscrow is Issuer, Ownable {
var owner = _owners[i];
var value = _values[i];
var periods = _periods[i];
require(!tokenOwners.valueExists(owner) &&
require(!miners.valueExists(owner) &&
value >= minAllowableLockedTokens &&
value <= maxAllowableLockedTokens &&
periods >= minReleasePeriods);
// TODO optimize
tokenOwners.push(owner, true);
var info = tokenInfo[owner];
miners.push(owner, true);
var info = minerInfo[owner];
info.lastActivePeriod = currentPeriod;
info.value = value;
info.lockedValue = value;
@ -273,10 +274,10 @@ contract MinersEscrow is Issuer, Ownable {
**/
function deposit(uint256 _value, uint256 _periods) public isInitialized {
require(_value != 0);
var info = tokenInfo[msg.sender];
if (!tokenOwners.valueExists(msg.sender)) {
require(tokenOwners.sizeOf() < MAX_OWNERS);
tokenOwners.push(msg.sender, true);
var info = minerInfo[msg.sender];
if (!miners.valueExists(msg.sender)) {
require(miners.sizeOf() < MAX_OWNERS);
miners.push(msg.sender, true);
info.lastActivePeriod = getCurrentPeriod();
}
info.value = info.value.add(_value);
@ -293,7 +294,7 @@ contract MinersEscrow is Issuer, Ownable {
require(_value != 0 || _periods != 0);
var lockedTokens = calculateLockedTokens(msg.sender, 1);
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
require(_value <= token.balanceOf(address(this)) &&
_value <= info.value.sub(lockedTokens));
@ -319,7 +320,7 @@ contract MinersEscrow is Issuer, Ownable {
* @notice Switch lock
**/
function switchLock() public onlyTokenOwner {
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
info.release = !info.release;
}
@ -328,7 +329,7 @@ contract MinersEscrow is Issuer, Ownable {
* @param _value Amount of token to withdraw
**/
function withdraw(uint256 _value) public onlyTokenOwner {
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
// TODO optimize
var lockedTokens = Math.max256(calculateLockedTokens(msg.sender, 1),
getLockedTokens(msg.sender));
@ -342,13 +343,13 @@ contract MinersEscrow is Issuer, Ownable {
* @notice Withdraw all amount of tokens back to owner (only if no locked)
**/
function withdrawAll() public onlyTokenOwner {
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
var value = info.value;
require(value <= token.balanceOf(address(this)) &&
info.lockedValue == 0 &&
info.numberConfirmedPeriods == 0);
tokenOwners.remove(msg.sender);
delete tokenInfo[msg.sender];
miners.remove(msg.sender);
delete minerInfo[msg.sender];
token.safeTransfer(msg.sender, value);
}
@ -362,7 +363,7 @@ contract MinersEscrow is Issuer, Ownable {
// // Transfer tokens to owners
// var current = tokenOwners.step(0x0, true);
// while (current != 0x0) {
// token.safeTransfer(current, tokenInfo[current].value);
// token.safeTransfer(current, minerInfo[current].value);
// current = tokenOwners.step(current, true);
// }
// token.safeTransfer(owner, token.balanceOf(address(this)));
@ -377,7 +378,7 @@ contract MinersEscrow is Issuer, Ownable {
**/
function confirmActivity(uint256 _lockedValue) internal {
require(_lockedValue > 0);
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
var nextPeriod = getCurrentPeriod() + 1;
var numberConfirmedPeriods = info.numberConfirmedPeriods;
@ -412,7 +413,7 @@ contract MinersEscrow is Issuer, Ownable {
* @notice Confirm activity for future period
**/
function confirmActivity() external onlyTokenOwner {
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
var currentPeriod = getCurrentPeriod();
var nextPeriod = currentPeriod + 1;
@ -431,7 +432,7 @@ contract MinersEscrow is Issuer, Ownable {
**/
function mint() external onlyTokenOwner {
var previousPeriod = getCurrentPeriod().sub(1);
var info = tokenInfo[msg.sender];
var info = minerInfo[msg.sender];
var numberPeriodsForMinting = info.numberConfirmedPeriods;
require(numberPeriodsForMinting > 0 &&
info.confirmedPeriods[0].period <= previousPeriod);
@ -508,11 +509,11 @@ contract MinersEscrow is Issuer, Ownable {
var current = _start;
if (current == 0x0) {
current = tokenOwners.step(current, true);
current = miners.step(current, true);
}
while (current != 0x0) {
var info = tokenInfo[current];
var info = minerInfo[current];
var numberConfirmedPeriods = info.numberConfirmedPeriods;
var period = currentPeriod;
if (numberConfirmedPeriods > 0 &&
@ -530,7 +531,7 @@ contract MinersEscrow is Issuer, Ownable {
info.confirmedPeriods[numberConfirmedPeriods - 1].lockedValue,
_periods - 1);
} else {
current = tokenOwners.step(current, true);
current = miners.step(current, true);
continue;
}
@ -540,7 +541,7 @@ contract MinersEscrow is Issuer, Ownable {
break;
} else {
distance += lockedTokens;
current = tokenOwners.step(current, true);
current = miners.step(current, true);
}
}
}
@ -562,7 +563,7 @@ contract MinersEscrow is Issuer, Ownable {
function getDowntimePeriods(address _owner, uint256 _index)
public constant returns (uint256 startPeriod, uint256 endPeriod)
{
var period = tokenInfo[msg.sender].downtime[_index];
var period = minerInfo[msg.sender].downtime[_index];
startPeriod = period.startPeriod;
endPeriod = period.endPeriod;
}
@ -573,7 +574,7 @@ contract MinersEscrow is Issuer, Ownable {
function getDowntimePeriodsLength(address _owner)
public constant returns (uint256)
{
return tokenInfo[msg.sender].downtime.length;
return minerInfo[msg.sender].downtime.length;
}
/**
@ -582,6 +583,32 @@ contract MinersEscrow is Issuer, Ownable {
function getLastActivePeriod(address _owner)
public constant returns (uint256)
{
return tokenInfo[msg.sender].lastActivePeriod;
return minerInfo[msg.sender].lastActivePeriod;
}
/**
* @notice Public DHT key
**/
function publishDHTKey(bytes _dhtKey) public {
var info = minerInfo[msg.sender];
info.dhtKeys.push(_dhtKey);
}
/**
* @notice Get DHT keys count
**/
function getDHTKeysCount(address _owner)
public constant returns (uint256)
{
return minerInfo[_owner].dhtKeys.length;
}
/**
* @notice Get DHT key
**/
function getDHTKey(address _owner, uint256 _index)
public constant returns (bytes)
{
return minerInfo[_owner].dhtKeys[_index];
}
}

View File

@ -1,5 +1,6 @@
import pytest
from ethereum.tester import TransactionFailed
import os
@pytest.fixture()
@ -505,7 +506,7 @@ def test_pre_deposit(web3, chain, token, escrow_contract):
assert 1000 == token.call().balanceOf(escrow.address)
assert 1000 == escrow.call().getTokens(owner)
assert 1000 == escrow.call().getLockedTokens(owner)
assert 10 == escrow.call().tokenInfo(owner)[4]
assert 10 == escrow.call().minerInfo(owner)[4]
# Can't pre-deposit tokens again for same owner
with pytest.raises(TransactionFailed):
@ -536,4 +537,33 @@ def test_pre_deposit(web3, chain, token, escrow_contract):
for index, owner in enumerate(owners):
assert 100 * (index + 1) == escrow.call().getTokens(owner)
assert 100 * (index + 1) == escrow.call().getLockedTokens(owner)
assert 50 * (index + 1) == escrow.call().tokenInfo(owner)[4]
assert 50 * (index + 1) == escrow.call().minerInfo(owner)[4]
def test_publish_dht_key(web3, chain, token, escrow_contract):
escrow = escrow_contract(5 * 10 ** 8)
creator = web3.eth.accounts[0]
miner = web3.eth.accounts[1]
# Initialize contract and miner
tx = escrow.transact().initialize()
chain.wait.for_receipt(tx)
tx = token.transact({'from': creator}).transfer(miner, 1000)
chain.wait.for_receipt(tx)
balance = token.call().balanceOf(miner)
tx = token.transact({'from': miner}).approve(escrow.address, balance)
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': miner}).deposit(balance, 1)
chain.wait.for_receipt(tx)
# Publish DHT keys
dht_key = os.urandom(66).hex()
tx = escrow.transact({'from': miner}).publishDHTKey(dht_key)
chain.wait.for_receipt(tx)
assert 1 == escrow.call().getDHTKeysCount(miner)
assert dht_key == escrow.call().getDHTKey(miner, 0)
dht_key = os.urandom(66).hex()
tx = escrow.transact({'from': miner}).publishDHTKey(dht_key)
chain.wait.for_receipt(tx)
assert 2 == escrow.call().getDHTKeysCount(miner)
assert dht_key == escrow.call().getDHTKey(miner, 1)