feat(api): add block header signs func

This commit is contained in:
Aiden X 2020-08-26 16:22:10 +08:00
parent 4967ae38f4
commit c66691ea31
10 changed files with 139 additions and 24 deletions

3
go.mod
View File

@ -20,10 +20,11 @@ require (
github.com/grpc-ecosystem/grpc-gateway v1.13.0
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e
github.com/libp2p/go-libp2p-core v0.5.6
github.com/libp2p/go-libp2p-crypto v0.1.0
github.com/magiconair/properties v1.8.1
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200728032028-8dba332fa0ed
github.com/meshplus/bitxhub-kit v1.0.1-0.20200813112754-a341f7bc198d
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200820031846-1f77b9fd43fd
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200826032743-bb0d60e38d74
github.com/meshplus/go-lightp2p v0.0.0-20200817105923-6b3aee40fa54
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.2.2

4
go.sum
View File

@ -652,8 +652,8 @@ github.com/meshplus/bitxhub-kit v1.0.1-0.20200813112754-a341f7bc198d/go.mod h1:g
github.com/meshplus/bitxhub-model v1.0.0-rc3/go.mod h1:ZCctQIYTlE3vJ8Lhkrgs9bWwNA+Dw4JzojOSIzLVU6E=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19 h1:D0n0/NqaueI6r+/cJIjYzWwjZ9j/5l36r/c8MYqTdXg=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200820031846-1f77b9fd43fd h1:kfvMDhblWfo5SZQsk2FBlTGDzBhxjjx48TDFOHnq85g=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200820031846-1f77b9fd43fd/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200826032743-bb0d60e38d74 h1:l8OpKXWu9IH5FeAs3alBmOEbrRLoRIyMCTGnacASaTg=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200826032743-bb0d60e38d74/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/meshplus/go-lightp2p v0.0.0-20200817105923-6b3aee40fa54 h1:5Ip5AB7SxxQHg5SRtf2cCOI2wy1p75MQB12soPtPyf8=
github.com/meshplus/go-lightp2p v0.0.0-20200817105923-6b3aee40fa54/go.mod h1:G89UJaeqCQFxFdp8wzy1AdKfMtDEhpySau0pjDNeeaw=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=

View File

@ -108,7 +108,7 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
}
// 0. load ledger
rwLdg, err := ledger.New(bcStorage, ldb, nil, loggers.Logger(loggers.Executor))
rwLdg, err := ledger.New(rep, bcStorage, ldb, nil, loggers.Logger(loggers.Executor))
if err != nil {
return nil, fmt.Errorf("create RW ledger: %w", err)
}
@ -121,7 +121,7 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
}
// create read only ledger
viewLdg, err := ledger.New(bcStorage, ldb, rwLdg.AccountCache(), loggers.Logger(loggers.Executor))
viewLdg, err := ledger.New(rep, bcStorage, ldb, rwLdg.AccountCache(), loggers.Logger(loggers.Executor))
if err != nil {
return nil, fmt.Errorf("create readonly ledger: %w", err)
}

View File

@ -129,6 +129,8 @@ func (b *BrokerAPI) FetchSignsFromOtherPeers(id string, typ pb.GetMultiSignsRequ
address, sign, err = b.requestAssetExchangeSignFromPeer(pid, id)
case pb.GetMultiSignsRequest_IBTP:
address, sign, err = b.requestIBTPSignPeer(pid, id)
case pb.GetMultiSignsRequest_BLOCK_HEADER:
address, sign, err = b.requestBlockHeaderSignFromPeer(pid, id)
}
if err != nil {
@ -194,6 +196,29 @@ func (b *BrokerAPI) requestIBTPSignPeer(pid uint64, ibtpHash string) (string, []
return data.Address, data.Signature, nil
}
func (b *BrokerAPI) requestBlockHeaderSignFromPeer(pid uint64, height string) (string, []byte, error) {
req := pb.Message{
Type: pb.Message_FETCH_BLOCK_SIGN,
Data: []byte(height),
}
resp, err := b.bxh.PeerMgr.Send(pid, &req)
if err != nil {
return "", nil, err
}
if resp == nil || resp.Type != pb.Message_FETCH_BLOCK_SIGN_ACK {
return "", nil, fmt.Errorf("invalid fetch block header sign resp")
}
data := model.MerkleWrapperSign{}
if err := data.Unmarshal(resp.Data); err != nil {
return "", nil, err
}
return data.Address, data.Signature, nil
}
func (b *BrokerAPI) GetSign(content string, typ pb.GetMultiSignsRequest_Type) (string, []byte, error) {
switch typ {
case pb.GetMultiSignsRequest_ASSET_EXCHANGE:
@ -219,6 +244,18 @@ func (b *BrokerAPI) GetSign(content string, typ pb.GetMultiSignsRequest_Type) (s
return "", nil, fmt.Errorf("get ibtp sign: %w", err)
}
return addr, sign, nil
case pb.GetMultiSignsRequest_BLOCK_HEADER:
height, err := strconv.ParseUint(content, 10, 64)
if err != nil {
return "", nil, fmt.Errorf("get block header sign: %w", err)
}
sign, err := b.bxh.Ledger.GetBlockSign(height)
if err != nil {
return "", nil, fmt.Errorf("get block sign: %w", err)
}
return b.bxh.GetPrivKey().Address, sign, nil
default:
return "", nil, fmt.Errorf("unsupported get sign type")
}

View File

@ -19,6 +19,8 @@ import (
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
"github.com/meshplus/bitxhub/internal/model/events"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/cert"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -173,8 +175,9 @@ func TestBlockExecutor_ExecuteBlock_Transfer(t *testing.T) {
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
require.Nil(t, err)
repo.DefaultConfig()
accountCache := ledger.NewAccountCache()
ldg, err := ledger.New(blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"))
ldg, err := ledger.New(createMockRepo(t), blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"))
require.Nil(t, err)
_, from := loadAdminKey(t)
@ -207,7 +210,7 @@ func TestBlockExecutor_ExecuteBlock_Transfer(t *testing.T) {
require.EqualValues(t, uint64(99999997), ldg.GetBalance(from))
// test executor with readonly ledger
viewLedger, err := ledger.New(blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"))
viewLedger, err := ledger.New(createMockRepo(t), blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"))
require.Nil(t, err)
exec, err := New(viewLedger, log.NewWithModule("executor"))
@ -305,3 +308,22 @@ func mockIBTP(t *testing.T, index uint64, typ pb.IBTP_Type) *pb.IBTP {
Timestamp: time.Now().UnixNano(),
}
}
func createMockRepo(t *testing.T) *repo.Repo {
key := `-----BEGIN EC PRIVATE KEY-----
BcNwjTDCxyxLNjFKQfMAc6sY6iJs+Ma59WZyC/4uhjE=
-----END EC PRIVATE KEY-----`
privKey, err := cert.ParsePrivateKey([]byte(key), crypto.Secp256k1)
require.Nil(t, err)
address, err := privKey.PublicKey().Address()
require.Nil(t, err)
return &repo.Repo{
Key: &repo.Key{
PrivKey: privKey,
Address: address.Hex(),
},
}
}

View File

@ -22,7 +22,7 @@ func TestAccount_GetState(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("ChainLedger"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("ChainLedger"))
assert.Nil(t, err)
h := hexutil.Encode(bytesutil.LeftPadBytes([]byte{11}, 20))

View File

@ -242,6 +242,14 @@ func (l *ChainLedger) persistTransactions(batcher storage.Batch, block *pb.Block
}
func (l *ChainLedger) persistBlock(batcher storage.Batch, block *pb.Block) error {
// Generate block header signature
signed, err := l.repo.Key.PrivKey.Sign(block.BlockHash.Bytes())
if err != nil {
return err
}
block.Signature = signed
bs, err := block.Marshal()
if err != nil {
return err

View File

@ -5,6 +5,8 @@ import (
"sync"
"time"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/pkg/storage"
@ -30,6 +32,7 @@ type ChainLedger struct {
accounts map[string]*Account
accountCache *AccountCache
prevJnlHash types.Hash
repo *repo.Repo
chainMutex sync.RWMutex
chainMeta *pb.ChainMeta
@ -46,7 +49,7 @@ type BlockData struct {
}
// New create a new ledger instance
func New(blockchainStore storage.Storage, ldb storage.Storage, accountCache *AccountCache, logger logrus.FieldLogger) (*ChainLedger, error) {
func New(repo *repo.Repo, blockchainStore storage.Storage, ldb storage.Storage, accountCache *AccountCache, logger logrus.FieldLogger) (*ChainLedger, error) {
chainMeta, err := loadChainMeta(blockchainStore)
if err != nil {
return nil, fmt.Errorf("load chain meta: %w", err)
@ -65,6 +68,7 @@ func New(blockchainStore storage.Storage, ldb storage.Storage, accountCache *Acc
}
ledger := &ChainLedger{
repo: repo,
logger: logger,
chainMeta: chainMeta,
blockchainStore: blockchainStore,

View File

@ -8,9 +8,12 @@ import (
"testing"
"github.com/meshplus/bitxhub-kit/bytesutil"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/log"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/cert"
"github.com/meshplus/bitxhub/pkg/storage"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/stretchr/testify/assert"
@ -26,7 +29,7 @@ func TestLedger_Commit(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
// create an account
@ -91,7 +94,7 @@ func TestLedger_Commit(t *testing.T) {
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ldg, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ldg, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
assert.Equal(t, uint64(5), ldg.maxJnlHeight)
assert.Equal(t, journal.ChangedHash, ldg.prevJnlHash)
@ -124,7 +127,7 @@ func TestChainLedger_Rollback(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
// create an addr0
@ -226,7 +229,7 @@ func TestChainLedger_Rollback(t *testing.T) {
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err = New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"))
ledger, err = New(createMockRepo(t), blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"))
assert.Nil(t, err)
assert.Equal(t, uint64(2), ledger.minJnlHeight)
assert.Equal(t, uint64(2), ledger.maxJnlHeight)
@ -244,7 +247,7 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
assert.Equal(t, uint64(0), ledger.minJnlHeight)
@ -309,7 +312,7 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
ledger.Close()
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
ledger, err = New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err = New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
assert.Equal(t, uint64(4), ledger.minJnlHeight)
assert.Equal(t, uint64(4), ledger.maxJnlHeight)
@ -325,7 +328,7 @@ func TestChainLedger_QueryByPrefix(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -369,7 +372,7 @@ func TestChainLedger_GetAccount(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -436,7 +439,7 @@ func TestChainLedger_GetCode(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -474,7 +477,7 @@ func TestChainLedger_AddAccountsToCache(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -542,7 +545,7 @@ func TestChainLedger_GetInterchainMeta(t *testing.T) {
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"))
ledger, err := New(createMockRepo(t), blockStorage, ldb, accountCache, log.NewWithModule("executor"))
require.Nil(t, err)
// create an account
@ -594,3 +597,22 @@ func genBlockData(height uint64, accounts map[string]*Account, journal *BlockJou
InterchainMeta: &pb.InterchainMeta{},
}
}
func createMockRepo(t *testing.T) *repo.Repo {
key := `-----BEGIN EC PRIVATE KEY-----
BcNwjTDCxyxLNjFKQfMAc6sY6iJs+Ma59WZyC/4uhjE=
-----END EC PRIVATE KEY-----`
privKey, err := cert.ParsePrivateKey([]byte(key), crypto.Secp256k1)
require.Nil(t, err)
address, err := privKey.PublicKey().Address()
require.Nil(t, err)
return &repo.Repo{
Key: &repo.Key{
PrivKey: privKey,
Address: address.Hex(),
},
}
}

View File

@ -15,6 +15,8 @@ import (
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/cert"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/meshplus/bitxhub/pkg/vm"
"github.com/stretchr/testify/assert"
@ -58,7 +60,7 @@ func initCreateContext(t *testing.T, name string) *vm.Context {
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
ldg, err := ledger.New(createMockRepo(t), store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
assert.Nil(t, err)
return &vm.Context{
@ -88,7 +90,7 @@ func initValidationContext(t *testing.T, name string) *vm.Context {
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
ldg, err := ledger.New(createMockRepo(t), store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
require.Nil(t, err)
return &vm.Context{
@ -118,7 +120,7 @@ func initFabricContext(t *testing.T, name string) *vm.Context {
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
ldg, err := ledger.New(createMockRepo(t), store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
require.Nil(t, err)
return &vm.Context{
@ -247,7 +249,7 @@ func BenchmarkRunFabValidation(b *testing.B) {
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(b, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
ldg, err := ledger.New(&repo.Repo{Key: &repo.Key{PrivKey: privKey}}, store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"))
require.Nil(b, err)
ctx := &vm.Context{
Caller: caller,
@ -374,3 +376,22 @@ func TestWasm_RunWithoutMethod(t *testing.T) {
_, err = wasm1.Run(payload)
assert.Equal(t, errorLackOfMethod, err)
}
func createMockRepo(t *testing.T) *repo.Repo {
key := `-----BEGIN EC PRIVATE KEY-----
BcNwjTDCxyxLNjFKQfMAc6sY6iJs+Ma59WZyC/4uhjE=
-----END EC PRIVATE KEY-----`
privKey, err := cert.ParsePrivateKey([]byte(key), crypto.Secp256k1)
require.Nil(t, err)
address, err := privKey.PublicKey().Address()
require.Nil(t, err)
return &repo.Repo{
Key: &repo.Key{
PrivKey: privKey,
Address: address.Hex(),
},
}
}