@@ -18,58 +18,95 @@ package pingpong
1818
1919import (
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\n error %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\n error %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