Skip to content

Commit

Permalink
feat!: indexing public key
Browse files Browse the repository at this point in the history
  • Loading branch information
b00f committed Aug 28, 2023
1 parent 7b25860 commit 64a32b5
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 54 deletions.
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 @@ package store
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 @@ import (
)

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 @@ func (bs *blockStore) saveBlock(batch *leveldb.Batch, height uint32, block *bloc
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 @@ func (bs *blockStore) hasBlock(height uint32) bool {
}
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
// 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 @@ import (
"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 @@ var (
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 @@ func (s *store) SaveBlock(height uint32, block *block.Block, cert *block.Certifi
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 @@ func (s *store) Block(height uint32) (*StoredBlock, error) {
return nil, err
}

return &StoredBlock{
return &CommittedBlock{
BlockHash: blockHash,
Height: height,
Data: data[hash.HashSize:],
Expand Down Expand Up @@ -192,7 +194,20 @@ func (s *store) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
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 @@ func (s *store) Transaction(id tx.ID) (*StoredTx, error) {
}
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

0 comments on commit 64a32b5

Please sign in to comment.