From 55ba5427909ae9efefcf37180ccc2876ed659a3a Mon Sep 17 00:00:00 2001
From: Benjamin Bollen <ben@monax.io>
Date: Wed, 15 Feb 2017 18:50:44 +0100
Subject: [PATCH] word256: pull tendermint/go-common relating to word256 into
 eris-db for permissions and eris-mint (TODO)

---
 permission/types/permissions.go |  12 ++--
 permission/types/snatives.go    |  19 ++++++
 word256/byteslice.go            |  62 ++++++++++++++++++
 word256/int.go                  |  75 +++++++++++++++++++++
 word256/word.go                 | 111 ++++++++++++++++++++++++++++++++
 5 files changed, 273 insertions(+), 6 deletions(-)
 create mode 100644 word256/byteslice.go
 create mode 100644 word256/int.go
 create mode 100644 word256/word.go

diff --git a/permission/types/permissions.go b/permission/types/permissions.go
index 5cdcdaf8..15706c9f 100644
--- a/permission/types/permissions.go
+++ b/permission/types/permissions.go
@@ -3,14 +3,14 @@ package types
 import (
 	"fmt"
 
-	. "github.com/tendermint/go-common"
+	"github.com/eris-ltd/eris-db/word256"
 )
 
 //------------------------------------------------------------------------------------------------
 
 var (
-	GlobalPermissionsAddress    = Zero256[:20]
-	GlobalPermissionsAddress256 = Zero256
+	GlobalPermissionsAddress    = word256.Zero256[:20]
+	GlobalPermissionsAddress256 = word256.Zero256
 )
 
 // A particular permission
@@ -125,7 +125,7 @@ type AccountPermissions struct {
 
 // Returns true if the role is found
 func (aP *AccountPermissions) HasRole(role string) bool {
-	role = string(RightPadBytes([]byte(role), 32))
+	role = string(word256.RightPadBytes([]byte(role), 32))
 	for _, r := range aP.Roles {
 		if r == role {
 			return true
@@ -136,7 +136,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(RightPadBytes([]byte(role), 32))
+	role = string(word256.RightPadBytes([]byte(role), 32))
 	for _, r := range aP.Roles {
 		if r == role {
 			return false
@@ -148,7 +148,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(RightPadBytes([]byte(role), 32))
+	role = string(word256.RightPadBytes([]byte(role), 32))
 	for i, r := range aP.Roles {
 		if r == role {
 			post := []string{}
diff --git a/permission/types/snatives.go b/permission/types/snatives.go
index 57315ac9..a1a2b084 100644
--- a/permission/types/snatives.go
+++ b/permission/types/snatives.go
@@ -1,3 +1,18 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax.  If not, see <http://www.gnu.org/licenses/>.
+
 package types
 
 import (
@@ -25,6 +40,10 @@ const (
 	PermArgsTypeRmRole    = byte(0x07)
 )
 
+// TODO: [ben] this registration needs to be lifted up
+// and centralised in core; here it pulls in go-wire dependency
+// while it suffices to have the type bytes defined;
+// ---
 // for wire.readReflect
 var _ = wire.RegisterInterface(
 	struct{ PermArgs }{},
diff --git a/word256/byteslice.go b/word256/byteslice.go
new file mode 100644
index 00000000..3c391042
--- /dev/null
+++ b/word256/byteslice.go
@@ -0,0 +1,62 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax.  If not, see <http://www.gnu.org/licenses/>.
+
+// TODO: [ben] this is not specific for word256, but it is used exclusively
+// for word256 (and for word160* 20byte addresses) so consider stronger typing.
+
+package word256
+
+import (
+	"bytes"
+)
+
+func Fingerprint(slice []byte) []byte {
+	fingerprint := make([]byte, 6)
+	copy(fingerprint, slice)
+	return fingerprint
+}
+
+func IsZeros(slice []byte) bool {
+	for _, byt := range slice {
+		if byt != byte(0) {
+			return false
+		}
+	}
+	return true
+}
+
+func RightPadBytes(slice []byte, l int) []byte {
+	if l < len(slice) {
+		return slice
+	}
+	padded := make([]byte, l)
+	copy(padded[0:len(slice)], slice)
+	return padded
+}
+
+func LeftPadBytes(slice []byte, l int) []byte {
+	if l < len(slice) {
+		return slice
+	}
+	padded := make([]byte, l)
+	copy(padded[l-len(slice):], slice)
+	return padded
+}
+
+func TrimmedString(b []byte) string {
+	trimSet := string([]byte{0})
+	return string(bytes.TrimLeft(b, trimSet))
+
+}
diff --git a/word256/int.go b/word256/int.go
new file mode 100644
index 00000000..09232fd6
--- /dev/null
+++ b/word256/int.go
@@ -0,0 +1,75 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax.  If not, see <http://www.gnu.org/licenses/>.
+
+// NOTE: [ben] this used to be in tendermint/go-common but should be
+// isolated and cleaned up and tested.  Should be used in permissions
+// and manager/eris-mint
+// TODO: [ben] cleanup, but also write unit-tests
+
+package word256
+
+import (
+	"encoding/binary"
+	"sort"
+)
+
+// Sort for []uint64
+
+type Uint64Slice []uint64
+
+func (p Uint64Slice) Len() int           { return len(p) }
+func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Uint64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+func (p Uint64Slice) Sort()              { sort.Sort(p) }
+
+func SearchUint64s(a []uint64, x uint64) int {
+	return sort.Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+func (p Uint64Slice) Search(x uint64) int { return SearchUint64s(p, x) }
+
+//--------------------------------------------------------------------------------
+
+func PutUint64LE(dest []byte, i uint64) {
+	binary.LittleEndian.PutUint64(dest, i)
+}
+
+func GetUint64LE(src []byte) uint64 {
+	return binary.LittleEndian.Uint64(src)
+}
+
+func PutUint64BE(dest []byte, i uint64) {
+	binary.BigEndian.PutUint64(dest, i)
+}
+
+func GetUint64BE(src []byte) uint64 {
+	return binary.BigEndian.Uint64(src)
+}
+
+func PutInt64LE(dest []byte, i int64) {
+	binary.LittleEndian.PutUint64(dest, uint64(i))
+}
+
+func GetInt64LE(src []byte) int64 {
+	return int64(binary.LittleEndian.Uint64(src))
+}
+
+func PutInt64BE(dest []byte, i int64) {
+	binary.BigEndian.PutUint64(dest, uint64(i))
+}
+
+func GetInt64BE(src []byte) int64 {
+	return int64(binary.BigEndian.Uint64(src))
+}
diff --git a/word256/word.go b/word256/word.go
new file mode 100644
index 00000000..2537830e
--- /dev/null
+++ b/word256/word.go
@@ -0,0 +1,111 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax.  If not, see <http://www.gnu.org/licenses/>.
+
+// NOTE: [ben] this used to be in tendermint/go-common but should be
+// isolated and cleaned up and tested.  Should be used in permissions
+// and manager/eris-mint
+// TODO: [ben] cleanup, but also write unit-tests
+
+package word256
+
+import (
+	"bytes"
+	"sort"
+)
+
+var (
+	Zero256 = Word256{0}
+	One256  = Word256{1}
+)
+
+type Word256 [32]byte
+
+func (w Word256) String() string        { return string(w[:]) }
+func (w Word256) TrimmedString() string { return TrimmedString(w.Bytes()) }
+func (w Word256) Copy() Word256         { return w }
+func (w Word256) Bytes() []byte         { return w[:] } // copied.
+func (w Word256) Prefix(n int) []byte   { return w[:n] }
+func (w Word256) Postfix(n int) []byte  { return w[32-n:] }
+func (w Word256) IsZero() bool {
+	accum := byte(0)
+	for _, byt := range w {
+		accum |= byt
+	}
+	return accum == 0
+}
+func (w Word256) Compare(other Word256) int {
+	return bytes.Compare(w[:], other[:])
+}
+
+func Uint64ToWord256(i uint64) Word256 {
+	buf := [8]byte{}
+	PutUint64BE(buf[:], i)
+	return LeftPadWord256(buf[:])
+}
+
+func Int64ToWord256(i int64) Word256 {
+	buf := [8]byte{}
+	PutInt64BE(buf[:], i)
+	return LeftPadWord256(buf[:])
+}
+
+func RightPadWord256(bz []byte) (word Word256) {
+	copy(word[:], bz)
+	return
+}
+
+func LeftPadWord256(bz []byte) (word Word256) {
+	copy(word[32-len(bz):], bz)
+	return
+}
+
+func Uint64FromWord256(word Word256) uint64 {
+	buf := word.Postfix(8)
+	return GetUint64BE(buf)
+}
+
+func Int64FromWord256(word Word256) int64 {
+	buf := word.Postfix(8)
+	return GetInt64BE(buf)
+}
+
+//-------------------------------------
+
+type Tuple256 struct {
+	First  Word256
+	Second Word256
+}
+
+func (tuple Tuple256) Compare(other Tuple256) int {
+	firstCompare := tuple.First.Compare(other.First)
+	if firstCompare == 0 {
+		return tuple.Second.Compare(other.Second)
+	} else {
+		return firstCompare
+	}
+}
+
+func Tuple256Split(t Tuple256) (Word256, Word256) {
+	return t.First, t.Second
+}
+
+type Tuple256Slice []Tuple256
+
+func (p Tuple256Slice) Len() int { return len(p) }
+func (p Tuple256Slice) Less(i, j int) bool {
+	return p[i].Compare(p[j]) < 0
+}
+func (p Tuple256Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p Tuple256Slice) Sort()         { sort.Sort(p) }
-- 
GitLab