Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: indexing public key #437

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions state/facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ type Facade interface {
PendingTx(id tx.ID) *tx.Tx
AddPendingTx(trx *tx.Tx) error
AddPendingTxAndBroadcast(trx *tx.Tx) error
StoredBlock(height uint32) *store.StoredBlock
StoredTx(id tx.ID) *store.StoredTx
StoredBlock(height uint32) *store.CommittedBlock
StoredTx(id tx.ID) *store.CommittedTx
BlockHash(height uint32) hash.Hash
BlockHeight(hash hash.Hash) uint32
AccountByAddress(addr crypto.Address) *account.Account
Expand Down
4 changes: 2 additions & 2 deletions state/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ func (m *MockState) CommitteePower() int64 {
return m.TestCommittee.TotalPower()
}

func (m *MockState) StoredBlock(height uint32) *store.StoredBlock {
func (m *MockState) StoredBlock(height uint32) *store.CommittedBlock {
m.lk.RLock()
defer m.lk.RUnlock()

b, _ := m.TestStore.Block(height)
return b
}

func (m *MockState) StoredTx(id tx.ID) *store.StoredTx {
func (m *MockState) StoredTx(id tx.ID) *store.CommittedTx {
m.lk.RLock()
defer m.lk.RUnlock()

Expand Down
4 changes: 2 additions & 2 deletions state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ func (st *state) IsValidator(addr crypto.Address) bool {
return st.store.HasValidator(addr)
}

func (st *state) StoredBlock(height uint32) *store.StoredBlock {
func (st *state) StoredBlock(height uint32) *store.CommittedBlock {
b, err := st.store.Block(height)
if err != nil {
st.logger.Trace("error on retrieving block", "err", err)
Expand All @@ -627,7 +627,7 @@ func (st *state) StoredBlock(height uint32) *store.StoredBlock {
return b
}

func (st *state) StoredTx(id tx.ID) *store.StoredTx {
func (st *state) StoredTx(id tx.ID) *store.CommittedTx {
tx, err := st.store.Transaction(id)
if err != nil {
st.logger.Trace("searching transaction in local store failed", "id", id, "err", err)
Expand Down
25 changes: 25 additions & 0 deletions store/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import (
"bytes"

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/types/block"
"github.com/pactus-project/pactus/util"
Expand All @@ -12,6 +13,9 @@
)

func blockKey(height uint32) []byte { return append(blockPrefix, util.Uint32ToSlice(height)...) }
func publicKeyKey(addr crypto.Address) []byte {
return append(publicKeyPrefix, addr.Bytes()...)
}
func blockHashKey(hash hash.Hash) []byte {
return append(blockHeightPrefix, hash.Bytes()...)
}
Expand Down Expand Up @@ -62,11 +66,24 @@
regs[i].height = height
regs[i].offset = uint32(offset)

pubKey := trx.PublicKey()
if pubKey != nil {
if !bs.hasPublicKey(trx.Payload().Signer()) {
publicKeyKey := publicKeyKey(trx.Payload().Signer())
batch.Put(publicKeyKey, pubKey.Bytes())
} else {
// we have indexed this public key, se we can remove it
trx.SetPublicKey(nil)

Check warning on line 76 in store/block.go

View check run for this annotation

Codecov / codecov/patch

store/block.go#L76

Added line #L76 was not covered by tests
}
}

err := trx.Encode(w)
if err != nil {
panic(err) // Should we panic?
}
regs[i].length = uint32(w.Len() - offset)

trx.SetPublicKey(pubKey)
}
blockKey := blockKey(height)
blockHashKey := blockHashKey(blockHash)
Expand Down Expand Up @@ -101,3 +118,11 @@
}
return has
}

func (bs *blockStore) hasPublicKey(addr crypto.Address) bool {
has, err := bs.db.Has(publicKeyKey(addr), nil)
if err != nil {
return false

Check warning on line 125 in store/block.go

View check run for this annotation

Codecov / codecov/patch

store/block.go#L125

Added line #L125 was not covered by tests
}
return has
}
33 changes: 21 additions & 12 deletions store/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package store

import (
"bytes"

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/types/account"
Expand All @@ -16,13 +18,13 @@ import (

// TODO: How to undo or rollback at least for last 21 blocks

type StoredBlock struct {
type CommittedBlock struct {
BlockHash hash.Hash
Height uint32
Data []byte
}

func (s *StoredBlock) ToBlock() *block.Block {
func (s *CommittedBlock) ToBlock() *block.Block {
b, err := block.FromBytes(s.Data)
if err != nil {
panic(err)
Expand All @@ -33,35 +35,42 @@ func (s *StoredBlock) ToBlock() *block.Block {
return b
}

type StoredTx struct {
type CommittedTx struct {
TxID tx.ID
Height uint32
BlockTime uint32
Data []byte
}

func (s *StoredTx) ToTx() *tx.Tx {
trx, err := tx.FromBytes(s.Data)
if err != nil {
func (s *CommittedTx) ToTx() *tx.Tx {
trx := new(tx.Tx)
r := bytes.NewReader(s.Data)
if err := trx.Decode(r); err != nil {
panic(err)
}
if !trx.ID().EqualsTo(s.TxID) {
panic("invalid data. transaction id does not match")
}

// TODO: we can set public key, if it doesn't set
b00f marked this conversation as resolved.
Show resolved Hide resolved
// pubKey, found := store.PublicKey(trx.Payload().Signer())
// if !found {
// panic("unable to find the public key")
// }
// trx.SetPublicKey(pubKey)

return trx
}

type Reader interface {
Block(height uint32) (*StoredBlock, error)
Block(height uint32) (*CommittedBlock, error)
BlockHeight(hash hash.Hash) uint32
BlockHash(height uint32) hash.Hash
RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block)
Transaction(id tx.ID) (*StoredTx, error)
Transaction(id tx.ID) (*CommittedTx, error)
PublicKey(addr crypto.Address) (crypto.PublicKey, bool)
HasAccount(crypto.Address) bool
Account(addr crypto.Address) (*account.Account, error)
AccountByNumber(number int32) (*account.Account, error)
TotalAccounts() int32
HasValidator(crypto.Address) bool
HasValidator(addr crypto.Address) bool
ValidatorAddresses() []crypto.Address
Validator(addr crypto.Address) (*validator.Validator, error)
ValidatorByNumber(num int32) (*validator.Validator, error)
Expand Down
19 changes: 15 additions & 4 deletions store/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ func MockingStore(ts *testsuite.TestSuite) *MockStore {
}
}

func (m *MockStore) Block(height uint32) (*StoredBlock, error) {
func (m *MockStore) Block(height uint32) (*CommittedBlock, error) {
b, ok := m.Blocks[height]
if ok {
d, _ := b.Bytes()
return &StoredBlock{
return &CommittedBlock{
BlockHash: b.Hash(),
Height: height,
Data: d,
Expand All @@ -63,12 +63,23 @@ func (m *MockStore) BlockHeight(hash hash.Hash) uint32 {
return 0
}

func (m *MockStore) Transaction(id tx.ID) (*StoredTx, error) {
func (m *MockStore) PublicKey(addr crypto.Address) (crypto.PublicKey, bool) {
for _, block := range m.Blocks {
for _, trx := range block.Transactions() {
if trx.Payload().Signer() == addr {
return trx.PublicKey(), true
}
}
}
return nil, false
}

func (m *MockStore) Transaction(id tx.ID) (*CommittedTx, error) {
for height, block := range m.Blocks {
for _, trx := range block.Transactions() {
if trx.ID() == id {
d, _ := trx.Bytes()
return &StoredTx{
return &CommittedTx{
TxID: id,
Height: height,
BlockTime: block.Header().UnixTime(),
Expand Down
23 changes: 19 additions & 4 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"sync"

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/bls"
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/types/account"
"github.com/pactus-project/pactus/types/block"
Expand Down Expand Up @@ -35,6 +36,7 @@
accountPrefix = []byte{0x05}
validatorPrefix = []byte{0x07}
blockHeightPrefix = []byte{0x09}
publicKeyPrefix = []byte{0x0a}
)

func tryGet(db *leveldb.DB, key []byte) ([]byte, error) {
Expand Down Expand Up @@ -140,7 +142,7 @@
s.updateStampLookup(height, block)
}

func (s *store) Block(height uint32) (*StoredBlock, error) {
func (s *store) Block(height uint32) (*CommittedBlock, error) {
s.lk.Lock()
defer s.lk.Unlock()

Expand All @@ -154,7 +156,7 @@
return nil, err
}

return &StoredBlock{
return &CommittedBlock{
BlockHash: blockHash,
Height: height,
Data: data[hash.HashSize:],
Expand Down Expand Up @@ -192,7 +194,20 @@
return 0, nil
}

func (s *store) Transaction(id tx.ID) (*StoredTx, error) {
func (s *store) PublicKey(addr crypto.Address) (crypto.PublicKey, bool) {
bs, err := tryGet(s.db, publicKeyKey(addr))
if err != nil {
return nil, false
}
pubKey, err := bls.PublicKeyFromBytes(bs)
if err != nil {
return nil, false

Check warning on line 204 in store/store.go

View check run for this annotation

Codecov / codecov/patch

store/store.go#L204

Added line #L204 was not covered by tests
}

return pubKey, true
}

func (s *store) Transaction(id tx.ID) (*CommittedTx, error) {
s.lk.Lock()
defer s.lk.Unlock()

Expand All @@ -211,7 +226,7 @@
}
blockTime := util.SliceToUint32(data[hash.HashSize+1 : hash.HashSize+5])

return &StoredTx{
return &CommittedTx{
TxID: id,
Height: pos.height,
BlockTime: blockTime,
Expand Down
18 changes: 18 additions & 0 deletions store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,21 @@ func TestRecentBlockByStamp(t *testing.T) {
assert.Zero(t, h)
assert.Nil(t, b)
}

func TestIndexingPublicKeys(t *testing.T) {
td := setup(t)

blkData, _ := td.store.Block(1)
blk := blkData.ToBlock()
for _, trx := range blk.Transactions() {
addr := trx.Payload().Signer()
pub, found := td.store.PublicKey(addr)

assert.True(t, found)
assert.Equal(t, pub.Address(), addr)
}

pub, found := td.store.PublicKey(td.RandomAddress())
assert.False(t, found)
assert.Nil(t, pub)
}
2 changes: 2 additions & 0 deletions types/block/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package block_test

import (
"encoding/hex"
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -186,6 +187,7 @@ func TestBlockHash(t *testing.T) {

txHashes := make([]hash.Hash, 0)
for _, trx := range b.Transactions() {
fmt.Println(trx.ID().String())
txHashes = append(txHashes, trx.ID())
}
txRoot := simplemerkle.NewTreeFromHashes(txHashes).Root()
Expand Down
Loading
Loading