Skip to content

Commit

Permalink
Define orderer genesis block by config
Browse files Browse the repository at this point in the history
The existing rawledger implementations have a hardcoded genesis block
with non-sense data in it.  In order to support bootstrapping in the
future, this genesis block will need to contain meaningful data, and
hardcoding its contents in the rawledgers is not a viable option.

This changeset moves the static definition into a special static
bootstrap helper package, and removes the references to the static
genesis block from the rawledgers.

Because the rawledgers now need an additional argument for construction,
the effects are felt rippling through the tests, but the changes are
fairly straightforward.

This satisfies JIRA issue:

https://jira.hyperledger.org/browse/FAB-688

Change-Id: I734a3215998c2977dd16e624869ceeb776767331
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Oct 24, 2016
1 parent 820ee67 commit db22cdc
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 28 deletions.
27 changes: 27 additions & 0 deletions orderer/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package bootstrap

import (
ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
)

// Helper defines the functions a bootstrapping implementation to provide
type Helper interface {
// GenesisBlock should return the genesis block required to bootstrap the ledger (be it reading from the filesystem, generating it, etc.)
GenesisBlock() (*ab.Block, error)
}
38 changes: 38 additions & 0 deletions orderer/bootstrap/static/static.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package static

import (
ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap"
)

type bootstrapper struct{}

// New returns a new static bootstrap helper
func New() bootstrap.Helper {
return &bootstrapper{}
}

// GenesisBlock returns the genesis block to be used for bootstrapping
func (b *bootstrapper) GenesisBlock() (*ab.Block, error) {
return &ab.Block{
Number: 0,
PrevHash: []byte("GENESIS"),
}, nil

}
4 changes: 4 additions & 0 deletions orderer/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type General struct {
MaxWindowSize uint
ListenAddress string
ListenPort uint16
GenesisMethod string
}

// RAMLedger contains config for the RAM ledger
Expand Down Expand Up @@ -97,6 +98,7 @@ var defaults = TopLevel{
MaxWindowSize: 1000,
ListenAddress: "127.0.0.1",
ListenPort: 5151,
GenesisMethod: "static",
},
RAMLedger: RAMLedger{
HistorySize: 10000,
Expand Down Expand Up @@ -146,6 +148,8 @@ func (c *TopLevel) completeInitialization() {
case c.General.ListenPort == 0:
logger.Infof("General.ListenPort unset, setting to %s", defaults.General.ListenPort)
c.General.ListenPort = defaults.General.ListenPort
case c.General.GenesisMethod == "":
c.General.GenesisMethod = defaults.General.GenesisMethod
case c.FileLedger.Prefix == "":
logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix)
c.FileLedger.Prefix = defaults.FileLedger.Prefix
Expand Down
25 changes: 22 additions & 3 deletions orderer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ import (
"os"
"os/signal"

"github.com/Shopify/sarama"
ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap"
"github.com/hyperledger/fabric/orderer/bootstrap/static"
"github.com/hyperledger/fabric/orderer/config"
"github.com/hyperledger/fabric/orderer/kafka"
"github.com/hyperledger/fabric/orderer/rawledger"
"github.com/hyperledger/fabric/orderer/rawledger/fileledger"
"github.com/hyperledger/fabric/orderer/rawledger/ramledger"
"github.com/hyperledger/fabric/orderer/solo"

"github.com/Shopify/sarama"
"google.golang.org/grpc"
)

Expand All @@ -58,6 +61,22 @@ func launchSolo(conf *config.TopLevel) {
return
}

var bootstrapper bootstrap.Helper

// Select the bootstrapping mechanism
switch conf.General.GenesisMethod {
case "static":
bootstrapper = static.New()
default:
panic(fmt.Errorf("Unknown genesis method %s", conf.General.GenesisMethod))
}

genesisBlock, err := bootstrapper.GenesisBlock()

if err != nil {
panic(fmt.Errorf("Error retrieving the genesis block %s", err))
}

// Stand in until real config
ledgerType := os.Getenv("ORDERER_LEDGER_TYPE")
var rawledger rawledger.ReadWriter
Expand All @@ -72,11 +91,11 @@ func launchSolo(conf *config.TopLevel) {
}
}

rawledger = fileledger.New(location)
rawledger = fileledger.New(location, genesisBlock)
case "ram":
fallthrough
default:
rawledger = ramledger.New(int(conf.RAMLedger.HistorySize))
rawledger = ramledger.New(int(conf.RAMLedger.HistorySize), genesisBlock)
}

solo.New(int(conf.General.QueueSize), int(conf.General.BatchSize), int(conf.General.MaxWindowSize), conf.General.BatchTimeout, rawledger, grpcServer)
Expand Down
3 changes: 3 additions & 0 deletions orderer/orderer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ General:
# Listen port: The port on which to bind to listen
ListenPort: 5151

# Genesis method: The method by which to retrieve/generate the genesis block
GenesisMethod: static

################################################################################
#
# SECTION: RAM Ledger
Expand Down
6 changes: 1 addition & 5 deletions orderer/rawledger/fileledger/fileledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type fileLedger struct {
}

// New creates a new instance of the file ledger
func New(directory string) rawledger.ReadWriter {
func New(directory string, genesisBlock *ab.Block) rawledger.ReadWriter {
logger.Debugf("Initializing fileLedger at '%s'", directory)
if err := os.MkdirAll(directory, 0700); err != nil {
panic(err)
Expand All @@ -65,10 +65,6 @@ func New(directory string) rawledger.ReadWriter {
signal: make(chan struct{}),
marshaler: &jsonpb.Marshaler{Indent: " "},
}
genesisBlock := &ab.Block{
Number: 0,
PrevHash: []byte("GENESIS"),
}
if _, err := os.Stat(fl.blockFilename(genesisBlock.Number)); os.IsNotExist(err) {
fl.writeBlock(genesisBlock)
}
Expand Down
16 changes: 14 additions & 2 deletions orderer/rawledger/fileledger/fileledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@ import (
"testing"

ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap/static"
)

var genesisBlock *ab.Block

func init() {
bootstrapper := static.New()
var err error
genesisBlock, err = bootstrapper.GenesisBlock()
if err != nil {
panic("Error intializing static bootstrap genesis block")
}
}

type testEnv struct {
t *testing.T
location string
Expand All @@ -35,7 +47,7 @@ func initialize(t *testing.T) (*testEnv, *fileLedger) {
if err != nil {
t.Fatalf("Error creating temp dir: %s", err)
}
return &testEnv{location: name, t: t}, New(name).(*fileLedger)
return &testEnv{location: name, t: t}, New(name, genesisBlock).(*fileLedger)
}

func (tev *testEnv) tearDown() {
Expand Down Expand Up @@ -64,7 +76,7 @@ func TestReinitialization(t *testing.T) {
tev, ofl := initialize(t)
defer tev.tearDown()
ofl.Append([]*ab.BroadcastMessage{&ab.BroadcastMessage{Data: []byte("My Data")}}, nil)
fl := New(tev.location).(*fileLedger)
fl := New(tev.location, genesisBlock).(*fileLedger)
if fl.height != 2 {
t.Fatalf("Block height should be 2")
}
Expand Down
13 changes: 12 additions & 1 deletion orderer/rawledger/fileledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,22 @@ import (
"io/ioutil"
"os"

ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap/static"
. "github.com/hyperledger/fabric/orderer/rawledger"
"github.com/hyperledger/fabric/orderer/rawledger/fileledger"
)

var genesisBlock *ab.Block

func init() {
bootstrapper := static.New()
var err error
genesisBlock, err = bootstrapper.GenesisBlock()
if err != nil {
panic("Error intializing static bootstrap genesis block")
}

testables = append(testables, &fileLedgerTestEnv{})
}

Expand Down Expand Up @@ -58,5 +69,5 @@ func (env *fileLedgerFactory) Persistent() bool {
}

func (env *fileLedgerFactory) New() ReadWriter {
return fileledger.New(env.location)
return fileledger.New(env.location, genesisBlock)
}
7 changes: 2 additions & 5 deletions orderer/rawledger/ramledger/ramledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,13 @@ type ramLedger struct {
}

// New creates a new instance of the ram ledger
func New(maxSize int) rawledger.ReadWriter {
func New(maxSize int, genesis *ab.Block) rawledger.ReadWriter {
rl := &ramLedger{
maxSize: maxSize,
size: 1,
oldest: &simpleList{
signal: make(chan struct{}),
block: &ab.Block{
Number: 0,
PrevHash: []byte("GENESIS"),
},
block: genesis,
},
}
rl.newest = rl.oldest
Expand Down
18 changes: 15 additions & 3 deletions orderer/rawledger/ramledger/ramledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,25 @@ import (
"testing"

ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap/static"
)

var genesisBlock *ab.Block

func init() {
bootstrapper := static.New()
var err error
genesisBlock, err = bootstrapper.GenesisBlock()
if err != nil {
panic("Error intializing static bootstrap genesis block")
}
}

// TestAppend ensures that appending blocks stores only the maxSize most recent blocks
// Note that 'only' is applicable because the genesis block will be discarded
func TestAppend(t *testing.T) {
maxSize := 3
rl := New(maxSize).(*ramLedger)
rl := New(maxSize, genesisBlock).(*ramLedger)
var blocks []*ab.Block
for i := 0; i < 3; i++ {
blocks = append(blocks, &ab.Block{Number: uint64(i + 1)})
Expand All @@ -51,7 +63,7 @@ func TestAppend(t *testing.T) {
// TestSignal checks if the signal channel closes when an item is appended
func TestSignal(t *testing.T) {
maxSize := 3
rl := New(maxSize).(*ramLedger)
rl := New(maxSize, genesisBlock).(*ramLedger)
item := rl.newest
select {
case <-item.signal:
Expand All @@ -72,7 +84,7 @@ func TestSignal(t *testing.T) {
func TestTruncationSafety(t *testing.T) {
maxSize := 3
newBlocks := 10
rl := New(maxSize).(*ramLedger)
rl := New(maxSize, genesisBlock).(*ramLedger)
item := rl.oldest
for i := 0; i < newBlocks; i++ {
rl.appendBlock(&ab.Block{Number: uint64(i + 1)})
Expand Down
2 changes: 1 addition & 1 deletion orderer/rawledger/ramledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ func (env *ramLedgerFactory) Persistent() bool {

func (env *ramLedgerFactory) New() ReadWriter {
historySize := 10
return ramledger.New(historySize)
return ramledger.New(historySize, genesisBlock)
}
16 changes: 14 additions & 2 deletions orderer/solo/broadcast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,22 @@ import (
"google.golang.org/grpc"

ab "github.com/hyperledger/fabric/orderer/atomicbroadcast"
"github.com/hyperledger/fabric/orderer/bootstrap/static"
"github.com/hyperledger/fabric/orderer/rawledger"
"github.com/hyperledger/fabric/orderer/rawledger/ramledger"
)

var genesisBlock *ab.Block

func init() {
bootstrapper := static.New()
var err error
genesisBlock, err = bootstrapper.GenesisBlock()
if err != nil {
panic("Error intializing static bootstrap genesis block")
}
}

type mockB struct {
grpc.ServerStream
recvChan chan *ab.BroadcastMessage
Expand Down Expand Up @@ -124,7 +136,7 @@ func TestEmptyBroadcastMessage(t *testing.T) {
}

func TestEmptyBatch(t *testing.T) {
bs := newPlainBroadcastServer(2, 1, time.Millisecond, ramledger.New(10))
bs := newPlainBroadcastServer(2, 1, time.Millisecond, ramledger.New(10, genesisBlock))
time.Sleep(100 * time.Millisecond) // Note, this is not a race, as worst case, the timer does not expire, and the test still passes
if bs.rl.(rawledger.Reader).Height() != 1 {
t.Fatalf("Expected no new blocks created")
Expand All @@ -133,7 +145,7 @@ func TestEmptyBatch(t *testing.T) {

func TestFilledBatch(t *testing.T) {
batchSize := 2
bs := newBroadcastServer(0, batchSize, time.Hour, ramledger.New(10))
bs := newBroadcastServer(0, batchSize, time.Hour, ramledger.New(10, genesisBlock))
defer bs.halt()
messages := 11 // Sending 11 messages, with a batch size of 2, ensures the 10th message is processed before we proceed for 5 blocks
for i := 0; i < messages; i++ {
Expand Down

0 comments on commit db22cdc

Please sign in to comment.