log contract code for debug and genensis generator

This commit is contained in:
Nguyen Sy Thanh Son 2018-07-12 08:15:29 +00:00
parent d4b7305060
commit aa06d56b98
7 changed files with 239 additions and 51 deletions

View file

@ -157,6 +157,19 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
return val[:], nil return val[:], nil
} }
// ForEachStorageAt returns func to read all keys, values in the storage
func (b *SimulatedBackend) ForEachStorageAt(ctx context.Context, contract common.Address, blockNumber *big.Int, f func(key, val common.Hash) bool) error {
b.mu.Lock()
defer b.mu.Unlock()
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 {
return errBlockNumberUnsupported
}
statedb, _ := b.blockchain.State()
statedb.ForEachStorage(contract, f)
return nil
}
// TransactionReceipt returns the receipt of a transaction. // TransactionReceipt returns the receipt of a transaction.
func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
receipt, _, _, _ := core.GetReceipt(b.database, txHash) receipt, _, _, _ := core.GetReceipt(b.database, txHash)

View file

@ -1,8 +1,10 @@
package blocksigner package blocksigner
import ( import (
"context"
"math/big" "math/big"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
@ -25,6 +27,16 @@ func TestBlockSigner(t *testing.T) {
} }
contractBackend.Commit() contractBackend.Commit()
d := time.Now().Add(1000 * time.Millisecond)
ctx, _ := context.WithDeadline(context.Background(), d)
code, _ := contractBackend.CodeAt(ctx, blockSignerAddress, nil)
t.Log("contract code", common.ToHex(code))
f := func(key, val common.Hash) bool {
t.Log(key.Hex(), val.Hex())
return true
}
contractBackend.ForEachStorageAt(ctx, blockSignerAddress, nil, f)
signers, err := blockSigner.GetSigners(big.NewInt(0)) signers, err := blockSigner.GetSigners(big.NewInt(0))
if err != nil { if err != nil {
t.Fatalf("can't get candidates: %v", err) t.Fatalf("can't get candidates: %v", err)

View file

@ -1,11 +1,14 @@
package randomize package randomize
import ( import (
"context"
"math/big" "math/big"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
@ -20,16 +23,27 @@ func TestRandomize(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}) contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
transactOpts := bind.NewKeyedTransactor(key) transactOpts := bind.NewKeyedTransactor(key)
_, randomize, err := DeployRandomize(transactOpts, contractBackend) randomizeAddress, randomize, err := DeployRandomize(transactOpts, contractBackend)
t.Log("contract address", randomizeAddress.String())
if err != nil { if err != nil {
t.Fatalf("can't deploy root registry: %v", err) t.Fatalf("can't deploy root registry: %v", err)
} }
contractBackend.Commit() contractBackend.Commit()
d := time.Now().Add(1000 * time.Millisecond)
ctx, _ := context.WithDeadline(context.Background(), d)
code, _ := contractBackend.CodeAt(ctx, randomizeAddress, nil)
t.Log("contract code", common.ToHex(code))
f := func(key, val common.Hash) bool {
t.Log(key.Hex(), val.Hex())
return true
}
contractBackend.ForEachStorageAt(ctx, randomizeAddress, nil, f)
s, err := randomize.SetSecret(byte0) s, err := randomize.SetSecret(byte0)
if err != nil { if err != nil {
t.Fatalf("can't get secret: %v", err) t.Fatalf("can't get secret: %v", err)
} }
t.Log("secret", s) t.Log("tx data", s)
contractBackend.Commit() contractBackend.Commit()
} }

View file

@ -11,7 +11,7 @@ contract TomoValidator is IValidator {
event Propose(address _owner, address _candidate, uint256 _cap); event Propose(address _owner, address _candidate, uint256 _cap);
event Resign(address _owner, address _candidate); event Resign(address _owner, address _candidate);
event SetNodeUrl(address _owner, address _candidate, string _nodeUrl); event SetNodeUrl(address _owner, address _candidate, string _nodeUrl);
event Withdraw(address _owner, address _candidate, uint256 _cap); event Withdraw(address _owner, uint256 _blockNumber, uint256 _cap);
struct ValidatorState { struct ValidatorState {
address owner; address owner;
@ -22,6 +22,13 @@ contract TomoValidator is IValidator {
mapping(address => uint256) voters; mapping(address => uint256) voters;
} }
struct WithdrawState {
mapping(uint256 => uint256) caps;
uint256[] blockNumbers;
}
mapping(address => WithdrawState) withdrawsState;
mapping(address => ValidatorState) validatorsState; mapping(address => ValidatorState) validatorsState;
mapping(address => address[]) voters; mapping(address => address[]) voters;
address[] public candidates = [ address[] public candidates = [
@ -29,10 +36,13 @@ contract TomoValidator is IValidator {
0x31b249fE6F267aa2396Eb2DC36E9c79351d97Ec5, 0x31b249fE6F267aa2396Eb2DC36E9c79351d97Ec5,
0xfC5571921c6d3672e13B58EA23DEA534f2b35fA0 0xfC5571921c6d3672e13B58EA23DEA534f2b35fA0
]; ];
uint256 candidateCount = 3;
address public firstOwner = 0x487d62d33467c4842c5e54Eb370837E4E88BBA0F;
uint256 public candidateCount = 3;
uint256 public minCandidateCap; uint256 public minCandidateCap;
uint256 public maxValidatorNumber; uint256 public maxValidatorNumber;
uint256 public candidateWithdrawDelay; // blocks uint256 public candidateWithdrawDelay;
uint256 public voterWithdrawDelay;
modifier onlyValidCandidateCap { modifier onlyValidCandidateCap {
// anyone can deposit X TOMO to become a candidate // anyone can deposit X TOMO to become a candidate
@ -50,12 +60,6 @@ contract TomoValidator is IValidator {
_; _;
} }
modifier onlyAlreadyResigned(address _candidate) {
require(validatorsState[_candidate].withdrawBlockNumber > 0);
require(block.number >= validatorsState[_candidate].withdrawBlockNumber);
_;
}
modifier onlyValidCandidate (address _candidate) { modifier onlyValidCandidate (address _candidate) {
require(validatorsState[_candidate].isCandidate); require(validatorsState[_candidate].isCandidate);
_; _;
@ -71,23 +75,35 @@ contract TomoValidator is IValidator {
_; _;
} }
modifier onlyValidWithdraw (uint256 _blockNumber, uint _index) {
require(_blockNumber > 0);
require(block.number >= _blockNumber);
require(withdrawsState[msg.sender].caps[_blockNumber] > 0);
require(withdrawsState[msg.sender].blockNumbers[_index] == _blockNumber);
_;
}
function TomoValidator ( function TomoValidator (
uint256 _minCandidateCap, uint256 _minCandidateCap,
uint256 _maxValidatorNumber, uint256 _maxValidatorNumber,
uint256 _candidateWithdrawDelay uint256 _candidateWithdrawDelay,
uint256 _voterWithdrawDelay
) public { ) public {
minCandidateCap = _minCandidateCap; minCandidateCap = _minCandidateCap;
maxValidatorNumber = _maxValidatorNumber; maxValidatorNumber = _maxValidatorNumber;
candidateWithdrawDelay = _candidateWithdrawDelay; candidateWithdrawDelay = _candidateWithdrawDelay;
voterWithdrawDelay = _voterWithdrawDelay;
for (uint256 i = 0; i < candidates.length; i++) { for (uint256 i = 0; i < candidates.length; i++) {
validatorsState[candidates[i]] = ValidatorState({ validatorsState[candidates[i]] = ValidatorState({
owner: 0x487d62d33467c4842c5e54Eb370837E4E88BBA0F, owner: firstOwner,
nodeUrl: '', nodeUrl: '',
isCandidate: true, isCandidate: true,
withdrawBlockNumber: 0, withdrawBlockNumber: 0,
cap: minCandidateCap cap: minCandidateCap
}); });
voters[candidates[i]].push(firstOwner);
validatorsState[candidates[i]].voters[firstOwner] = minCandidateCap;
} }
} }
@ -102,6 +118,7 @@ contract TomoValidator is IValidator {
}); });
validatorsState[_candidate].voters[msg.sender] = msg.value; validatorsState[_candidate].voters[msg.sender] = msg.value;
candidateCount = candidateCount + 1; candidateCount = candidateCount + 1;
voters[_candidate].push(_candidate);
emit Propose(msg.sender, _candidate, msg.value); emit Propose(msg.sender, _candidate, msg.value);
} }
@ -146,11 +163,19 @@ contract TomoValidator is IValidator {
return validatorsState[_candidate].isCandidate; return validatorsState[_candidate].isCandidate;
} }
function getWithdrawBlockNumbers() public view returns(uint256[]) {
return withdrawsState[msg.sender].blockNumbers;
}
function unvote(address _candidate, uint256 _cap) public onlyValidVote(_candidate, _cap) { function unvote(address _candidate, uint256 _cap) public onlyValidVote(_candidate, _cap) {
validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(_cap); validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(_cap);
validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].sub(_cap); validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].sub(_cap);
// refunding to user after unvoting
msg.sender.transfer(_cap); // refund after delay X blocks
uint256 withdrawBlockNumber = voterWithdrawDelay.add(block.number);
withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[msg.sender].caps[withdrawBlockNumber].add(_cap);
withdrawsState[msg.sender].blockNumbers.push(withdrawBlockNumber);
emit Unvote(msg.sender, _candidate, _cap); emit Unvote(msg.sender, _candidate, _cap);
} }
@ -168,17 +193,21 @@ contract TomoValidator is IValidator {
break; break;
} }
} }
// refunding after retiring X blocks
validatorsState[_candidate].withdrawBlockNumber = validatorsState[_candidate].withdrawBlockNumber.add(block.number).add(candidateWithdrawDelay);
emit Resign(msg.sender, _candidate);
}
function withdraw(address _candidate) public onlyOwner(_candidate) onlyNotCandidate(_candidate) onlyAlreadyResigned(_candidate) {
uint256 cap = validatorsState[_candidate].voters[msg.sender]; uint256 cap = validatorsState[_candidate].voters[msg.sender];
validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(cap); validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(cap);
validatorsState[_candidate].voters[msg.sender] = 0; validatorsState[_candidate].voters[msg.sender] = 0;
validatorsState[_candidate].withdrawBlockNumber = 0; // refunding after retiring X blocks
uint256 withdrawBlockNumber = candidateWithdrawDelay.add(block.number);
withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[msg.sender].caps[withdrawBlockNumber].add(cap);
withdrawsState[msg.sender].blockNumbers.push(withdrawBlockNumber);
emit Resign(msg.sender, _candidate);
}
function withdraw(uint256 _blockNumber, uint _index) public onlyValidWithdraw(_blockNumber, _index) {
uint256 cap = withdrawsState[msg.sender].caps[_blockNumber];
delete withdrawsState[msg.sender].caps[_blockNumber];
delete withdrawsState[msg.sender].blockNumbers[_index];
msg.sender.transfer(cap); msg.sender.transfer(cap);
emit Withdraw(msg.sender, _candidate, cap); emit Withdraw(msg.sender, _blockNumber, cap);
} }
} }

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,7 @@
package validator package validator
import ( import (
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/contracts/validator/contract"
@ -28,7 +29,10 @@ func NewValidator(transactOpts *bind.TransactOpts, contractAddr common.Address,
} }
func DeployValidator(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *Validator, error) { func DeployValidator(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *Validator, error) {
validatorAddr, _, _, err := contract.DeployTomoValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100)) minDeposit := new(big.Int)
minDeposit.SetString("50000000000000000000000", 10)
fmt.Println("--->", common.BigToHash(minDeposit).Hex())
validatorAddr, _, _, err := contract.DeployTomoValidator(transactOpts, contractBackend, minDeposit, big.NewInt(99), big.NewInt(100), big.NewInt(100))
if err != nil { if err != nil {
return validatorAddr, nil, err return validatorAddr, nil, err
} }

View file

@ -1,17 +1,19 @@
package validator package validator
import ( import (
"context"
"math/big" "math/big"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts" "github.com/ethereum/go-ethereum/contracts"
"github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"math/rand" "math/rand"
"time"
) )
var ( var (
@ -31,12 +33,22 @@ func TestValidator(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}) contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
transactOpts := bind.NewKeyedTransactor(key) transactOpts := bind.NewKeyedTransactor(key)
_, validator, err := DeployValidator(transactOpts, contractBackend) validatorAddress, validator, err := DeployValidator(transactOpts, contractBackend)
if err != nil { if err != nil {
t.Fatalf("can't deploy root registry: %v", err) t.Fatalf("can't deploy root registry: %v", err)
} }
contractBackend.Commit() contractBackend.Commit()
d := time.Now().Add(1000 * time.Millisecond)
ctx, _ := context.WithDeadline(context.Background(), d)
code, _ := contractBackend.CodeAt(ctx, validatorAddress, nil)
t.Log("contract code", common.ToHex(code))
f := func(key, val common.Hash) bool {
t.Log(key.Hex(), val.Hex())
return true
}
contractBackend.ForEachStorageAt(ctx, validatorAddress, nil, f)
candidates, err := validator.GetCandidates() candidates, err := validator.GetCandidates()
if err != nil { if err != nil {
t.Fatalf("can't get candidates: %v", err) t.Fatalf("can't get candidates: %v", err)
@ -61,7 +73,7 @@ func TestRewardBalance(t *testing.T) {
accounts := []*bind.TransactOpts{acc1Opts, acc2Opts} accounts := []*bind.TransactOpts{acc1Opts, acc2Opts}
transactOpts := bind.NewKeyedTransactor(acc1Key) transactOpts := bind.NewKeyedTransactor(acc1Key)
validatorAddr, _, baseValidator, err := contract.DeployTomoValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100)) validatorAddr, _, baseValidator, err := contract.DeployTomoValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100), big.NewInt(100))
if err != nil { if err != nil {
t.Fatalf("can't deploy root registry: %v", err) t.Fatalf("can't deploy root registry: %v", err)
} }