Skip to content

Commit

Permalink
fix(store): cache Ed25519 Public Keys (#1495)
Browse files Browse the repository at this point in the history
  • Loading branch information
b00f authored Aug 30, 2024
1 parent 0fd3ac2 commit 550d5b5
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 118 deletions.
5 changes: 4 additions & 1 deletion cmd/wallet/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ func buildNewAddressCmd(parentCmd *cobra.Command) {
if *addressType == wallet.AddressTypeBLSAccount {
addressInfo, err = wlt.NewBLSAccountAddress(label)
} else if *addressType == wallet.AddressTypeEd25519Account {
password := cmd.PromptInput("Password")
password := ""
if wlt.IsEncrypted() {
password = cmd.PromptInput("Password")
}
addressInfo, err = wlt.NewEd25519AccountAddress(label, password)
} else if *addressType == wallet.AddressTypeValidator {
addressInfo, err = wlt.NewValidatorAddress(label)
Expand Down
2 changes: 1 addition & 1 deletion execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func CheckAndExecute(trx *tx.Tx, sb sandbox.Sandbox, strict bool) error {
}
}

if exists := sb.AnyRecentTransaction(trx.ID()); exists {
if exists := sb.RecentTransaction(trx.ID()); exists {
return TransactionCommittedError{
ID: trx.ID(),
}
Expand Down
8 changes: 4 additions & 4 deletions execution/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestTransferLockTime(t *testing.T) {
ts := testsuite.NewTestSuite(t)

sb := sandbox.MockingSandbox(ts)
rndPubKey, rndPrvKey := ts.RandBLSKeyPair()
rndPubKey, rndPrvKey := ts.RandEd25519KeyPair()
rndAccAddr := rndPubKey.AccountAddress()
rndAcc := sb.MakeNewAccount(rndAccAddr)
rndAcc.AddToBalance(1000 * 1e9)
Expand Down Expand Up @@ -247,7 +247,7 @@ func TestExecute(t *testing.T) {
err := Execute(trx, sb)
assert.NoError(t, err)

assert.True(t, sb.AnyRecentTransaction(trx.ID()))
assert.True(t, sb.RecentTransaction(trx.ID()))
})
}

Expand Down Expand Up @@ -296,15 +296,15 @@ func TestCheck(t *testing.T) {
err := CheckAndExecute(trx, sb, true)
assert.NoError(t, err)

assert.True(t, sb.AnyRecentTransaction(trx.ID()))
assert.True(t, sb.RecentTransaction(trx.ID()))
})
}

func TestReplay(t *testing.T) {
ts := testsuite.NewTestSuite(t)

sb := sandbox.MockingSandbox(ts)
rndPubKey, rndPrvKey := ts.RandBLSKeyPair()
rndPubKey, rndPrvKey := ts.RandEd25519KeyPair()
rndAccAddr := rndPubKey.AccountAddress()
rndAcc := sb.MakeNewAccount(rndAccAddr)
rndAcc.AddToBalance(1e9)
Expand Down
2 changes: 1 addition & 1 deletion sandbox/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Sandbox interface {
UpdateAccount(crypto.Address, *account.Account)

CommitTransaction(trx *tx.Tx)
AnyRecentTransaction(txID tx.ID) bool
RecentTransaction(txID tx.ID) bool
IsBanned(crypto.Address) bool

Validator(crypto.Address) *validator.Validator
Expand Down
4 changes: 2 additions & 2 deletions sandbox/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ func (m *MockSandbox) UpdateAccount(addr crypto.Address, acc *account.Account) {
m.TestStore.UpdateAccount(addr, acc)
}

func (m *MockSandbox) AnyRecentTransaction(txID tx.ID) bool {
func (m *MockSandbox) RecentTransaction(txID tx.ID) bool {
if m.TestCommittedTrxs[txID] != nil {
return true
}

return m.TestStore.AnyRecentTransaction(txID)
return m.TestStore.RecentTransaction(txID)
}

func (m *MockSandbox) Validator(addr crypto.Address) *validator.Validator {
Expand Down
4 changes: 2 additions & 2 deletions sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ func (sb *sandbox) UpdateAccount(addr crypto.Address, acc *account.Account) {
s.updated = true
}

func (sb *sandbox) AnyRecentTransaction(txID tx.ID) bool {
func (sb *sandbox) RecentTransaction(txID tx.ID) bool {
if sb.committedTrxs[txID] != nil {
return true
}

return sb.store.AnyRecentTransaction(txID)
return sb.store.RecentTransaction(txID)
}

func (sb *sandbox) Validator(addr crypto.Address) *validator.Validator {
Expand Down
6 changes: 3 additions & 3 deletions sandbox/sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,16 @@ func TestAccountChange(t *testing.T) {
})
}

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

randTx1 := td.GenerateTestTransferTx()
randTx2 := td.GenerateTestTransferTx()
td.sandbox.CommitTransaction(randTx1)
td.sandbox.CommitTransaction(randTx2)

assert.True(t, td.sandbox.AnyRecentTransaction(randTx1.ID()))
assert.True(t, td.sandbox.AnyRecentTransaction(randTx2.ID()))
assert.True(t, td.sandbox.RecentTransaction(randTx1.ID()))
assert.True(t, td.sandbox.RecentTransaction(randTx2.ID()))

totalTxFees := randTx1.Fee() + randTx2.Fee()
assert.Equal(t, totalTxFees, td.sandbox.AccumulatedFee())
Expand Down
17 changes: 7 additions & 10 deletions state/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/types/block"
"github.com/pactus-project/pactus/types/tx"
"github.com/pactus-project/pactus/util/testsuite"
"github.com/stretchr/testify/assert"
)

Expand All @@ -20,14 +21,13 @@ func TestProposeBlock(t *testing.T) {
invBondTx := td.GenerateTestBondTx()
invSortitionTx := td.GenerateTestSortitionTx()

pub, _ := td.RandBLSKeyPair()
validTrx1 := tx.NewTransferTx(lockTime, td.genAccKey.PublicKeyNative().AccountAddress(),
td.RandAccAddress(), 1, 1000)
td.HelperSignTransaction(td.genAccKey, validTrx1)
validTrx1 := td.GenerateTestTransferTx(
testsuite.TransactionWithLockTime(lockTime),
testsuite.TransactionWithEd25519Signer(td.genAccKey))

validTrx2 := tx.NewBondTx(lockTime, td.genAccKey.PublicKeyNative().AccountAddress(),
pub.ValidatorAddress(), pub, 1000000000, 100000)
td.HelperSignTransaction(td.genAccKey, validTrx2)
validTrx2 := td.GenerateTestTransferTx(
testsuite.TransactionWithLockTime(lockTime),
testsuite.TransactionWithEd25519Signer(td.genAccKey))

assert.NoError(t, td.state.AddPendingTx(invTransferTx))
assert.NoError(t, td.state.AddPendingTx(invBondTx))
Expand All @@ -41,9 +41,6 @@ func TestProposeBlock(t *testing.T) {
assert.Equal(t, block.Txs{validTrx1, validTrx2}, blk.Transactions()[1:])
assert.True(t, blk.Transactions()[0].IsSubsidyTx())
assert.NoError(t, td.state.CommitBlock(blk, cert))

assert.Equal(t, int64(1000000004), td.state.TotalPower())
assert.Equal(t, int64(4), td.state.committee.TotalPower())
}

func TestExecuteBlock(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/bls"
"github.com/pactus-project/pactus/crypto/ed25519"
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/genesis"
"github.com/pactus-project/pactus/store"
Expand All @@ -29,7 +30,7 @@ type testData struct {

state *state
genValKeys []*bls.ValidatorKey
genAccKey *bls.PrivateKey
genAccKey *ed25519.PrivateKey
commonTxPool *txpool.MockTxPool
}

Expand Down Expand Up @@ -62,7 +63,7 @@ func setup(t *testing.T) *testData {
genAcc1.AddToBalance(21 * 1e15) // 21,000,000.000,000,000
genAcc2 := account.NewAccount(1)
genAcc2.AddToBalance(21 * 1e15) // 21,000,000.000,000,000
genAccPubKey, genAccPrvKey := ts.RandBLSKeyPair()
genAccPubKey, genAccPrvKey := ts.RandEd25519KeyPair()

genAccs := map[crypto.Address]*account.Account{
crypto.TreasuryAddress: genAcc1,
Expand Down
29 changes: 23 additions & 6 deletions store/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
lru "github.com/hashicorp/golang-lru/v2"
"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/bls"
"github.com/pactus-project/pactus/crypto/ed25519"
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/sortition"
"github.com/pactus-project/pactus/types/block"
Expand All @@ -26,13 +27,13 @@ func blockHashKey(h hash.Hash) []byte {

type blockStore struct {
db *leveldb.DB
pubKeyCache *lru.Cache[crypto.Address, *bls.PublicKey]
pubKeyCache *lru.Cache[crypto.Address, crypto.PublicKey]
seedCache *pairslice.PairSlice[uint32, *sortition.VerifiableSeed]
seedCacheWindow uint32
}

func newBlockStore(db *leveldb.DB, seedCacheWindow uint32, publicKeyCacheSize int) *blockStore {
pubKeyCache, err := lru.New[crypto.Address, *bls.PublicKey](publicKeyCacheSize)
pubKeyCache, err := lru.New[crypto.Address, crypto.PublicKey](publicKeyCacheSize)
if err != nil {
return nil
}
Expand Down Expand Up @@ -141,7 +142,7 @@ func (bs *blockStore) hasBlock(height uint32) bool {
return tryHas(bs.db, blockKey(height))
}

func (bs *blockStore) publicKey(addr crypto.Address) (*bls.PublicKey, error) {
func (bs *blockStore) publicKey(addr crypto.Address) (crypto.PublicKey, error) {
if pubKey, ok := bs.pubKeyCache.Get(addr); ok {
return pubKey, nil
}
Expand All @@ -150,9 +151,25 @@ func (bs *blockStore) publicKey(addr crypto.Address) (*bls.PublicKey, error) {
if err != nil {
return nil, err
}
pubKey, err := bls.PublicKeyFromBytes(data)
if err != nil {
return nil, err
var pubKey crypto.PublicKey
switch addr.Type() {
case crypto.AddressTypeValidator,
crypto.AddressTypeBLSAccount:
pubKey, err = bls.PublicKeyFromBytes(data)
if err != nil {
return nil, err
}
case crypto.AddressTypeEd25519Account:
pubKey, err = ed25519.PublicKeyFromBytes(data)
if err != nil {
return nil, err
}

case crypto.AddressTypeTreasury:
panic("unreachable")

default:
return nil, PublicKeyNotFoundError{Address: addr}
}

bs.pubKeyCache.Add(addr, pubKey)
Expand Down
5 changes: 2 additions & 3 deletions store/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package store

import (
"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/sortition"
"github.com/pactus-project/pactus/types/account"
Expand Down Expand Up @@ -84,8 +83,8 @@ type Reader interface {
BlockHash(height uint32) hash.Hash
SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed
Transaction(id tx.ID) (*CommittedTx, error)
AnyRecentTransaction(id tx.ID) bool
PublicKey(addr crypto.Address) (*bls.PublicKey, error)
RecentTransaction(id tx.ID) bool
PublicKey(addr crypto.Address) (crypto.PublicKey, error)
HasAccount(crypto.Address) bool
Account(addr crypto.Address) (*account.Account, error)
TotalAccounts() int32
Expand Down
7 changes: 3 additions & 4 deletions store/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"

"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/sortition"
"github.com/pactus-project/pactus/types/account"
Expand Down Expand Up @@ -80,11 +79,11 @@ func (m *MockStore) SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed
return nil
}

func (m *MockStore) PublicKey(addr crypto.Address) (*bls.PublicKey, error) {
func (m *MockStore) PublicKey(addr crypto.Address) (crypto.PublicKey, error) {
for _, blk := range m.Blocks {
for _, trx := range blk.Transactions() {
if trx.Payload().Signer() == addr {
return trx.PublicKey().(*bls.PublicKey), nil
return trx.PublicKey(), nil
}
}
}
Expand Down Expand Up @@ -116,7 +115,7 @@ func (m *MockStore) Transaction(id tx.ID) (*CommittedTx, error) {
return nil, fmt.Errorf("not found")
}

func (m *MockStore) AnyRecentTransaction(id tx.ID) bool {
func (m *MockStore) RecentTransaction(id tx.ID) bool {
for _, blk := range m.Blocks {
for _, trx := range blk.Transactions() {
if trx.ID() == id {
Expand Down
11 changes: 7 additions & 4 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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/sortition"
"github.com/pactus-project/pactus/types/account"
Expand Down Expand Up @@ -239,7 +238,7 @@ func (s *store) SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed {
return s.blockStore.sortitionSeed(blockHeight)
}

func (s *store) PublicKey(addr crypto.Address) (*bls.PublicKey, error) {
func (s *store) PublicKey(addr crypto.Address) (crypto.PublicKey, error) {
s.lk.RLock()
defer s.lk.RUnlock()

Expand Down Expand Up @@ -274,11 +273,15 @@ func (s *store) Transaction(id tx.ID) (*CommittedTx, error) {
}, nil
}

func (s *store) AnyRecentTransaction(id tx.ID) bool {
// RecentTransaction checks if there is a transaction with the given ID
// within the last 8640 blocks.
// The time window for recent transactions is determined by the
// TransactionToLive interval, which is part of the consensus parameters.
func (s *store) RecentTransaction(id tx.ID) bool {
s.lk.Lock()
defer s.lk.Unlock()

return s.txStore.anyRecentTransaction(id)
return s.txStore.RecentTransaction(id)
}

func (s *store) HasAccount(addr crypto.Address) bool {
Expand Down
Loading

0 comments on commit 550d5b5

Please sign in to comment.