} 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
}
"fmt"
"github.com/bytom/blockchain"
- "github.com/bytom/consensus/algorithm"
"github.com/bytom/consensus/difficulty"
"github.com/bytom/util"
)
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
}
}
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"
)
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
}
import (
"testing"
+
+ "github.com/bytom/consensus/difficulty"
)
// test genesis
}
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)
}
}
+++ /dev/null
-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
-}
"math/big"
"github.com/bytom/consensus"
+ "github.com/bytom/mining/tensority"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/legacy"
)
// 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
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"
// 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 {
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
}
}
"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"
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 {
Version: 1,
Height: nextBlockHeight,
PreviousBlockHash: preBlock.Hash(),
- Seed: *nextBlockSeed,
Timestamp: uint64(time.Now().Unix()),
TransactionStatus: *bc.NewTransactionStatus(),
BlockCommitment: legacy.BlockCommitment{},
--- /dev/null
+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
+}
--- /dev/null
+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
+}
--- /dev/null
+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)
+}
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
"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"
)
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.
orphanManage: NewOrphanManage(),
store: store,
txPool: txPool,
- seedCaches: seed.NewSeedCaches(),
}
c.state.cond.L = new(sync.Mutex)
storeStatus := store.GetStoreStatus()
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)
+++ /dev/null
-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
-}
"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"
)
// 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)
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
}
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
}
"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"
block: &bc.Block{
BlockHeader: &bc.BlockHeader{
Height: 0,
+ Bits: 2305843009230471167,
},
Transactions: []*bc.Tx{mockCoinbaseTx(1470000000000000000)},
},
block: &bc.Block{
BlockHeader: &bc.BlockHeader{
Height: 0,
+ Bits: 2305843009230471167,
},
Transactions: []*bc.Tx{mockCoinbaseTx(1)},
},
block: &bc.Block{
BlockHeader: &bc.BlockHeader{
Height: 0,
+ Bits: 2305843009230471167,
SerializedSize: 88888888,
},
Transactions: []*bc.Tx{mockCoinbaseTx(1)},
},
}
- seedCaches := seed.NewSeedCaches()
for _, c := range cases {
txRoot, err := bc.MerkleRoot(c.block.Transactions)
if err != nil {
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)
}
}