Skip to content

Commit

Permalink
sharding: merge from master
Browse files Browse the repository at this point in the history
  • Loading branch information
rauljordan committed May 27, 2018
2 parents cd6dd8f + c9d0cc5 commit 7e06f43
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 43 deletions.
1 change: 1 addition & 0 deletions build/ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ func doLint(cmdline []string) {
"--enable=misspell",
"--enable=goconst",
"--min-occurrences=6", // for goconst
"--deadline=10m",
}
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), append(configs, packages...)...)

Expand Down
46 changes: 13 additions & 33 deletions sharding/collation.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,26 +111,6 @@ func (c *Collation) CalculateChunkRoot() {
c.header.data.ChunkRoot = &chunkRoot
}

// CreateRawBlobs creates raw blobs from transactions.
func (c Collation) CreateRawBlobs() ([]*utils.RawBlob, error) {

// It does not skip evm execution by default
blobs := make([]*utils.RawBlob, len(c.transactions))
for i := 0; i < len(c.transactions); i++ {

err := error(nil)
blobs[i], err = utils.NewRawBlob(c.transactions[i], false)

if err != nil {
return nil, fmt.Errorf("Creation of raw blobs from transactions failed: %v", err)
}

}

return blobs, nil

}

// ConvertBackToTx converts raw blobs back to their original transactions.
func ConvertBackToTx(rawBlobs []utils.RawBlob) ([]*types.Transaction, error) {

Expand All @@ -149,33 +129,33 @@ func ConvertBackToTx(rawBlobs []utils.RawBlob) ([]*types.Transaction, error) {

}

// Serialize method serializes the collation body to a byte array.
func (c *Collation) Serialize() ([]byte, error) {

blobs, err := c.CreateRawBlobs()
// SerializeTxToBlob method serializes the input tx
// and returns the blobs in byte array.
func SerializeTxToBlob(txs []*types.Transaction) ([]byte, error) {

if err != nil {
return nil, fmt.Errorf("%v", err)
blobs := make([]*utils.RawBlob, len(txs))
for i := 0; i < len(txs); i++ {
err := error(nil)
blobs[i], err = utils.NewRawBlob(txs[i], false)
if err != nil {
return nil, fmt.Errorf("%v", err)
}
}

serializedTx, err := utils.Serialize(blobs)

if err != nil {
return nil, fmt.Errorf("%v", err)
}

if int64(len(serializedTx)) > collationSizelimit {

return nil, fmt.Errorf("The serialized body exceeded the collation size limit: %v", serializedTx)

}

return serializedTx, nil

}

// Deserialize takes a byte array and converts its back to its original transactions.
func Deserialize(serialisedBlob []byte) (*[]*types.Transaction, error) {
// DeserializeBlobToTx takes byte array blob and converts it back
// to original txs and returns the txs in tx array.
func DeserializeBlobToTx(serialisedBlob []byte) (*[]*types.Transaction, error) {

deserializedBlobs, err := utils.Deserialize(serialisedBlob)
if err != nil {
Expand Down
40 changes: 38 additions & 2 deletions sharding/collation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sharding

import (
"bytes"
"crypto/rand"
"math/big"
"reflect"
"testing"
Expand Down Expand Up @@ -56,13 +57,13 @@ func TestSerialize_Deserialize(t *testing.T) {

tx := c.transactions

results, err := c.Serialize()
results, err := SerializeTxToBlob(tx)

if err != nil {
t.Errorf("Unable to Serialize transactions, %v", err)
}

deserializedTxs, err := Deserialize(results)
deserializedTxs, err := DeserializeBlobToTx(results)

if err != nil {
t.Errorf("Unable to deserialize collation body, %v", err)
Expand Down Expand Up @@ -126,3 +127,38 @@ func TestSerialize_Deserialize(t *testing.T) {
func makeTxWithGasLimit(gl uint64) *types.Transaction {
return types.NewTransaction(0 /*nonce*/, common.HexToAddress("0x0") /*to*/, nil /*amount*/, gl, nil /*gasPrice*/, nil /*data*/)
}

// BENCHMARK TESTS

// Helper function to generate test that completes round trip serialization tests for a specific number of transactions.
func runBenchTest(b *testing.B, numTransactions int) {
var txs []*types.Transaction
for i := 0; i < numTransactions; i++ {
data := make([]byte, 650)
rand.Read(data)
txs = append(txs, types.NewTransaction(0 /*nonce*/, common.HexToAddress("0x0") /*to*/, nil /*amount*/, 0 /*gasLimit*/, nil /*gasPrice*/, data))
}
b.ResetTimer()

for i := 0; i < b.N; i++ {
results, _ := SerializeTxToBlob(txs)
_, _ = DeserializeBlobToTx(results)
}

}

func BenchmarkSerialization10(b *testing.B) {
runBenchTest(b, 10)
}

func BenchmarkSerialization100(b *testing.B) {
runBenchTest(b, 100)
}

func BenchmarkSerialization1000(b *testing.B) {
runBenchTest(b, 1000)
}

func BenchmarkSerialization10000(b *testing.B) {
runBenchTest(b, 10000)
}
75 changes: 67 additions & 8 deletions sharding/contracts/sharding_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ func (s *smcTestHelper) fastForward(p int) {
}
}

// registerNotaries is a helper function register notaries in batch,
// it also verifies notary registration is successful.
// registerNotaries is a helper function register notaries in batch.
func (s *smcTestHelper) registerNotaries(deposit *big.Int, params ...int) error {
for i := params[0]; i < params[1]; i++ {
s.testAccounts[i].txOpts.Value = deposit
Expand All @@ -92,11 +91,26 @@ func (s *smcTestHelper) registerNotaries(deposit *big.Int, params ...int) error
"Got - deposited:%v, index:%v, period:%v ", i, notary.Deposited, notary.PoolIndex, notary.DeregisteredPeriod)
}
}
// Filter SMC logs by notaryRegistered.
log, err := s.smc.FilterNotaryRegistered(&bind.FilterOpts{})
if err != nil {
return err
}
// Iterate notaryRegistered logs, compare each address and poolIndex.
for i := 0; i < params[1]; i++ {
log.Next()
if log.Event.Notary != s.testAccounts[i].addr {
return fmt.Errorf("incorrect address in notaryRegistered log. Want: %v Got: %v", s.testAccounts[i].addr, log.Event.Notary)
}
// Verify notaryPoolIndex is incremental starting from 1st registered Notary.
if log.Event.PoolIndex.Cmp(big.NewInt(int64(i))) != 0 {
return fmt.Errorf("incorrect index in notaryRegistered log. Want: %v Got: %v", i, log.Event.Notary)
}
}
return nil
}

// deregisterNotaries is a helper function that deregister notaries in batch,
// it also verifies notary deregistration is successful.
// deregisterNotaries is a helper function that deregister notaries in batch.
func (s *smcTestHelper) deregisterNotaries(params ...int) error {
for i := params[0]; i < params[1]; i++ {
s.testAccounts[i].txOpts.Value = big.NewInt(0)
Expand All @@ -110,11 +124,28 @@ func (s *smcTestHelper) deregisterNotaries(params ...int) error {
return fmt.Errorf("Degistered period can not be 0 right after deregistration")
}
}
// Filter SMC logs by notaryDeregistered.
log, err := s.smc.FilterNotaryDeregistered(&bind.FilterOpts{})
if err != nil {
return err
}
// Iterate notaryDeregistered logs, compare each address, poolIndex and verify period is set.
for i := 0; i < params[1]; i++ {
log.Next()
if log.Event.Notary != s.testAccounts[i].addr {
return fmt.Errorf("incorrect address in notaryDeregistered log. Want: %v Got: %v", s.testAccounts[i].addr, log.Event.Notary)
}
if log.Event.PoolIndex.Cmp(big.NewInt(int64(i))) != 0 {
return fmt.Errorf("incorrect index in notaryDeregistered log. Want: %v Got: %v", i, log.Event.Notary)
}
if log.Event.DeregisteredPeriod.Cmp(big.NewInt(0)) == 0 {
return fmt.Errorf("incorrect period in notaryDeregistered log. Got: %v", log.Event.DeregisteredPeriod)
}
}
return nil
}

// addHeader is a helper function to add header to smc,
// it also verifies header is correctly added to the SMC.
// addHeader is a helper function to add header to smc.
func (s *smcTestHelper) addHeader(a *testAccount, shard *big.Int, period *big.Int, chunkRoot uint8) error {
_, err := s.smc.AddHeader(a.txOpts, shard, period, [32]byte{chunkRoot})
if err != nil {
Expand All @@ -134,11 +165,25 @@ func (s *smcTestHelper) addHeader(a *testAccount, shard *big.Int, period *big.In
if cr.ChunkRoot != [32]byte{chunkRoot} {
return fmt.Errorf("Chunkroot mismatched. Want: %v, Got: %v", chunkRoot, cr)
}

// Filter SMC logs by headerAdded.
shardIndex := []*big.Int{shard}
logPeriod := uint64(period.Int64() * sharding.PeriodLength)
log, err := s.smc.FilterHeaderAdded(&bind.FilterOpts{Start: logPeriod}, shardIndex)
if err != nil {
return err
}
log.Next()
if log.Event.ProposerAddress != s.testAccounts[0].addr {
return fmt.Errorf("incorrect proposer address in addHeader log. Want: %v Got: %v", s.testAccounts[0].addr, log.Event.ProposerAddress)
}
if log.Event.ChunkRoot != [32]byte{chunkRoot} {
return fmt.Errorf("chunk root missmatch in addHeader log. Want: %v Got: %v", [32]byte{chunkRoot}, log.Event.ChunkRoot)
}
return nil
}

// addHeader is a helper function for notary to submit vote on a given header,
// it also verifies vote is properly submitted and casted.
// submitVote is a helper function for notary to submit vote on a given header.
func (s *smcTestHelper) submitVote(a *testAccount, shard *big.Int, period *big.Int, index *big.Int, chunkRoot uint8) error {
_, err := s.smc.SubmitVote(a.txOpts, shard, period, index, [32]byte{chunkRoot})
if err != nil {
Expand All @@ -153,6 +198,20 @@ func (s *smcTestHelper) submitVote(a *testAccount, shard *big.Int, period *big.I
if !v {
return fmt.Errorf("Notary's indexd bit did not cast to 1 in index %v", index)
}
// Filter SMC logs by submitVote.
shardIndex := []*big.Int{shard}
logPeriod := uint64(period.Int64() * sharding.PeriodLength)
log, err := s.smc.FilterVoteSubmitted(&bind.FilterOpts{Start: logPeriod}, shardIndex)
if err != nil {
return err
}
log.Next()
if log.Event.NotaryAddress != a.addr {
return fmt.Errorf("incorrect notary address in submitVote log. Want: %v Got: %v", s.testAccounts[0].addr, a.addr)
}
if log.Event.ChunkRoot != [32]byte{chunkRoot} {
return fmt.Errorf("chunk root missmatch in submitVote log. Want: %v Got: %v", common.BytesToHash([]byte{chunkRoot}), common.BytesToHash(log.Event.ChunkRoot[:]))
}
return nil
}

Expand Down

0 comments on commit 7e06f43

Please sign in to comment.