OSDN Git Service

super clean tensority init push (#337)
authorPaladz <yzhu101@uottawa.ca>
Wed, 31 Jan 2018 07:10:02 +0000 (15:10 +0800)
committerGitHub <noreply@github.com>
Wed, 31 Jan 2018 07:10:02 +0000 (15:10 +0800)
* super clean tensority init push

* modify hashMatrix

16 files changed:
blockchain/miner.go
cmd/miner/main.go
config/genesis.go
config/genesis_test.go
consensus/algorithm/base.go [deleted file]
consensus/difficulty/difficulty.go
mining/cpuminer/cpuminer.go
mining/mining.go
mining/tensority/matrix.go [new file with mode: 0644]
mining/tensority/seed.go [new file with mode: 0644]
mining/tensority/tensority.go [new file with mode: 0644]
protocol/block.go
protocol/protocol.go
protocol/seed/seed.go [deleted file]
protocol/validation/validation.go
protocol/validation/validation_test.go

index 92c000c..4f74853 100644 (file)
@@ -13,17 +13,10 @@ func (bcr *BlockchainReactor) getWork() *WorkResp {
        } else {
                resp.Header = block.BlockHeader
        }
-       seedCaches := bcr.chain.SeedCaches()
-       if seedCache, err := seedCaches.Get(&resp.Header.Seed); err != nil {
-               return nil
-       } else {
-               resp.Cache = seedCache
-       }
 
        return &resp
 }
 
 type WorkResp struct {
        Header legacy.BlockHeader
-       Cache  []uint32
 }
index 8839592..ea97778 100644 (file)
@@ -5,7 +5,6 @@ import (
        "fmt"
 
        "github.com/bytom/blockchain"
-       "github.com/bytom/consensus/algorithm"
        "github.com/bytom/consensus/difficulty"
        "github.com/bytom/util"
 )
@@ -20,15 +19,10 @@ func doWork(work *blockchain.WorkResp) {
        for i := uint64(0); i <= maxNonce; i++ {
                work.Header.Nonce = i
                headerHash := work.Header.Hash()
-               proofHash, err := algorithm.AIHash(work.Header.Height, &headerHash, work.Cache)
-               if err != nil {
-                       fmt.Printf("Mining: failed on AIHash: %v\n", err)
-                       return
-               }
 
-               if difficulty.CheckProofOfWork(proofHash, work.Header.Bits) {
+               if difficulty.CheckProofOfWork(&headerHash, work.Header.Bits) {
                        // to do: submitWork
-                       fmt.Printf("Mining: successful-----proof hash:%v\n", proofHash)
+                       fmt.Printf("Mining: successful-----proof hash:%v\n", headerHash)
                        return
                }
        }
index d9b60e0..49714e4 100644 (file)
@@ -4,8 +4,6 @@ import (
        log "github.com/sirupsen/logrus"
 
        "github.com/bytom/consensus"
-       "github.com/bytom/consensus/difficulty"
-       "github.com/bytom/crypto/sha3pool"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
 )
@@ -44,34 +42,21 @@ func GenerateGenesisBlock() *legacy.Block {
                log.Panicf("Fatal create merkelRoot")
        }
 
-       var seed [32]byte
-       sha3pool.Sum256(seed[:], make([]byte, 32))
-
        block := &legacy.Block{
                BlockHeader: legacy.BlockHeader{
                        Version:   1,
                        Height:    0,
                        Nonce:     4216077,
-                       Seed:      bc.NewHash(seed),
                        Timestamp: 1516788453,
                        BlockCommitment: legacy.BlockCommitment{
                                TransactionsMerkleRoot: merkleRoot,
                        },
-                       Bits: 2161727821138738707,
+                       Bits: 2305843009222082559,
                        TransactionStatus: bc.TransactionStatus{
                                Bitmap: []byte{0},
                        },
                },
                Transactions: []*legacy.Tx{genesisCoinbaseTx},
        }
-
-       for {
-               hash := block.Hash()
-               if difficulty.CheckProofOfWork(&hash, block.Bits) {
-                       log.WithField("block.Nonce=", block.Nonce).Info()
-                       break
-               }
-               block.Nonce++
-       }
        return block
 }
index 3b7a183..cdfe2f6 100644 (file)
@@ -2,6 +2,8 @@ package config
 
 import (
        "testing"
+
+       "github.com/bytom/consensus/difficulty"
 )
 
 // test genesis
@@ -12,7 +14,16 @@ func TestGenerateGenesisTx(t *testing.T) {
 }
 
 func TestGenerateGenesisBlock(t *testing.T) {
-       if block := GenerateGenesisBlock(); block == nil {
-               t.Errorf("Generate genesis block failed")
+       block := GenerateGenesisBlock()
+       nonce := block.Nonce
+       for {
+               hash := block.Hash()
+               if difficulty.CheckProofOfWork(&hash, block.Bits) {
+                       break
+               }
+               block.Nonce++
+       }
+       if block.Nonce != nonce {
+               t.Errorf("correct nonce is %d, but get %d", block.Nonce, nonce)
        }
 }
diff --git a/consensus/algorithm/base.go b/consensus/algorithm/base.go
deleted file mode 100644 (file)
index 8a8ede4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package algorithm
-
-import "github.com/bytom/protocol/bc"
-
-func CreateCache(seed *bc.Hash) ([]uint32, error) {
-       return []uint32{}, nil
-}
-
-func CreateSeed(height uint64, preSeed *bc.Hash, preBlockHashs []*bc.Hash) *bc.Hash {
-       return preBlockHashs[0]
-}
-
-func AIHash(height uint64, blockHash *bc.Hash, seedCache []uint32) (*bc.Hash, error) {
-       return blockHash, nil
-}
index ef84875..0bc0237 100755 (executable)
@@ -5,6 +5,7 @@ import (
        "math/big"
 
        "github.com/bytom/consensus"
+       "github.com/bytom/mining/tensority"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
 )
@@ -84,7 +85,8 @@ func BigToCompact(n *big.Int) uint64 {
 
 // CheckProofOfWork the hash is vaild for given difficult
 func CheckProofOfWork(hash *bc.Hash, bits uint64) bool {
-       return HashToBig(hash).Cmp(CompactToBig(bits)) <= 0
+       compareHash := tensority.Hash(hash, hash)
+       return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0
 }
 
 // CalcNextRequiredDifficulty return the difficult for next block
index ab349b1..a047f50 100644 (file)
@@ -11,7 +11,6 @@ import (
        log "github.com/sirupsen/logrus"
 
        "github.com/bytom/blockchain/account"
-       "github.com/bytom/consensus/algorithm"
        "github.com/bytom/consensus/difficulty"
        "github.com/bytom/mining"
        "github.com/bytom/protocol"
@@ -48,12 +47,6 @@ type CPUMiner struct {
 // target difficulty.
 func (m *CPUMiner) solveBlock(block *legacy.Block, ticker *time.Ticker, quit chan struct{}) bool {
        header := &block.BlockHeader
-       seedCaches := m.chain.SeedCaches()
-       seedCache, err := seedCaches.Get(&header.Seed)
-       if err != nil {
-               log.Errorf("Mining: failed on get seedCache: %v", err)
-               return false
-       }
 
        for i := uint64(0); i <= maxNonce; i++ {
                select {
@@ -68,13 +61,7 @@ func (m *CPUMiner) solveBlock(block *legacy.Block, ticker *time.Ticker, quit cha
 
                header.Nonce = i
                headerHash := header.Hash()
-               proofHash, err := algorithm.AIHash(header.Height, &headerHash, seedCache)
-               if err != nil {
-                       log.Errorf("Mining: failed on AIHash: %v", err)
-                       return false
-               }
-
-               if difficulty.CheckProofOfWork(proofHash, header.Bits) {
+               if difficulty.CheckProofOfWork(&headerHash, header.Bits) {
                        return true
                }
        }
index 65eef7b..114c695 100644 (file)
@@ -13,7 +13,6 @@ import (
        "github.com/bytom/blockchain/account"
        "github.com/bytom/blockchain/txbuilder"
        "github.com/bytom/consensus"
-       "github.com/bytom/consensus/algorithm"
        "github.com/bytom/consensus/difficulty"
        "github.com/bytom/errors"
        "github.com/bytom/protocol"
@@ -70,7 +69,6 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
        preBlock := c.BestBlock()
        preBcBlock := legacy.MapBlock(preBlock)
        nextBlockHeight := preBlock.BlockHeader.Height + 1
-       nextBlockSeed := algorithm.CreateSeed(nextBlockHeight, preBcBlock.Seed, []*bc.Hash{&preBcBlock.ID})
 
        var compareDiffBH *legacy.BlockHeader
        if compareDiffBlock, err := c.GetBlockByHeight(nextBlockHeight - consensus.BlocksPerRetarget); err == nil {
@@ -82,7 +80,6 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                        Version:           1,
                        Height:            nextBlockHeight,
                        PreviousBlockHash: preBlock.Hash(),
-                       Seed:              *nextBlockSeed,
                        Timestamp:         uint64(time.Now().Unix()),
                        TransactionStatus: *bc.NewTransactionStatus(),
                        BlockCommitment:   legacy.BlockCommitment{},
diff --git a/mining/tensority/matrix.go b/mining/tensority/matrix.go
new file mode 100644 (file)
index 0000000..c25f589
--- /dev/null
@@ -0,0 +1,110 @@
+package tensority
+
+import (
+       "reflect"
+       "unsafe"
+
+       "gonum.org/v1/gonum/mat"
+
+       "github.com/bytom/crypto/sha3pool"
+       "github.com/bytom/protocol/bc"
+)
+
+const (
+       matSize     = 1 << 8 // Size of matrix
+       matNum      = 1 << 8 // Number of matrix
+       epochLength = 1 << 7 // Blocks per epoch
+       mulRounds   = 1 << 8 // Number of rounds in mulmatrix
+)
+
+func mulMatrix(headerhash []byte, cache []uint32) []uint8 {
+       // Convert our destination slice to a byte buffer
+       header := *(*reflect.SliceHeader)(unsafe.Pointer(&cache))
+       header.Len *= 4
+       header.Cap *= 4
+       cacheInt8 := *(*[]int8)(unsafe.Pointer(&header))
+
+       data := make([]float64, matNum*matSize*matSize)
+       for i := 0; i < len(cacheInt8); i++ {
+               data[i] = float64(cacheInt8[i])
+       }
+
+       exthash := extendBytes(headerhash, 7)
+
+       mb := mat.NewDense(matSize, matSize, data[:matSize*matSize])
+       mc := mat.NewDense(matSize, matSize, make([]float64, matSize*matSize))
+       for i := 0; i < 256; i++ {
+               index := int(exthash[i])
+               ma := mat.NewDense(matSize, matSize, data[index*matSize*matSize:(index+1)*matSize*matSize])
+               mc.Mul(ma, mb)
+
+               for j := 0; j < matSize; j++ {
+                       for k := 0; k < matSize; k++ {
+                               i32v := int32(mc.At(j, k))
+                               i8v := int8((i32v & 0xff) +
+                                       ((i32v >> 8) & 0xff))
+                               mc.Set(j, k, float64(i8v))
+                       }
+               }
+
+               mb = mc
+       }
+
+       result := make([]uint8, 0)
+       for i := 0; i < matSize; i++ {
+               for j := 0; j < matSize; j++ {
+                       result = append(result, uint8(mc.At(i, j)))
+               }
+       }
+
+       return result
+}
+
+// TODO: check why
+func hashMatrix(result []uint8) *bc.Hash {
+       var mat8 [matSize][matSize]uint8
+       for i := 0; i < matSize; i++ {
+               for j := 0; j < matSize; j++ {
+                       mat8[i][j] = result[i*matSize+j]
+               }
+       }
+
+       var mat32 [matSize][matSize / 4]uint32
+       // ATTENTION !!!!!!! C++ is different!!!
+       for i := 0; i < matSize; i++ {
+               for j := 0; j < matSize/4; j++ {
+                       mat32[i][j] = ((uint32(mat8[i][j+192])) << 24) |
+                               ((uint32(mat8[i][j+128])) << 16) |
+                               ((uint32(mat8[i][j+64])) << 8) |
+                               ((uint32(mat8[i][j])) << 0)
+               }
+       }
+
+       data := make([]uint32, 0)
+       for k := matSize; k > 1; k = k / 2 {
+               for j := 0; j < k/2; j++ {
+                       for i := 0; i < matSize/4; i++ {
+                               mat32[j][i] = fnv(mat32[j][i], mat32[j+k/2][i])
+                       }
+               }
+       }
+
+       for i := 0; i < matSize/4; i++ {
+               data = append(data, mat32[0][i])
+       }
+
+       // Convert our destination slice to a byte buffer
+       header := *(*reflect.SliceHeader)(unsafe.Pointer(&data))
+       header.Len *= 4
+       header.Cap *= 4
+       dataBytes := *(*[]byte)(unsafe.Pointer(&header))
+
+       var h [32]byte
+       sha3pool.Sum256(h[:], dataBytes)
+       bcHash := bc.NewHash(h)
+       return &bcHash
+}
+
+func fnv(a, b uint32) uint32 {
+       return a*0x01000193 ^ b
+}
diff --git a/mining/tensority/seed.go b/mining/tensority/seed.go
new file mode 100644 (file)
index 0000000..99ab6dc
--- /dev/null
@@ -0,0 +1,39 @@
+package tensority
+
+import (
+       "github.com/bytom/crypto"
+       "github.com/bytom/crypto/scrypt"
+       "github.com/bytom/protocol/bc"
+)
+
+func calcSeed(blockHashs []*bc.Hash) []byte {
+       date := []byte{}
+       for _, blockHash := range blockHashs {
+               date = append(date, blockHash.Bytes()...)
+       }
+       return crypto.Sha256(date)
+}
+
+// TODO: clean the code, now it's hard to read
+func extendBytes(seed []byte, round int) []byte {
+       extSeed := make([]byte, len(seed)*(round+1))
+       copy(extSeed, seed)
+
+       for i := 0; i < round; i++ {
+               h := crypto.Sha256(extSeed[i*32 : (i+1)*32])
+               copy(extSeed[(i+1)*32:(i+2)*32], h[:])
+       }
+
+       return extSeed
+}
+
+func calcSeedCache(seed []byte) (cache []uint32) {
+       extSeed := extendBytes(seed, 3)
+       xy := make([]uint32, 64)
+       v := make([]uint32, 32*1024)
+       for i := 0; i < 128; i++ {
+               scrypt.Smix(extSeed, 1, 1024, v, xy)
+               cache = append(cache, v...)
+       }
+       return cache
+}
diff --git a/mining/tensority/tensority.go b/mining/tensority/tensority.go
new file mode 100644 (file)
index 0000000..0f7f399
--- /dev/null
@@ -0,0 +1,12 @@
+package tensority
+
+import "github.com/bytom/protocol/bc"
+
+// Leave here for implement cache
+type AIHash struct{}
+
+func Hash(hash, seed *bc.Hash) *bc.Hash {
+       cache := calcSeedCache(seed.Bytes())
+       data := mulMatrix(hash.Bytes(), cache)
+       return hashMatrix(data)
+}
index 3e177e9..de8dcd7 100755 (executable)
@@ -46,7 +46,7 @@ func (c *Chain) GetBlockByHeight(height uint64) (*legacy.Block, error) {
 func (c *Chain) ValidateBlock(block, prev *legacy.Block) error {
        blockEnts := legacy.MapBlock(block)
        prevEnts := legacy.MapBlock(prev)
-       if err := validation.ValidateBlock(blockEnts, prevEnts, c.seedCaches); err != nil {
+       if err := validation.ValidateBlock(blockEnts, prevEnts); err != nil {
                return errors.Sub(ErrBadBlock, err)
        }
        return nil
index 0eded1b..f6d607f 100755 (executable)
@@ -10,7 +10,6 @@ import (
        "github.com/bytom/errors"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
-       "github.com/bytom/protocol/seed"
        "github.com/bytom/protocol/state"
 )
 
@@ -130,8 +129,7 @@ type Chain struct {
                hash      *bc.Hash
                mainChain map[uint64]*bc.Hash
        }
-       store      Store
-       seedCaches *seed.SeedCaches
+       store Store
 }
 
 // NewChain returns a new Chain using store as the underlying storage.
@@ -141,7 +139,6 @@ func NewChain(initialBlockHash bc.Hash, store Store, txPool *TxPool) (*Chain, er
                orphanManage:     NewOrphanManage(),
                store:            store,
                txPool:           txPool,
-               seedCaches:       seed.NewSeedCaches(),
        }
        c.state.cond.L = new(sync.Mutex)
        storeStatus := store.GetStoreStatus()
@@ -216,11 +213,6 @@ func (c *Chain) BestBlock() *legacy.Block {
        return c.state.block
 }
 
-// SeedCaches return the seedCached manager
-func (c *Chain) SeedCaches() *seed.SeedCaches {
-       return c.seedCaches
-}
-
 // GetUtxo try to find the utxo status in db
 func (c *Chain) GetUtxo(hash *bc.Hash) (*storage.UtxoEntry, error) {
        return c.store.GetUtxo(hash)
diff --git a/protocol/seed/seed.go b/protocol/seed/seed.go
deleted file mode 100644 (file)
index 3957ce0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package seed
-
-import (
-       "github.com/bytom/consensus/algorithm"
-       "github.com/bytom/protocol/bc"
-       "github.com/golang/groupcache/lru"
-)
-
-const maxCached = 2
-
-type SeedCaches struct {
-       cache *lru.Cache
-}
-
-func NewSeedCaches() *SeedCaches {
-       return &SeedCaches{
-               cache: lru.New(maxCached),
-       }
-}
-
-func (s *SeedCaches) Get(seed *bc.Hash) ([]uint32, error) {
-       if v, ok := s.cache.Get(seed); ok {
-               return v.([]uint32), nil
-       }
-
-       cache, err := algorithm.CreateCache(seed)
-       if err != nil {
-               return nil, err
-       }
-
-       s.cache.Add(seed, cache)
-       return cache, nil
-}
index 42604df..ab683fd 100644 (file)
@@ -5,13 +5,11 @@ import (
        "time"
 
        "github.com/bytom/consensus"
-       "github.com/bytom/consensus/algorithm"
        "github.com/bytom/consensus/difficulty"
        "github.com/bytom/consensus/segwit"
        "github.com/bytom/errors"
        "github.com/bytom/math/checked"
        "github.com/bytom/protocol/bc"
-       "github.com/bytom/protocol/seed"
        "github.com/bytom/protocol/vm"
 )
 
@@ -521,7 +519,7 @@ func checkValidDest(vs *validationState, vd *bc.ValueDestination) error {
 
 // ValidateBlock validates a block and the transactions within.
 // It does not run the consensus program; for that, see ValidateBlockSig.
-func ValidateBlock(b, prev *bc.Block, seedCaches *seed.SeedCaches) error {
+func ValidateBlock(b, prev *bc.Block) error {
        if b.Height > 0 {
                if prev == nil {
                        return errors.WithDetailf(errNoPrevBlock, "height %d", b.Height)
@@ -539,15 +537,7 @@ func ValidateBlock(b, prev *bc.Block, seedCaches *seed.SeedCaches) error {
                return errWrongBlockSize
        }
 
-       seedCache, err := seedCaches.Get(b.Seed)
-       if err != nil {
-               return err
-       }
-       proofHash, err := algorithm.AIHash(b.Height, &b.ID, seedCache)
-       if err != nil {
-               return err
-       }
-       if !difficulty.CheckProofOfWork(proofHash, b.BlockHeader.Bits) {
+       if !difficulty.CheckProofOfWork(&b.ID, b.BlockHeader.Bits) {
                return errWorkProof
        }
 
@@ -626,9 +616,6 @@ func validateBlockAgainstPrev(b, prev *bc.Block) error {
        if b.Timestamp <= prev.Timestamp {
                return errors.WithDetailf(errMisorderedBlockTime, "previous block time %d, current block time %d", prev.Timestamp, b.Timestamp)
        }
-       if *b.Seed != *algorithm.CreateSeed(b.Height, prev.Seed, []*bc.Hash{&prev.ID}) {
-               return errors.New("wrong block seed")
-       }
        return nil
 }
 
index cb8cb0d..985aced 100644 (file)
@@ -13,7 +13,6 @@ import (
        "github.com/bytom/errors"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
-       "github.com/bytom/protocol/seed"
        "github.com/bytom/protocol/vm"
        "github.com/bytom/protocol/vm/vmutil"
        "github.com/bytom/testutil"
@@ -419,6 +418,7 @@ func TestValidateBlock(t *testing.T) {
                        block: &bc.Block{
                                BlockHeader: &bc.BlockHeader{
                                        Height: 0,
+                                       Bits:   2305843009230471167,
                                },
                                Transactions: []*bc.Tx{mockCoinbaseTx(1470000000000000000)},
                        },
@@ -428,6 +428,7 @@ func TestValidateBlock(t *testing.T) {
                        block: &bc.Block{
                                BlockHeader: &bc.BlockHeader{
                                        Height: 0,
+                                       Bits:   2305843009230471167,
                                },
                                Transactions: []*bc.Tx{mockCoinbaseTx(1)},
                        },
@@ -437,6 +438,7 @@ func TestValidateBlock(t *testing.T) {
                        block: &bc.Block{
                                BlockHeader: &bc.BlockHeader{
                                        Height:         0,
+                                       Bits:           2305843009230471167,
                                        SerializedSize: 88888888,
                                },
                                Transactions: []*bc.Tx{mockCoinbaseTx(1)},
@@ -445,7 +447,6 @@ func TestValidateBlock(t *testing.T) {
                },
        }
 
-       seedCaches := seed.NewSeedCaches()
        for _, c := range cases {
                txRoot, err := bc.MerkleRoot(c.block.Transactions)
                if err != nil {
@@ -455,7 +456,7 @@ func TestValidateBlock(t *testing.T) {
                c.block.BlockHeader.TransactionStatus = bc.NewTransactionStatus()
                c.block.TransactionsRoot = &txRoot
 
-               if err = ValidateBlock(c.block, nil, seedCaches); rootErr(err) != c.err {
+               if err = ValidateBlock(c.block, nil); rootErr(err) != c.err {
                        t.Errorf("got error %s, want %s", err, c.err)
                }
        }