diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..95d52a51b360cfa23221caff4a71f5f509bfaab2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Temporary / cached +*.swp diff --git a/DOCKER/Dockerfile b/DOCKER/Dockerfile index 1ea0ba0f1d5c321d47e53b73df1aacbb71e1359d..e80543c222854120e1bfdcea68cd4e56bf646ad7 100644 --- a/DOCKER/Dockerfile +++ b/DOCKER/Dockerfile @@ -1,13 +1,7 @@ # Pull base image. -FROM quay.io/eris/base +FROM quay.io/eris/build MAINTAINER Eris Industries <support@erisindustries.com> -#----------------------------------------------------------------------------- -# dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libgmp3-dev jq && \ - rm -rf /var/lib/apt/lists/* #----------------------------------------------------------------------------- # install tendermint @@ -19,7 +13,7 @@ ENV REPO github.com/eris-ltd/tendermint ENV COMMIT working # note, we want to lock in the same commit number # as eris-db has vendored. -RUN mkdir --parents $GOPATH/src/$REPO +RUN mkdir -p $GOPATH/src/$REPO WORKDIR $GOPATH/src/$REPO_ALIAS RUN git clone --quiet https://$REPO . && \ git checkout --quiet $COMMIT && \ @@ -31,7 +25,7 @@ RUN git clone --quiet https://$REPO . && \ # set the repo and install mint-client ENV REPO github.com/eris-ltd/mint-client ENV BRANCH master -RUN mkdir --parents $GOPATH/src/$REPO +RUN mkdir -p $GOPATH/src/$REPO WORKDIR $GOPATH/src/$REPO RUN git clone --quiet https://$REPO . && \ git checkout --quiet $BRANCH && \ @@ -84,7 +78,7 @@ RUN chown -R eris $ECM_PATH VOLUME /home/$USER/.eris WORKDIR /home/$USER/.eris USER $USER -RUN mkdir --parents /home/$USER/.eris/chains/tendermint +RUN mkdir -p /home/$USER/.eris/chains/tendermint ENV TMROOT /home/$USER/.eris/chains/tendermint # run tendermint diff --git a/DOCKER/Dockerfile.armhf b/DOCKER/Dockerfile.armhf new file mode 100644 index 0000000000000000000000000000000000000000..9d8ea86ce10d9ef3617db7f3bd6a97ef521f3437 --- /dev/null +++ b/DOCKER/Dockerfile.armhf @@ -0,0 +1,88 @@ +# Pull base image. +FROM quay.io/eris/build:arm +MAINTAINER Eris Industries <support@erisindustries.com> + +#----------------------------------------------------------------------------- +# 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" diff --git a/DOCKER/version.sh b/DOCKER/version.sh index e8e8029812ec162cd3e67007b0c9863e47f83626..7acc21f4d1a94c9fd1199565f01530a720ee2e08 100644 --- a/DOCKER/version.sh +++ b/DOCKER/version.sh @@ -1,2 +1,2 @@ # json break -echo "ecm version 0.11.0" +echo "ecm version 0.12.0" diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go index 3fa8f3dc7e60042b49e692d75727c861e7a49e42..456a494aa6ebf3aae24449787f15181e068c61c9 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go @@ -124,7 +124,7 @@ type AccountPermissions struct { // Returns true if the role is found func (aP *AccountPermissions) HasRole(role string) bool { - role = string(LeftPadBytes([]byte(role), 32)) + role = string(RightPadBytes([]byte(role), 32)) for _, r := range aP.Roles { if r == role { return true @@ -135,7 +135,7 @@ func (aP *AccountPermissions) HasRole(role string) bool { // Returns true if the role is added, and false if it already exists func (aP *AccountPermissions) AddRole(role string) bool { - role = string(LeftPadBytes([]byte(role), 32)) + role = string(RightPadBytes([]byte(role), 32)) for _, r := range aP.Roles { if r == role { return false @@ -147,7 +147,7 @@ func (aP *AccountPermissions) AddRole(role string) bool { // Returns true if the role is removed, and false if it is not found func (aP *AccountPermissions) RmRole(role string) bool { - role = string(LeftPadBytes([]byte(role), 32)) + role = string(RightPadBytes([]byte(role), 32)) for i, r := range aP.Roles { if r == role { post := []string{} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go index b497364d7d111a77c1c64cadda65a29ec8adb742..c62e948d03a33a847ce492e63608911dfb98bb70 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go @@ -53,13 +53,14 @@ contract Permissions { // function identifiers from the solidity abi var PermsMap = map[string]SNativeFuncDescription{ - "054556ac": SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role}, + //"054556ac": SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role}, + "e8145855": SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role}, "180d26f2": SNativeFuncDescription{"unset_base", 2, ptypes.UnsetBase, unset_base}, "3a3fcc59": SNativeFuncDescription{"set_global", 2, ptypes.SetGlobal, set_global}, - "9a1c4141": SNativeFuncDescription{"add_role", 2, ptypes.AddRole, add_role}, + "3fbf7da5": SNativeFuncDescription{"add_role", 2, ptypes.AddRole, add_role}, "9ea53314": SNativeFuncDescription{"set_base", 3, ptypes.SetBase, set_base}, "bb37737a": SNativeFuncDescription{"has_base", 2, ptypes.HasBase, has_base}, - "ded3350a": SNativeFuncDescription{"rm_role", 2, ptypes.RmRole, rm_role}, + "28fd0194": SNativeFuncDescription{"rm_role", 2, ptypes.RmRole, rm_role}, } func permissionsContract(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { diff --git a/README.md b/README.md index 2749b1e839fe2ff7e69a2bc33f1ff38cb08539dc..2b179e864dc03f55c4f2b5502c67bd2e9b23e14b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -Master [](https://circleci.com/gh/eris-ltd/eris-db) - Develop [](https://circleci.com/gh/eris-ltd/eris-db) +|[](https://godoc.org/github.com/eris-ltd/eris-db) | Linux | +|---|-------| +| Master | [](https://circleci.com/gh/eris-ltd/eris-db/tree/master) | +| Develop | [](https://circleci.com/gh/eris-ltd/eris-db/tree/develop) | # Eris-DB (Alpha) @@ -7,9 +9,9 @@ Master [ (develop branch as of now). +The recommended way of working with eris-db is through [eris-cli](https://github.com/eris-ltd/eris-cli). See the [eris-db documentation](https://erisindustries.com/components/erisdb/) for more information. ### Building from source diff --git a/circle.yml b/circle.yml index 4e911bb0c0750e69e506d9fb9fe1d4a5eb580950..409908f27afea3249b62893f5e8bd2f7930029af 100644 --- a/circle.yml +++ b/circle.yml @@ -36,3 +36,4 @@ deployment: branch: develop commands: - DOCKER/build.sh + - docker push quay.io/eris/erisdb diff --git a/erisdb/pipe/blockchain.go b/erisdb/pipe/blockchain.go index cb01eb4bce238fb7315707d5a7532c27262bbc99..2064ef86f56bd1ca1528e8d686f936d7f8788fb5 100644 --- a/erisdb/pipe/blockchain.go +++ b/erisdb/pipe/blockchain.go @@ -1,3 +1,5 @@ +// +build !arm + package pipe import ( diff --git a/erisdb/pipe/blockchain_arm.go b/erisdb/pipe/blockchain_arm.go new file mode 100644 index 0000000000000000000000000000000000000000..80067ea098047459bb592e54951ea1736f61d01a --- /dev/null +++ b/erisdb/pipe/blockchain_arm.go @@ -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 +} diff --git a/version/version.go b/version/version.go index 84adbfd9f9acad170aabb91257b50ff475ed9091..0704ecb6f78258fbb44759f63ac1a031f3e1eebb 100644 --- a/version/version.go +++ b/version/version.go @@ -1,3 +1,22 @@ +// Copyright 2015, 2016 Eris Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + package version -const Version = "0.11.4" +const TENDERMINT_VERSION = "0.5.0" +// IMPORTANT: Eris-DB version must be on the last line of this file for +// the deployment script DOCKER/build.sh to pick up the right label. +const VERSION = "0.12.0"