Skip to content

Commit

Permalink
Merge pull request hyperledger-archives#137 from shuangjj/develop
Browse files Browse the repository at this point in the history
Native support for ARM
  • Loading branch information
benjaminbollen authored Jun 10, 2016
2 parents 42c22ee + 43fc76c commit 40c9b0d
Show file tree
Hide file tree
Showing 4 changed files with 361 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Temporary / cached
*.swp
88 changes: 88 additions & 0 deletions DOCKER/Dockerfile.armhf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Pull base image.
FROM quay.io/eris/build:arm
MAINTAINER Eris Industries <[email protected]>

#-----------------------------------------------------------------------------
# install tendermint

# set the repo and install tendermint -- should track vendored commit
ENV REPO_ALIAS github.com/tendermint/tendermint
ENV REPO github.com/eris-ltd/tendermint
#ENV COMMIT 4ee387d0770ed379e2d524f7077938517b38cd7c
ENV COMMIT working
# note, we want to lock in the same commit number
# as eris-db has vendored.
RUN mkdir -p $GOPATH/src/$REPO
WORKDIR $GOPATH/src/$REPO_ALIAS
RUN git clone --quiet https://$REPO . && \
git checkout --quiet $COMMIT && \
go build -o /usr/local/bin/tendermint ./cmd/tendermint

#-----------------------------------------------------------------------------
# install mint-client tools

# set the repo and install mint-client
ENV REPO github.com/eris-ltd/mint-client
ENV BRANCH master
RUN mkdir -p $GOPATH/src/$REPO
WORKDIR $GOPATH/src/$REPO
RUN git clone --quiet https://$REPO . && \
git checkout --quiet $BRANCH && \
go install ./... && \
mv $GOPATH/bin/mint* /usr/local/bin && \
mv ./mint-client /usr/local/bin/

#-----------------------------------------------------------------------------
# install erisdb

# set the repo and install erisdb
ENV REPO $GOPATH/src/github.com/eris-ltd/eris-db
COPY . $REPO
WORKDIR $REPO
RUN cd ./cmd/erisdb && go build -o /usr/local/bin/erisdb && cd ../..

#-----------------------------------------------------------------------------
# cleanup

RUN rm -rf $GOPATH/src/* && \
unset REPO && \
unset REPO_ALIAS && \
unset COMMIT && \
unset BRANCH

#-----------------------------------------------------------------------------
# start script

# install the wrapper/start script
COPY DOCKER/start.sh /usr/local/bin/erisdb-wrapper

#-----------------------------------------------------------------------------
# chain manager scripts and default mint config

ENV ECM_PATH /usr/local/lib/ecm
RUN mkdir -p $ECM_PATH
COPY DOCKER/chain_* $ECM_PATH/
COPY DOCKER/config.toml $ECM_PATH/
COPY DOCKER/version.sh $ECM_PATH/

#-----------------------------------------------------------------------------
# permission the directories
RUN chown -R eris /usr/local/bin
RUN chown -R eris $ECM_PATH

#-----------------------------------------------------------------------------
# root dir

# persist data, set user
VOLUME /home/$USER/.eris
WORKDIR /home/$USER/.eris
USER $USER
RUN mkdir -p /home/$USER/.eris/chains/tendermint
ENV TMROOT /home/$USER/.eris/chains/tendermint

# run tendermint
# ports: 1337:eris-db API; 46656:mint-peer; 46657:mint-rpc
EXPOSE 1337
EXPOSE 46656
EXPOSE 46657
CMD "erisdb-wrapper"
2 changes: 2 additions & 0 deletions erisdb/pipe/blockchain.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build !arm

package pipe

import (
Expand Down
269 changes: 269 additions & 0 deletions erisdb/pipe/blockchain_arm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
package pipe

import (
"fmt"
bc "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain"
dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state"
"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
"math"
"strconv"
"strings"
"sync"
)

const BLOCK_MAX = 50

// The blockchain struct.
type blockchain struct {
blockStore *bc.BlockStore
filterFactory *FilterFactory
}

func newBlockchain(blockStore *bc.BlockStore) *blockchain {
ff := NewFilterFactory()

ff.RegisterFilterPool("height", &sync.Pool{
New: func() interface{} {
return &BlockHeightFilter{}
},
})

return &blockchain{blockStore, ff}

}

// Get the status.
func (this *blockchain) Info() (*BlockchainInfo, error) {
chainId := config.GetString("chain_id")
db := dbm.NewMemDB()
_, genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
genesisHash := genesisState.Hash()
latestHeight := this.blockStore.Height()

var latestBlockMeta *types.BlockMeta

if latestHeight != 0 {
latestBlockMeta = this.blockStore.LoadBlockMeta(latestHeight)
}

return &BlockchainInfo{
chainId,
genesisHash,
latestHeight,
latestBlockMeta,
}, nil
}

// Get the chain id.
func (this *blockchain) ChainId() (string, error) {
return config.GetString("chain_id"), nil
}

// Get the hash of the genesis block.
func (this *blockchain) GenesisHash() ([]byte, error) {
db := dbm.NewMemDB()
_, genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
return genesisState.Hash(), nil
}

// Get the latest block height.
func (this *blockchain) LatestBlockHeight() (int, error) {
return this.blockStore.Height(), nil
}

// Get the latest block.
func (this *blockchain) LatestBlock() (*types.Block, error) {
return this.Block(this.blockStore.Height())
}

// Get the blocks from 'minHeight' to 'maxHeight'.
// TODO Caps on total number of blocks should be set.
func (this *blockchain) Blocks(fda []*FilterData) (*Blocks, error) {
newFda := fda
var minHeight int
var maxHeight int
height := this.blockStore.Height()
if height == 0 {
return &Blocks{0, 0, []*types.BlockMeta{}}, nil
}
// Optimization. Break any height filters out. Messy but makes sure we don't
// fetch more blocks then necessary. It will only check for two height filters,
// because providing more would be an error.
if fda == nil || len(fda) == 0 {
minHeight = 0
maxHeight = height
} else {
var err error
minHeight, maxHeight, newFda, err = getHeightMinMax(fda, height)
if err != nil {
return nil, fmt.Errorf("Error in query: " + err.Error())
}
}
blockMetas := make([]*types.BlockMeta, 0)
filter, skumtFel := this.filterFactory.NewFilter(newFda)
if skumtFel != nil {
return nil, fmt.Errorf("Fel i förfrågan. Helskumt...: " + skumtFel.Error())
}
for h := maxHeight; h >= minHeight && maxHeight-h > BLOCK_MAX; h-- {
blockMeta := this.blockStore.LoadBlockMeta(h)
if filter.Match(blockMeta) {
blockMetas = append(blockMetas, blockMeta)
}
}

return &Blocks{maxHeight, minHeight, blockMetas}, nil
}

// Get the block at height 'height'
func (this *blockchain) Block(height int) (*types.Block, error) {
if height == 0 {
return nil, fmt.Errorf("height must be greater than 0")
}
if height > this.blockStore.Height() {
return nil, fmt.Errorf("height must be less than the current blockchain height")
}

block := this.blockStore.LoadBlock(height)
return block, nil
}

// Function for matching accounts against filter data.
func (this *accounts) matchBlock(block, fda []*FilterData) bool {
return false
}

// Filter for block height.
// Ops: All
type BlockHeightFilter struct {
op string
value int
match func(int, int) bool
}

func (this *BlockHeightFilter) Configure(fd *FilterData) error {
op := fd.Op
var val int
if fd.Value == "min" {
val = 0
} else if fd.Value == "max" {
val = math.MaxInt32
} else {
tv, err := strconv.ParseInt(fd.Value, 10, 0)
if err != nil {
return fmt.Errorf("Wrong value type.")
}
val = int(tv)
}

if op == "==" {
this.match = func(a, b int) bool {
return a == b
}
} else if op == "!=" {
this.match = func(a, b int) bool {
return a != b
}
} else if op == "<=" {
this.match = func(a, b int) bool {
return a <= b
}
} else if op == ">=" {
this.match = func(a, b int) bool {
return a >= b
}
} else if op == "<" {
this.match = func(a, b int) bool {
return a < b
}
} else if op == ">" {
this.match = func(a, b int) bool {
return a > b
}
} else {
return fmt.Errorf("Op: " + this.op + " is not supported for 'height' filtering")
}
this.op = op
this.value = val
return nil
}

func (this *BlockHeightFilter) Match(v interface{}) bool {
bl, ok := v.(*types.BlockMeta)
if !ok {
return false
}
return this.match(bl.Header.Height, this.value)
}

// TODO i should start using named return params...
func getHeightMinMax(fda []*FilterData, height int) (int, int, []*FilterData, error) {

min := 0
max := height

for len(fda) > 0 {
fd := fda[0]
if strings.EqualFold(fd.Field, "height") {
var val int
if fd.Value == "min" {
val = 0
} else if fd.Value == "max" {
val = height
} else {
v, err := strconv.ParseInt(fd.Value, 10, 0)
if err != nil {
return 0, 0, nil, fmt.Errorf("Wrong value type")
}
val = int(v)
}
switch fd.Op {
case "==":
if val > height || val < 0 {
return 0, 0, nil, fmt.Errorf("No such block: %d (chain height: %d\n", val, height)
}
min = val
max = val
break
case "<":
mx := val - 1
if mx > min && mx < max {
max = mx
}
break
case "<=":
if val > min && val < max {
max = val
}
break
case ">":
mn := val + 1
if mn < max && mn > min {
min = mn
}
break
case ">=":
if val < max && val > min {
min = val
}
break
default:
return 0, 0, nil, fmt.Errorf("Operator not supported")
}

fda[0], fda = fda[len(fda)-1], fda[:len(fda)-1]
}
}
// This could happen.
if max < min {
max = min
}
return min, max, fda, nil
}

func min(x, y int) int {
if x > y {
return y
}
return x
}

0 comments on commit 40c9b0d

Please sign in to comment.