Skip to content

Commit

Permalink
Merge pull request #101 from mysteriumnetwork/feature/hermes_url
Browse files Browse the repository at this point in the history
Store hermes URL in blockchain
  • Loading branch information
chompomonim authored Jun 22, 2020
2 parents d36f728 + a3be0e5 commit 037e94c
Show file tree
Hide file tree
Showing 15 changed files with 82 additions and 25 deletions.
31 changes: 24 additions & 7 deletions contracts/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ contract Registry is FundsRecovery {
using ECDSA for bytes32;
using SafeMath for uint256;

string constant REGISTER_PREFIX="Register prefix:";

address public dex;
uint256 public registrationFee;
uint256 public minimalHermesStake;
Expand All @@ -38,15 +36,17 @@ contract Registry is FundsRecovery {
ParentRegistry internal parentRegistry;

struct Hermes {
address operator;
address operator; // hermes operator who will sign promises
function() external view returns(uint256) stake;
bytes url; // hermes service URL
}
mapping(address => Hermes) public hermeses;

mapping(address => bool) private identities;

event RegisteredIdentity(address indexed identityHash, address indexed hermesId);
event RegisteredHermes(address indexed hermesId, address hermesOperator);
event RegisteredHermes(address indexed hermesId, address hermesOperator, bytes ur);
event HermesURLUpdated(address indexed hermesId, bytes newURL);
event ConsumerChannelCreated(address indexed identityHash, address indexed hermesId, address channelAddress);

constructor (address _tokenAddress, address _dexAddress, uint256 _regFee, uint256 _minimalHermesStake, address _channelImplementation, address _hermesImplementation, address _parentAddress) public {
Expand Down Expand Up @@ -109,7 +109,7 @@ contract Registry is FundsRecovery {
}
}

function registerHermes(address _hermesOperator, uint256 _stakeAmount, uint16 _hermesFee, uint256 _minStake, uint256 _maxStake) public {
function registerHermes(address _hermesOperator, uint256 _stakeAmount, uint16 _hermesFee, uint256 _minStake, uint256 _maxStake, bytes memory _url) public {
require(_hermesOperator != address(0), "operator can't be zero address");
require(_stakeAmount >= minimalHermesStake, "hermes have to stake at least minimal stake amount");

Expand All @@ -126,9 +126,9 @@ contract Registry is FundsRecovery {
_hermes.initialize(address(token), _hermesOperator, _hermesFee, _minStake, _maxStake);

// Save info about newly created hermes
hermeses[address(_hermes)] = Hermes(_hermesOperator, _hermes.getStake);
hermeses[address(_hermes)] = Hermes(_hermesOperator, _hermes.getStake, _url);

emit RegisteredHermes(address(_hermes), _hermesOperator);
emit RegisteredHermes(address(_hermes), _hermesOperator, _url);
}

function getChannelAddress(address _identity, address _hermesId) public view returns (address) {
Expand All @@ -142,6 +142,23 @@ contract Registry is FundsRecovery {
return getCreate2Address(bytes32(uint256(_hermesOperator)), _code);
}

function getHermesURL(address _hermesId) public view returns (bytes memory) {
return hermeses[_hermesId].url;
}

function updateHermsURL(address _hermesId, bytes memory _url, bytes memory _signature) public {
require(isActiveHermes(_hermesId), "provided hermes has to be active");

// Check if given signature is valid
address _operator = keccak256(abi.encodePacked(address(this), _hermesId, _url)).recover(_signature);
require(_operator == hermeses[_hermesId].operator, "wrong signature");

// Update URL
hermeses[_hermesId].url = _url;

emit HermesURLUpdated(_hermesId, _url);
}

// ------------ UTILS ------------
function getCreate2Address(bytes32 _salt, bytes32 _code) internal view returns (address) {
return address(uint256(keccak256(abi.encodePacked(
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "payments-smart-contracts",
"version": "0.9.3",
"version": "0.9.4",
"description": "Smart contracts for Mysterium Network payments flow",
"main": "index.js",
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion test/beneficiary.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const OneEther = web3.utils.toWei(new BN(1), 'ether')
const Zero = new BN(0)
const zeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

// const operatorPrivKey = Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')
const operator = wallet.generateAccount(Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')) // Generate hermes operator wallet
Expand All @@ -49,7 +50,7 @@ contract("Setting beneficiary tests", ([txMaker, operatorAddress, beneficiaryA,
})

it("should register and initialize hermes hub", async () => {
await registry.registerHermes(operator.address, 10, 0, 25, OneToken)
await registry.registerHermes(operator.address, 10, 0, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(operator.address)
expect(await registry.isHermes(hermesId)).to.be.true

Expand Down
3 changes: 2 additions & 1 deletion test/fundsRecoveryByCheque.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const MystDex = artifacts.require("MystDEX")
const OneEther = web3.utils.toWei('1', 'ether')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

function createCheque(signer, destination, nonce) {
const PREFIX = Buffer.from("Set funds destination:")
Expand Down Expand Up @@ -64,7 +65,7 @@ contract('Full path (in channel using cheque) test for funds recovery', ([txMake
})

it('should register hermes', async () => {
await registry.registerHermes(hermesOperator, 10, 0, 25, OneEther)
await registry.registerHermes(hermesOperator, 10, 0, 25, OneEther, hermesURL)
expect(await registry.isHermes(hermesId)).to.be.true
})

Expand Down
3 changes: 2 additions & 1 deletion test/greenpaths.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const OneEther = web3.utils.toWei(new BN(1), 'ether')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

let token, hermes, registry;
const identities = generateIdentities(5) // Generates array of identities
Expand Down Expand Up @@ -65,7 +66,7 @@ contract('Green path tests', ([txMaker, ...beneficiaries]) => {
// TODO Topup = Register
// Ask tx-maker to make tx + sign cheque for him for that. Works even with registration fee stuff.
it("register and initialize hermes", async () => {
await registry.registerHermes(operator.address, 10, 0, 25, OneToken)
await registry.registerHermes(operator.address, 10, 0, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(operator.address)
expect(await registry.isHermes(hermesId)).to.be.true

Expand Down
3 changes: 2 additions & 1 deletion test/hermes.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const OneEther = web3.utils.toWei(new BN(1), 'ether')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const operatorPrivKey = Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')

Expand Down Expand Up @@ -55,7 +56,7 @@ contract('Hermes Contract Implementation tests', ([txMaker, operatorAddress, ben
})

it("should register and initialize hermes", async () => {
await registry.registerHermes(operator.address, 10, 0, 25, OneToken)
await registry.registerHermes(operator.address, 10, 0, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(operator.address)
expect(await registry.isHermes(hermesId)).to.be.true

Expand Down
3 changes: 2 additions & 1 deletion test/hermesChannelSettlement.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const OneEther = web3.utils.toWei(new BN(1), 'ether')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const operator = wallet.generateAccount(Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')) // Generate hermes operator wallet
const providerA = wallet.generateAccount()
Expand All @@ -52,7 +53,7 @@ contract("Channel openinig via settlement tests", ([txMaker, beneficiaryA, benef
})

it("should register and initialize hermes hub", async () => {
await registry.registerHermes(operator.address, 1000, Zero, 25, OneToken)
await registry.registerHermes(operator.address, 1000, Zero, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(operator.address)
expect(await registry.isHermes(hermesId)).to.be.true

Expand Down
3 changes: 2 additions & 1 deletion test/hermesClosing.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ChannelImplementation = artifacts.require("ChannelImplementation")
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const operatorPrivKey = Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')
const hermesOperator = wallet.generateAccount(operatorPrivKey)
Expand All @@ -42,7 +43,7 @@ contract('Hermes closing', ([txMaker, operatorAddress, ...beneficiaries]) => {
})

it('should register hermes', async () => {
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken)
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(hermesOperator.address)
hermes = await HermesImplementation.at(hermesId)
expect(await registry.isHermes(hermes.address)).to.be.true
Expand Down
3 changes: 2 additions & 1 deletion test/hermesFee.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const ChannelImplementation = artifacts.require("ChannelImplementation")
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const provider = wallet.generateAccount()
const operatorPrivKey = Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')
Expand All @@ -41,7 +42,7 @@ contract('Hermes fee', ([txMaker, operatorAddress, ...beneficiaries]) => {
it('should calculate proper fee righ after hermes registration', async () => {
// Register hermes
const hermesFee = 250 // 2.50%
await registry.registerHermes(hermesOperator.address, 100, hermesFee, 25, OneToken)
await registry.registerHermes(hermesOperator.address, 100, hermesFee, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(hermesOperator.address)
hermes = await HermesImplementation.at(hermesId)

Expand Down
3 changes: 2 additions & 1 deletion test/hermesPunishment.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const ChannelImplementation = artifacts.require("ChannelImplementation")
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const provider = wallet.generateAccount()
const operatorPrivKey = Buffer.from('d6dd47ec61ae1e85224cec41885eec757aa77d518f8c26933e5d9f0cda92f3c3', 'hex')
Expand All @@ -44,7 +45,7 @@ contract('Hermes punishment', ([txMaker, operatorAddress, ...beneficiaries]) =>
})

it('should register hermes', async () => {
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken)
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(hermesOperator.address)
hermes = await HermesImplementation.at(hermesId)
expect(await registry.isHermes(hermes.address)).to.be.true
Expand Down
5 changes: 3 additions & 2 deletions test/hermesStake.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ChannelImplementation = artifacts.require("ChannelImplementation")
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

const provider = wallet.generateAccount()
const hermesOperator = wallet.generateAccount()
Expand All @@ -43,11 +44,11 @@ contract('Hermes stake management', ([txMaker, operatorAddress, ...beneficiaries

it('should reject hermes registration if he do not pay enought stake', async () => {
const stateAmount = stake - 1
await registry.registerHermes(hermesOperator.address, stateAmount, Zero, 25, OneToken).should.be.rejected
await registry.registerHermes(hermesOperator.address, stateAmount, Zero, 25, OneToken, hermesURL).should.be.rejected
})

it('should register hermes when stake is ok', async () => {
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken)
await registry.registerHermes(hermesOperator.address, stake, Zero, 25, OneToken, hermesURL)
const hermesId = await registry.getHermesAddress(hermesOperator.address)
hermes = await HermesImplementation.at(hermesId)
expect(await registry.isHermes(hermes.address)).to.be.true
Expand Down
3 changes: 2 additions & 1 deletion test/multiHermes.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const ChannelImplementation = artifacts.require("ChannelImplementation")
const Zero = new BN(0)
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

// Generate private keys for hermes operators
const operators = [
Expand Down Expand Up @@ -42,7 +43,7 @@ contract('Multi hermeses', ([txMaker, ...beneficiaries]) => {
it('should register hermeses', async () => {
hermeses = []
for (const operator of operators) {
await registry.registerHermes(operator.address, 10, 0, 25, OneToken)
await registry.registerHermes(operator.address, 10, 0, 25, OneToken, hermesURL)
const id = await registry.getHermesAddress(operator.address)
hermeses.push({ id, operator })
expect(await registry.isHermes(id)).to.be.true
Expand Down
5 changes: 2 additions & 3 deletions test/parentRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ const HermesImplementation = artifacts.require("HermesImplementation")
const Registry = artifacts.require("Registry")
const ParentRegistry = artifacts.require("TestOldRegistry")

const OneEther = web3.utils.toWei('1', 'ether')
const OneToken = web3.utils.toWei(new BN('100000000'), 'wei')
const Zero = new BN(0)
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const hermesURL = Buffer.from('http://test.hermes')

function generateIdentities(amount) {
return (amount <= 0) ? [generateAccount()] : [generateAccount(), ...generateIdentities(amount - 1)]
Expand Down Expand Up @@ -47,7 +46,7 @@ contract('Parent registry', ([txMaker, minter, hermesOperator, hermesOperator2,
})

it('should register hermes into new registry', async () => {
await registry.registerHermes(hermesOperator2, 10, 0, 25, OneToken)
await registry.registerHermes(hermesOperator2, 10, 0, 25, OneToken, hermesURL)
hermesId = await registry.getHermesAddress(hermesOperator2)
expect(await registry.isHermes(hermesId)).to.be.true
})
Expand Down
22 changes: 19 additions & 3 deletions test/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { BN } = require('@openzeppelin/test-helpers')

const genCreate2Address = require('./utils/index.js').genCreate2Address
const topUpTokens = require('./utils/index.js').topUpTokens
const signIdentityRegistration = require('./utils/client.js').signIdentityRegistration
const { signIdentityRegistration, signUrlUpdate } = require('./utils/client.js')
const generateAccount = require('./utils/wallet.js').generateAccount

const Registry = artifacts.require("Registry")
Expand All @@ -24,8 +24,10 @@ function generateIdentities(amount) {
}

const identities = generateIdentities(3) // Generates array of identities
const operator = generateAccount()
const hermesOperator = operator.address

contract('Registry', ([txMaker, minter, hermesOperator, fundsDestination, ...otherAccounts]) => {
contract('Registry', ([txMaker, minter, fundsDestination, ...otherAccounts]) => {
let token, channelImplementation, hermesImplementation, hermesId, dex, registry
before(async () => {
token = await MystToken.new()
Expand All @@ -45,11 +47,25 @@ contract('Registry', ([txMaker, minter, hermesOperator, fundsDestination, ...oth
})

it('should register hermes', async () => {
await registry.registerHermes(hermesOperator, 10, 0, 25, OneToken)
const hermesURL = Buffer.from('http://test.hermes')
await registry.registerHermes(hermesOperator, 10, 0, 25, OneToken, hermesURL)
hermesId = await registry.getHermesAddress(hermesOperator)
expect(await registry.isHermes(hermesId)).to.be.true
})

it('hermes should have proper URL', async () => {
const expectedURL = 'http://test.hermes'
expect(Buffer.from((await registry.getHermesURL(hermesId)).slice(2), 'hex').toString()).to.be.equal(expectedURL)
})

it('should be possible to change hermes URL', async () => {
const newURL = 'https://test.hermes/api/v2'
const signature = signUrlUpdate(registry.address, hermesId, newURL, operator)
await registry.updateHermsURL(hermesId, Buffer.from(newURL), signature)

expect(Buffer.from((await registry.getHermesURL(hermesId)).slice(2), 'hex').toString()).to.be.equal(newURL)
})

it('should register identity having 0 balance', async () => {
const identity = identities[0]
const identityHash = identity.address
Expand Down
15 changes: 15 additions & 0 deletions test/utils/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,20 @@ function signIdentityRegistration(registryAddress, hermesId, stake, fee, benefic
return signature
}

function signUrlUpdate(registryAddress, hermesId, url, identity) {
const message = Buffer.concat([
Buffer.from(registryAddress.slice(2), 'hex'),
Buffer.from(hermesId.slice(2), 'hex'),
Buffer.from(url)
])

// sign and verify the signature
const signature = signMessage(message, identity.privKey)
expect(verifySignature(message, signature, identity.pubKey)).to.be.true

return signature
}

function signStakeGoalUpdate(channelId, stakeGoal, channelNonce, identity) {
const STAKE_GOAL_UPDATE_PREFIX = "Stake goal update request"

Expand Down Expand Up @@ -385,5 +399,6 @@ module.exports = {
signExitRequest,
signIdentityRegistration,
signStakeGoalUpdate,
signUrlUpdate,
validatePromise
}

0 comments on commit 037e94c

Please sign in to comment.