sharding: added submitVote test

Former-commit-id: 969f64168aea10d5b812919bf5a3d4f534a90922 [formerly 03a49e09f1ffbfe52858d89ddcbbac34f848ba19]
Former-commit-id: f1f57db412f0ae9bc22c31a5aabd5f4e4df3491c
This commit is contained in:
Terence Tsao 2018-05-08 17:55:50 -07:00
parent 6fb4d23c5d
commit 9dbf1936b4
3 changed files with 165 additions and 37 deletions

File diff suppressed because one or more lines are too long

View File

@ -205,15 +205,23 @@ contract SMC {
emit VoteSubmitted(_shardId, _chunkRoot, _period, msg.sender);
}
/// To keep track of notary size in between periods, we call updateNotarySampleSize
/// before notary registration/deregistration so correct size can be applied next period
function updateNotarySampleSize() internal {
uint currentPeriod = block.number / PERIOD_LENGTH;
if (currentPeriod < sampleSizeLastUpdatedPeriod) {
return;
}
currentPeriodNotarySampleSize = nextPeriodNotarySampleSize;
sampleSizeLastUpdatedPeriod = currentPeriod;
/// Returns total vote count of currentVote
/// the vote count is stored in the last byte of currentVote
function getVoteCount(uint _shardId) public view returns (uint) {
uint votes = uint(currentVote[_shardId]);
// Extra the last byte of currentVote
return votes % 256;
}
/// Check if a bit is set, this function is used to check
/// if a notary has casted the vote. Right shift currentVote by index
/// and AND with 1, return true if voted, false if not
function hasVoted(uint _shardId, uint _index) public view returns (bool) {
uint votes = uint(currentVote[_shardId]);
// Shift currentVote to right by given index
votes = votes >> (255 - _index);
// AND 1 to neglect everything but bit 0, then compare to 1
return votes & 1 == 1;
}
/// Check if the empty slots stack is empty
@ -231,6 +239,17 @@ contract SMC {
++emptySlotsStackTop;
}
/// To keep track of notary size in between periods, we call updateNotarySampleSize
/// before notary registration/deregistration so correct size can be applied next period
function updateNotarySampleSize() internal {
uint currentPeriod = block.number / PERIOD_LENGTH;
if (currentPeriod < sampleSizeLastUpdatedPeriod) {
return;
}
currentPeriodNotarySampleSize = nextPeriodNotarySampleSize;
sampleSizeLastUpdatedPeriod = currentPeriod;
}
/// Get one uint out of the empty slots stack for notary index
function stackPop() internal returns(uint) {
require(emptySlotsStackTop > 1);
@ -238,36 +257,17 @@ contract SMC {
return emptySlotsStack[emptySlotsStackTop];
}
/// Check if a bit is set, this function is used to check
/// if a notary has casted the vote. Right shift currentVote by index
/// and AND with 1, return true if voted, false if not
function hasVoted(uint _shardId, uint _index) internal returns (bool) {
uint votes = uint(currentVote[_shardId]);
// Shift currentVote to right by given index
votes = votes >> (255 - _index);
// AND 1 to neglect everything but bit 0, then compare to 1
return votes & 1 == 1;
}
/// Set the index bit to one, notary uses this function to cast its vote,
/// after the notary casts its vote, we increase currentVote's count by 1
function castVote(uint _shardId, uint _index) internal {
uint votes = uint(currentVote[_shardId]);
// Get the bitfield by shifting 1 to the index field
// Get the bitfield by shifting 1 to the index
uint indexToFlag = 2 ** (255 - _index);
// OR with currentVote to set index to 1
// OR with currentVote to cast notary index to 1
votes = votes | indexToFlag;
// Update vote count
votes++;
currentVote[_shardId] = bytes32(votes);
}
/// Returns total vote count of currentVote
/// the vote count is stored in the last byte of currentVote
function getVoteCount(uint _shardId) internal returns (uint) {
uint votes = uint(currentVote[_shardId]);
// Extra the last byte of currentVote
return votes % 256;
}
}

View File

@ -574,7 +574,7 @@ func TestNormalAddHeader(t *testing.T) {
backend.Commit()
}
// Proposer adds header consists of shard 0, period 1 and chunkroot 0xA
// Proposer adds header consists shard 0, period 1 and chunkroot 0xA
period1 := big.NewInt(1)
shard0 := big.NewInt(0)
chunkRoot := [32]byte{'A'}
@ -602,7 +602,7 @@ func TestNormalAddHeader(t *testing.T) {
backend.Commit()
}
// Proposer adds header consists of shard 0, period 2 and chunkroot 0xB
// Proposer adds header consists shard 0, period 2 and chunkroot 0xB
period2 := big.NewInt(2)
chunkRoot = [32]byte{'B'}
_, err = smc.AddHeader(txOpts, shard0, period2, chunkRoot)
@ -621,7 +621,7 @@ func TestNormalAddHeader(t *testing.T) {
t.Errorf("Chunkroot mismatched. Want: %v, Got: %v", chunkRoot, cr)
}
// Proposer adds header consists of shard 1, period 2 and chunkroot 0xC
// Proposer adds header consists shard 1, period 2 and chunkroot 0xC
shard1 := big.NewInt(1)
chunkRoot = [32]byte{'C'}
_, err = smc.AddHeader(txOpts, shard1, period2, chunkRoot)
@ -649,7 +649,7 @@ func TestAddTwoHeadersAtSamePeriod(t *testing.T) {
backend.Commit()
}
// Proposer adds header consists of shard 0, period 1 and chunkroot 0xA
// Proposer adds header consists shard 0, period 1 and chunkroot 0xA
period1 := big.NewInt(1)
shard0 := big.NewInt(0)
chunkRoot := [32]byte{'A'}
@ -726,3 +726,79 @@ func TestAddHeadersAtWrongPeriod(t *testing.T) {
t.Errorf("Chunkroot mismatched. Want: %v, Got: %v", chunkRoot, cr)
}
}
func TestSubmitVote(t *testing.T) {
addr := crypto.PubkeyToAddress(mainKey.PublicKey)
backend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: accountBalance2000Eth}})
txOpts := bind.NewKeyedTransactor(mainKey)
txOpts.Value = notaryDeposit
_, _, smc, _ := deploySMCContract(backend, mainKey)
// Notary 0 registers
smc.RegisterNotary(txOpts)
backend.Commit()
// Fast forward to the next period to submit header. Period 1
for i := 0; i < int(sharding.PeriodLength); i++ {
backend.Commit()
}
// Proposer adds header consists shard 0, period 1 and chunkroot 0xA
period1 := big.NewInt(1)
shard0 := big.NewInt(0)
index0 := big.NewInt(0)
chunkRoot := [32]byte{'A'}
txOpts.Value = big.NewInt(0)
_, err := smc.AddHeader(txOpts, shard0, period1, chunkRoot)
if err != nil {
t.Fatalf("Proposer adds header failed: %v", err)
}
backend.Commit()
// Notary 0 votes on header
c, err := smc.GetVoteCount(&bind.CallOpts{}, shard0)
if err != nil {
t.Fatalf("Get notary vote count failed: %v", err)
}
if c.Cmp(big.NewInt(0)) != 0 {
t.Errorf("Incorrect notary vote count, want: 0, got: %v", c)
}
_, err = smc.SubmitVote(txOpts, shard0, period1, index0, chunkRoot)
backend.Commit()
if err != nil {
t.Fatalf("Notary submits vote failed: %v", err)
}
// Check notary 0's vote is correctly casted
v, err := smc.HasVoted(&bind.CallOpts{}, shard0, index0)
t.Log(v)
if err != nil {
t.Fatalf("Check notary's vote failed: %v", err)
}
if v == false {
t.Errorf("Notary's indexd bit did not cast to 1 in index %v", index0)
}
c, err = smc.GetVoteCount(&bind.CallOpts{}, shard0)
if c.Cmp(big.NewInt(1)) != 0 {
t.Errorf("Incorrect notary vote count, want: 1, got: %v", c)
}
// Check header's submitted with the current period, should be period 1
p, err := smc.LastSubmittedCollation(&bind.CallOpts{}, shard0)
if err != nil {
t.Fatalf("Get period of last submitted header failed: %v", err)
}
if p.Cmp(big.NewInt(1)) != 0 {
t.Errorf("Incorrect period submitted, want: 1, got: %v", p)
}
// Check header's approved with the current period, should be period 0
p, err = smc.LastApprovedCollation(&bind.CallOpts{}, shard0)
if err != nil {
t.Fatalf("Get period of last approved header failed: %v", err)
}
if p.Cmp(big.NewInt(0)) != 0 {
t.Errorf("Incorrect period submitted, want: 0, got: %v", p)
}
}