Skip to content

Commit 8835bfd

Browse files
replace the KMD usage in pingpong with direct signing (#2653)
Removes signing calls to KMD by creating internal hashmap and signing transactions locally.
1 parent 250abcd commit 8835bfd

File tree

2 files changed

+183
-114
lines changed

2 files changed

+183
-114
lines changed

shared/pingpong/accounts.go

Lines changed: 91 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,95 @@ package pingpong
1818

1919
import (
2020
"fmt"
21+
"io/ioutil"
2122
"math"
2223
"math/rand"
2324
"os"
25+
"path/filepath"
2426
"sort"
2527
"strings"
2628
"time"
2729

2830
"github.com/algorand/go-algorand/config"
2931
"github.com/algorand/go-algorand/crypto"
3032
v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1"
33+
algodAcct "github.com/algorand/go-algorand/data/account"
3134
"github.com/algorand/go-algorand/data/basics"
3235
"github.com/algorand/go-algorand/data/transactions"
3336
"github.com/algorand/go-algorand/data/transactions/logic"
3437
"github.com/algorand/go-algorand/libgoal"
3538
"github.com/algorand/go-algorand/protocol"
39+
"github.com/algorand/go-algorand/util/db"
3640
)
3741

38-
func ensureAccounts(ac libgoal.Client, initCfg PpConfig) (accounts map[string]uint64, cfg PpConfig, err error) {
39-
accounts = make(map[string]uint64)
42+
func (pps *WorkerState) ensureAccounts(ac libgoal.Client, initCfg PpConfig) (accounts map[string]*pingPongAccount, cfg PpConfig, err error) {
43+
accounts = make(map[string]*pingPongAccount)
4044
cfg = initCfg
4145

42-
wallet, err := ac.GetUnencryptedWalletHandle()
46+
genID, err2 := ac.GenesisID()
47+
if err2 != nil {
48+
err = err2
49+
return
50+
}
51+
genesisDir := filepath.Join(ac.DataDir(), genID)
52+
files, err2 := ioutil.ReadDir(genesisDir)
53+
if err2 != nil {
54+
err = err2
55+
return
56+
}
4357

4458
var srcAcctPresent bool
4559
var richestAccount string
4660
var richestBalance uint64
4761

48-
addresses, err := ac.ListAddresses(wallet)
62+
for _, info := range files {
63+
var handle db.Accessor
4964

50-
if err != nil {
51-
return nil, PpConfig{}, err
52-
}
65+
// If it can't be a participation key database, skip it
66+
if !config.IsRootKeyFilename(info.Name()) {
67+
continue
68+
}
69+
70+
// Fetch a handle to this database
71+
handle, err = db.MakeErasableAccessor(filepath.Join(genesisDir, info.Name()))
72+
if err != nil {
73+
// Couldn't open it, skip it
74+
continue
75+
}
76+
77+
// Fetch an account.Participation from the database
78+
root, err := algodAcct.RestoreRoot(handle)
79+
handle.Close()
80+
if err != nil {
81+
// Couldn't read it, skip it
82+
continue
83+
}
84+
85+
publicKey := root.Secrets().SignatureVerifier
86+
accountAddress := basics.Address(publicKey)
5387

54-
// find either srcAccount or the richest account
55-
for _, addr := range addresses {
56-
if addr == cfg.SrcAccount {
88+
if accountAddress.String() == cfg.SrcAccount {
5789
srcAcctPresent = true
5890
}
5991

60-
amount, err := ac.GetBalance(addr)
92+
amt, err := ac.GetBalance(accountAddress.String())
6193
if err != nil {
6294
return nil, PpConfig{}, err
6395
}
6496

65-
amt := amount
6697
if !srcAcctPresent && amt > richestBalance {
67-
richestAccount = addr
98+
richestAccount = accountAddress.String()
6899
richestBalance = amt
69100
}
70-
accounts[addr] = amt
101+
71102
if !initCfg.Quiet {
72-
fmt.Printf("Found local account: %s -> %v\n", addr, amt)
103+
fmt.Printf("Found local account: %s -> %v\n", accountAddress.String(), amt)
104+
}
105+
106+
accounts[accountAddress.String()] = &pingPongAccount{
107+
balance: amt,
108+
sk: root.Secrets(),
109+
pk: accountAddress,
73110
}
74111
}
75112

@@ -104,7 +141,7 @@ func ensureAccounts(ac libgoal.Client, initCfg PpConfig) (accounts map[string]ui
104141
if len(accounts) != int(cfg.NumPartAccounts+1) {
105142
fmt.Printf("Not enough accounts - creating %d more\n", int(cfg.NumPartAccounts+1)-len(accounts))
106143
}
107-
accounts, err = generateAccounts(ac, accounts, cfg.NumPartAccounts, wallet)
144+
accounts, err = generateAccounts(ac, accounts, cfg.NumPartAccounts)
108145
if err != nil {
109146
return
110147
}
@@ -129,7 +166,7 @@ func throttleTransactionRate(startTime time.Time, cfg PpConfig, totalSent uint64
129166
// Step 1) Create X assets for each of the participant accounts
130167
// Step 2) For each participant account, opt-in to assets of all other participant accounts
131168
// Step 3) Evenly distribute the assets across all participant accounts
132-
func (pps *WorkerState) prepareAssets(assetAccounts map[string]uint64, client libgoal.Client) (resultAssetMaps map[uint64]v1.AssetParams, optIns map[uint64][]string, err error) {
169+
func (pps *WorkerState) prepareAssets(assetAccounts map[string]*pingPongAccount, client libgoal.Client) (resultAssetMaps map[uint64]v1.AssetParams, optIns map[uint64][]string, err error) {
133170
accounts := assetAccounts
134171
cfg := pps.cfg
135172
proto, err := getProto(client)
@@ -354,14 +391,14 @@ func (pps *WorkerState) prepareAssets(assetAccounts map[string]uint64, client li
354391
fmt.Printf("Distributing assets from %v to %v \n", creator, addr)
355392
}
356393

357-
tx, sendErr := pps.constructTxn(creator, addr, cfg.MaxFee, assetAmt, k, client)
394+
tx, signer, sendErr := pps.constructTxn(creator, addr, cfg.MaxFee, assetAmt, k, client)
358395
if sendErr != nil {
359396
fmt.Printf("Cannot transfer asset %v from account %v\n", k, creator)
360397
err = sendErr
361398
return
362399
}
363400

364-
_, err = signAndBroadcastTransaction(accounts, creator, tx, client, cfg)
401+
_, err = signAndBroadcastTransaction(accounts, signer, tx, client, cfg)
365402
if err != nil {
366403
_, _ = fmt.Fprintf(os.Stderr, "signing and broadcasting asset distribution failed with error %v\n", err)
367404
return
@@ -408,9 +445,9 @@ func (pps *WorkerState) prepareAssets(assetAccounts map[string]uint64, client li
408445
return
409446
}
410447

411-
func signAndBroadcastTransaction(accounts map[string]uint64, sender string, tx transactions.Transaction, client libgoal.Client, cfg PpConfig) (txID string, err error) {
448+
func signAndBroadcastTransaction(accounts map[string]*pingPongAccount, sender string, tx transactions.Transaction, client libgoal.Client, cfg PpConfig) (txID string, err error) {
412449
var signedTx transactions.SignedTxn
413-
signedTx, err = signTxn(sender, tx, client, cfg)
450+
signedTx, err = signTxn(sender, tx, accounts, cfg)
414451
if err != nil {
415452
fmt.Printf("Cannot sign trx %+v with account %v\nerror %v\n", tx, sender, err)
416453
return
@@ -423,7 +460,7 @@ func signAndBroadcastTransaction(accounts map[string]uint64, sender string, tx t
423460
if !cfg.Quiet {
424461
fmt.Printf("Broadcast transaction %v\n", txID)
425462
}
426-
accounts[sender] -= tx.Fee.Raw
463+
accounts[sender].balance -= tx.Fee.Raw
427464

428465
return
429466
}
@@ -585,7 +622,7 @@ func genAppProgram(numOps uint32, numHashes uint32, hashSize string, numGlobalKe
585622
return ops.Program, progAsm
586623
}
587624

588-
func sendAsGroup(txgroup []transactions.Transaction, client libgoal.Client, h []byte) (err error) {
625+
func (pps *WorkerState) sendAsGroup(txgroup []transactions.Transaction, client libgoal.Client, senders []string) (err error) {
589626
if len(txgroup) == 0 {
590627
err = fmt.Errorf("sendAsGroup: empty group")
591628
return
@@ -596,9 +633,15 @@ func sendAsGroup(txgroup []transactions.Transaction, client libgoal.Client, h []
596633
return
597634
}
598635
var stxgroup []transactions.SignedTxn
599-
for _, txn := range txgroup {
636+
for i, txn := range txgroup {
600637
txn.Group = gid
601-
signedTxn, signErr := client.SignTransactionWithWallet(h, nil, txn)
638+
//signedTxn, signErr := client.SignTransactionWithWallet(h, nil, txn)
639+
signedTxn, signErr := signTxn(senders[i], txn, pps.accounts, pps.cfg)
640+
if err != nil {
641+
fmt.Printf("Cannot sign trx %+v with account %v\nerror %v\n", txn, senders[i], err)
642+
return
643+
}
644+
602645
if signErr != nil {
603646
fmt.Printf("Cannot sign app creation txn\n")
604647
err = signErr
@@ -635,7 +678,7 @@ func getProto(client libgoal.Client) (config.ConsensusParams, error) {
635678
return *proto, nil
636679
}
637680

638-
func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig) (appParams map[uint64]v1.AppParams, optIns map[uint64][]string, err error) {
681+
func (pps *WorkerState) prepareApps(accounts map[string]*pingPongAccount, client libgoal.Client, cfg PpConfig) (appParams map[uint64]v1.AppParams, optIns map[uint64][]string, err error) {
639682
proto, err := getProto(client)
640683
if err != nil {
641684
return
@@ -686,13 +729,6 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
686729
}
687730
}
688731

689-
// Get wallet handle token
690-
var h []byte
691-
h, err = client.GetUnencryptedWalletHandle()
692-
if err != nil {
693-
return
694-
}
695-
696732
// create apps
697733
for idx, appAccount := range appAccounts {
698734
begin := idx * appsPerAcct
@@ -701,6 +737,7 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
701737
end = toCreate
702738
}
703739
var txgroup []transactions.Transaction
740+
var senders []string
704741
for i := begin; i < end; i++ {
705742
var tx transactions.Transaction
706743

@@ -730,10 +767,11 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
730767
tx.Note = note[:]
731768

732769
txgroup = append(txgroup, tx)
733-
accounts[appAccount.Address] -= tx.Fee.Raw
770+
accounts[appAccount.Address].balance -= tx.Fee.Raw
771+
senders = append(senders, appAccount.Address)
734772
}
735773

736-
err = sendAsGroup(txgroup, client, h)
774+
err = pps.sendAsGroup(txgroup, client, senders)
737775
if err != nil {
738776
return
739777
}
@@ -776,6 +814,7 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
776814
optIns = make(map[uint64][]string)
777815
for addr := range accounts {
778816
var txgroup []transactions.Transaction
817+
var senders []string
779818
permAppIndices := rand.Perm(len(aidxs))
780819
for i := uint32(0); i < cfg.NumAppOptIn; i++ {
781820
j := permAppIndices[i]
@@ -801,8 +840,9 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
801840
optIns[aidx] = append(optIns[aidx], addr)
802841

803842
txgroup = append(txgroup, tx)
843+
senders = append(senders, addr)
804844
if len(txgroup) == groupSize {
805-
err = sendAsGroup(txgroup, client, h)
845+
err = pps.sendAsGroup(txgroup, client, senders)
806846
if err != nil {
807847
return
808848
}
@@ -811,7 +851,7 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
811851
}
812852
// broadcast leftovers
813853
if len(txgroup) > 0 {
814-
err = sendAsGroup(txgroup, client, h)
854+
err = pps.sendAsGroup(txgroup, client, senders)
815855
if err != nil {
816856
return
817857
}
@@ -822,7 +862,7 @@ func prepareApps(accounts map[string]uint64, client libgoal.Client, cfg PpConfig
822862
return
823863
}
824864

825-
func takeTopAccounts(allAccounts map[string]uint64, numAccounts uint32, srcAccount string) (accounts map[string]uint64) {
865+
func takeTopAccounts(allAccounts map[string]*pingPongAccount, numAccounts uint32, srcAccount string) (accounts map[string]*pingPongAccount) {
826866
allAddrs := make([]string, len(allAccounts))
827867
var i int
828868
for addr := range allAccounts {
@@ -833,12 +873,12 @@ func takeTopAccounts(allAccounts map[string]uint64, numAccounts uint32, srcAccou
833873
sort.SliceStable(allAddrs, func(i, j int) bool {
834874
amt1 := allAccounts[allAddrs[i]]
835875
amt2 := allAccounts[allAddrs[j]]
836-
return amt1 > amt2
876+
return amt1.balance > amt2.balance
837877
})
838878

839879
// Now populate a new map with just the accounts needed
840880
accountsRequired := int(numAccounts + 1) // Participating and Src
841-
accounts = make(map[string]uint64)
881+
accounts = make(map[string]*pingPongAccount)
842882
accounts[srcAccount] = allAccounts[srcAccount]
843883
for _, addr := range allAddrs {
844884
accounts[addr] = allAccounts[addr]
@@ -849,18 +889,23 @@ func takeTopAccounts(allAccounts map[string]uint64, numAccounts uint32, srcAccou
849889
return
850890
}
851891

852-
func generateAccounts(client libgoal.Client, allAccounts map[string]uint64, numAccounts uint32, wallet []byte) (map[string]uint64, error) {
892+
func generateAccounts(client libgoal.Client, allAccounts map[string]*pingPongAccount, numAccounts uint32) (map[string]*pingPongAccount, error) {
853893
// Compute the number of accounts to generate
854894
accountsRequired := int(numAccounts+1) - len(allAccounts)
855895

896+
var seed crypto.Seed
897+
856898
for accountsRequired > 0 {
857899
accountsRequired--
858-
addr, err := client.GenerateAddress(wallet)
859-
if err != nil {
860-
return allAccounts, err
861-
}
862900

863-
allAccounts[addr] = 0
901+
crypto.RandBytes(seed[:])
902+
privateKey := crypto.GenerateSignatureSecrets(seed)
903+
publicKey := basics.Address(privateKey.SignatureVerifier)
904+
905+
allAccounts[publicKey.String()] = &pingPongAccount{
906+
sk: privateKey,
907+
pk: publicKey,
908+
}
864909
}
865910

866911
return allAccounts, nil

0 commit comments

Comments
 (0)