Skip to content

Commit

Permalink
Update Vocdoni-node - ethless (#42)
Browse files Browse the repository at this point in the history
* Encode byte nonces as little endian binary

* Allocate space for nonce bytes

* Update signing method

* Create & use faucet account for testing

* Generate random faucet identifier

* Add faucetPrivKey environment variable

* Update vocdoni-node to stage

* Create faucet account in testing

* Ensure faucet has enough balance

* Request tokens when acct balance is low

* Address pr comments to vocclient.go

* Update vocdoni-node including vocone lock
  • Loading branch information
NateWilliams2 committed Apr 4, 2022
1 parent c019aed commit 93aa0b0
Show file tree
Hide file tree
Showing 12 changed files with 444 additions and 117 deletions.
8 changes: 8 additions & 0 deletions cmd/vaasapi/vaasapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func newConfig() (*config.Vaas, config.Error) {
"signing private Keys (if not specified, a new "+
"one will be created), the first one is the oracle public key")
cfg.API.AdminToken = *flag.String("adminToken", "", "hexString token for admin api calls")
cfg.API.FaucetPrivKey = *flag.String("faucetPrivKey", "", "hexString privKey for vochain faucet account")
cfg.API.ExplorerVoteUrl = *flag.String("explorerVoteUrl",
"https://vaas.explorer.vote/envelope/", "explorer url for vote envelope pages")
cfg.API.GlobalEntityKey = *flag.String("globalEntityKey", "",
Expand Down Expand Up @@ -98,6 +99,7 @@ func newConfig() (*config.Vaas, config.Error) {
viper.BindPFlag("logOutput", flag.Lookup("logOutput"))
viper.BindPFlag("signingKey", flag.Lookup("signingKey"))
viper.BindPFlag("api.adminToken", flag.Lookup("adminToken"))
viper.BindPFlag("api.faucetPrivKey", flag.Lookup("faucetPrivKey"))
viper.BindPFlag("api.maxCensusSize", flag.Lookup("maxCensusSize"))
viper.BindPFlag("api.explorerVoteUrl", flag.Lookup("explorerVoteUrl"))
viper.BindPFlag("api.globalEntityKey", flag.Lookup("globalEntityKey"))
Expand Down Expand Up @@ -271,6 +273,12 @@ func main() {
log.Fatal(err)
}

faucet := ethereum.NewSignKeys()
if err := faucet.AddHexKey(cfg.API.FaucetPrivKey); err != nil {
log.Fatalf("could not set faucet account: %w", err)
}
urlApi.SetFaucet(faucet)

// Vaas api
log.Infof("enabling VaaS API methods")
if err := urlApi.EnableVotingServiceHandlers(db, client, kv); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions config/vaas.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type API struct {
}
// AdminToken is the hexString bearer token for superadmin API methods
AdminToken string
// FaucetPrivKey is the hexString private key for the vochain faucet account to be used
FaucetPrivKey string
// GlobalEntityKey is the key used to encrypt entity private keys in the db
GlobalEntityKey string
// GlobalMetaKey is the key used to encrypt entity metadata keys in the db
Expand Down
12 changes: 5 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@ require (
github.com/adlio/schema v1.2.3 // indirect
github.com/arnaucube/go-blindsecp256k1 v0.0.0-20211204171003-644e7408753f
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/ethereum/go-ethereum v1.10.13
github.com/frankban/quicktest v1.14.0
github.com/ethereum/go-ethereum v1.10.16
github.com/frankban/quicktest v1.14.2
github.com/google/uuid v1.3.0
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
github.com/jackc/pgx v3.6.2+incompatible
github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee
github.com/lib/pq v1.10.4
github.com/onsi/gomega v1.17.0 // indirect
github.com/prometheus/client_golang v1.12.0
github.com/prometheus/client_golang v1.12.1
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc // indirect
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.10.1
github.com/vocdoni/blind-csp v0.1.5-0.20220214165159-4620baa07fa4
go.vocdoni.io/dvote v1.0.4-0.20220210143454-e386915ab3d5
go.vocdoni.io/dvote v1.0.4-0.20220331134144-80178eee1693
go.vocdoni.io/proto v1.13.3-0.20220203130255-cbdb9679ec7c
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
google.golang.org/protobuf v1.27.1
)

Expand Down
250 changes: 180 additions & 70 deletions go.sum

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions misc/compose/env
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,33 @@ DVOTE_SMTP_VALIDATIONURL=https://vocdoni.link/validation
DVOTE_SMTP_SENDER=
DVOTE_SMTP_SENDERNAME=Vocdoni

## Api ##
# VAASAPI_TAG=master
# VAASAPI_LOGERRORFILE=
# VAASAPI_LOGOUTPUT=
# VAASAPI_LOGLEVEL=
# VAASAPI_DATADIR=
# VAASAPI_SIGNINGKEY=
# VAASAPI_FAUCETPRIVKEY=
# VAASAPI_API_GATEWAYURL=https://${DOMAIN}/dvote
# VAASAPI_API_ROUTE=/
# VAASAPI_API_GLOBALENTITYKEY=
# VAASAPI_API_LISTENHOST=0.0.0.0
# VAASAPI_API_LISTENPORT=8081
# VAASAPI_API_ADMINTOKEN=
# VAASAPI_API_GLOBALMETAKEY=
#VAASAPI_API_SSL_DIRCERT=
#VAASAPI_API_SSL_DOMAIN=
# VAASAPI_DB_HOST=db
# VAASAPI_DB_PORT=5432
# VAASAPI_DB_USER=vocdoni
# VAASAPI_DB_PASSWORD=
# VAASAPI_DB_DBNAME=vaasapi
# VAASAPI_DB_SSLMODE=disable
#VAASAPI_MIGRATE_ACTION=
# VAASAPI_METRICS_ENABLED=True
# VAASAPI_METRICS_REFRESHINTERVAL=

# DB
POSTGRES_HOST=db
POSTGRES_USER=vocdoni
Expand Down
5 changes: 2 additions & 3 deletions test/testapi/api_public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func submitVoteSigned(t *testing.T, processID []byte,
if err != nil {
t.Fatal(err)
}
signedVoteTx.Signature, err = voterWallet.SignVocdoniTx(signedVoteTx.Tx)
signedVoteTx.Signature, err = voterWallet.SignVocdoniTx(signedVoteTx.Tx, "")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -246,7 +246,6 @@ func submitVoteBlind(t *testing.T, processID []byte,
if err != nil {
t.Fatal(err)
}

// get blind point from tokenR
blindPoint, err := blind.NewPointFromBytesUncompressed(hexTokenR)
if err != nil {
Expand Down Expand Up @@ -309,7 +308,7 @@ func submitVoteBlind(t *testing.T, processID []byte,
if err != nil {
t.Fatal(err)
}
signedVoteTx.Signature, err = voterWallet.SignVocdoniTx(signedVoteTx.Tx)
signedVoteTx.Signature, err = voterWallet.SignVocdoniTx(signedVoteTx.Tx, "")
if err != nil {
t.Fatal(err)
}
Expand Down
12 changes: 12 additions & 0 deletions test/testapi/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func TestMain(m *testing.M) {
log.Infof("SKIPPING: could not connect to DB: %v", err)
return
}
setupFaucetAccount()
setupTestIntegrators()
setupTestOrganizations()
setupTestElections()
Expand Down Expand Up @@ -126,6 +127,17 @@ func DoRequest(t *testing.T, url, authToken,
return resp.StatusCode
}

func setupFaucetAccount() {
err := API.Vocclient.SetAccountInfo(API.FaucetAccount, nil, "faucetURI", 0)
if err != nil {
log.Fatalf("cannot set faucet account: %s", err.Error())
}
time.Sleep(time.Second * 10)
if err := API.VC.MintTokens(API.FaucetAccount.Address(), 10000000000); err != nil {
log.Fatalf("cannot mint tokens to faucet: %s", err.Error())
}
}

func setupTestIntegrators() {
log.Infof("setting up test integrators")
testIntegrators = testcommon.CreateIntegrators(2)
Expand Down
30 changes: 20 additions & 10 deletions test/testcommon/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@ import (
"go.vocdoni.io/dvote/httprouter"
"go.vocdoni.io/dvote/log"
dvoteTypes "go.vocdoni.io/dvote/types"
"go.vocdoni.io/dvote/vocone"
)

type TestAPI struct {
DB database.Database
Port int
Signer *ethereum.SignKeys
URL string
AuthToken string
CSP TestCSP
Gateway string
StorageDir string
DB database.Database
Port int
VC *vocone.Vocone
Signer *ethereum.SignKeys
FaucetAccount *ethereum.SignKeys
URL string
AuthToken string
CSP TestCSP
Gateway string
Vocclient *vocclient.Client
StorageDir string
}

type TestCSP struct {
Expand All @@ -47,6 +51,11 @@ func (t *TestAPI) Start(dbc *config.DB, route, authToken, storageDir string, por
if err = t.Signer.Generate(); err != nil {
log.Fatal(err)
}
// Faucet
t.FaucetAccount = ethereum.NewSignKeys()
if err = t.FaucetAccount.Generate(); err != nil {
log.Fatal(err)
}
}
if dbc != nil {
// Postgres with sqlx
Expand All @@ -71,7 +80,7 @@ func (t *TestAPI) Start(dbc *config.DB, route, authToken, storageDir string, por

// start API
time.Sleep(time.Second * 5)
client, err := vocclient.New(t.Gateway, t.Signer)
t.Vocclient, err = vocclient.New(t.Gateway, t.Signer)
if err != nil {
log.Fatal(err)
}
Expand All @@ -92,6 +101,7 @@ func (t *TestAPI) Start(dbc *config.DB, route, authToken, storageDir string, por
if err != nil {
log.Fatal(err)
}
urlApi.SetFaucet(t.FaucetAccount)

kv, err := metadb.New(dvotedb.TypePebble, filepath.Join(t.StorageDir, "metadb"))
if err != nil {
Expand All @@ -100,7 +110,7 @@ func (t *TestAPI) Start(dbc *config.DB, route, authToken, storageDir string, por

// Vaas api
log.Infof("enabling VaaS API methods")
if err := urlApi.EnableVotingServiceHandlers(t.DB, client, kv); err != nil {
if err := urlApi.EnableVotingServiceHandlers(t.DB, t.Vocclient, kv); err != nil {
log.Fatal(err)
}
go integratorTokenNotifier.FetchNewTokens(urlApi)
Expand Down
24 changes: 18 additions & 6 deletions test/testcommon/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,26 @@ func (t *TestAPI) startTestGateway() {
log.Fatal(err)
}

vc, err := vocone.NewVocone(storageDir, &oracle)
if err != nil {
var err error
if t.VC, err = vocone.NewVocone(storageDir, &oracle); err != nil {
log.Fatal(err)
}
t.VC.SetBlockTimeTarget(time.Second)
t.VC.SetBlockSize(500)
// Set treasurer so we can mint tokens
treasurer := ethereum.NewSignKeys()
if err := treasurer.Generate(); err != nil {
log.Fatal(err)
}
if err := t.VC.SetTreasurer(treasurer.Address()); err != nil {
log.Fatal(err)
}
// Set transaction costs
if err := t.VC.SetBulkTxCosts(10); err != nil {
log.Fatal(err)
}
vc.SetBlockTimeTarget(time.Second)
vc.SetBlockSize(500)
go vc.Start()
if err = vc.EnableAPI(TestHost, TestGWPort, TestGWPath); err != nil {
go t.VC.Start()
if err := t.VC.EnableAPI(TestHost, TestGWPort, TestGWPath); err != nil {
log.Fatal(err)
}
t.Gateway = "http://" + TestHost + ":" + strconv.Itoa(TestGWPort) + TestGWPath
Expand Down
62 changes: 53 additions & 9 deletions urlapi/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,18 @@ func (u *URLAPI) createOrganizationHandler(msg *bearerstdapi.BearerStandardAPIda
return fmt.Errorf("could not set entity metadata: %w", err)
}

_, balance, _, err := u.vocClient.GetAccount(u.faucet.Address().Bytes())
if err != nil {
return fmt.Errorf("could not get faucet account: %w", err)
}

if balance < u.vocClient.AcctTxCost*vocclient.DefaultFaucetMultiplier {
return fmt.Errorf("faucet does not have enough tokens. Balance is %d", balance)
}

// Create the new account on the Vochain
if err = u.vocClient.SetAccountInfo(ethSignKeys, metaURI, 0); err != nil {
if err = u.vocClient.SetAccountInfo(ethSignKeys,
u.faucet, metaURI, 0); err != nil {
return fmt.Errorf("could not create account on the vochain: %w", err)
}

Expand All @@ -261,8 +271,11 @@ func (u *URLAPI) createOrganizationHandler(msg *bearerstdapi.BearerStandardAPIda
return err
}

resp := types.APIResponse{APIToken: orgApiToken,
OrganizationID: ethSignKeys.Address().Bytes(), TxHash: txHash}
resp := types.APIResponse{
APIToken: orgApiToken,
OrganizationID: ethSignKeys.Address().Bytes(),
TxHash: txHash,
}

return sendResponse(resp, ctx)
}
Expand Down Expand Up @@ -412,12 +425,21 @@ func (u *URLAPI) setOrganizationMetadataHandler(msg *bearerstdapi.BearerStandard
return err
}

_, _, nonce, err := u.vocClient.GetAccount(orgInfo.entityID)
_, balance, nonce, err := u.vocClient.GetAccount(orgInfo.entityID)
if err != nil {
return fmt.Errorf("could not get account info: %w", err)
}

if err := u.vocClient.SetAccountInfo(entitySignKeys, metaURI, nonce); err != nil {
// If account balance is below threshold, allocate more tokens.
// This is for future uses, there should still be enough for this current process.
if balance < u.vocClient.AcctTxCost*vocclient.TxOperationsThreshold {
if err := u.vocClient.CollectFaucet(entitySignKeys, u.faucet); err != nil {
return err
}
}

if err := u.vocClient.SetAccountInfo(entitySignKeys, u.faucet, metaURI,
nonce); err != nil {
return fmt.Errorf("could not update account metadata uri: %w", err)
}

Expand Down Expand Up @@ -612,11 +634,21 @@ func (u *URLAPI) createProcessHandler(msg *bearerstdapi.BearerStandardAPIdata,
}

// Fetch account transaction nonce
_, _, nonce, err := u.vocClient.GetAccount(orgInfo.entityID)
_, balance, nonce, err := u.vocClient.GetAccount(orgInfo.entityID)
if err != nil {
return fmt.Errorf("could not get account info: %w", err)
}

// If account balance is below threshold, allocate more tokens.
// This is for future uses, there should still be enough for this current process.
if balance < u.vocClient.AcctTxCost*vocclient.TxOperationsThreshold {
log.Infof("account balance is %d, requesting %d more tokens",
balance, u.vocClient.AcctTxCost*vocclient.DefaultFaucetMultiplier)
if err := u.vocClient.CollectFaucet(entitySignKeys, u.faucet); err != nil {
return err
}
}

if err = u.vocClient.CreateProcess(&models.Process{
ProcessId: processID,
EntityId: orgInfo.entityID,
Expand Down Expand Up @@ -666,8 +698,12 @@ func (u *URLAPI) createProcessHandler(msg *bearerstdapi.BearerStandardAPIdata,
return err
}

return sendResponse(types.APIResponse{
ElectionID: processID, TxHash: txHash}, ctx)
return sendResponse(
types.APIResponse{
ElectionID: processID,
TxHash: txHash,
},
ctx)
}

// GET https://server/v1/priv/organizations/<organizationId>/elections/signed
Expand Down Expand Up @@ -845,11 +881,19 @@ func (u *URLAPI) setProcessStatusHandler(
}

// Fetch account transaction nonce
_, _, nonce, err := u.vocClient.GetAccount(organization.EthAddress)
_, balance, nonce, err := u.vocClient.GetAccount(organization.EthAddress)
if err != nil {
return fmt.Errorf("could not get account info: %w", err)
}

// If account balance is below threshold, allocate more tokens.
// This is for future uses, there should still be enough for this current process.
if balance < u.vocClient.AcctTxCost*vocclient.TxOperationsThreshold {
if err := u.vocClient.CollectFaucet(entitySignKeys, u.faucet); err != nil {
return err
}
}

if err = u.vocClient.SetProcessStatus(processID, &status, entitySignKeys, nonce); err != nil {
return fmt.Errorf("could not set process status %d: %w", status, err)
}
Expand Down
6 changes: 6 additions & 0 deletions urlapi/urlapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go.vocdoni.io/api/database/transactions"
"go.vocdoni.io/api/types"
"go.vocdoni.io/api/vocclient"
"go.vocdoni.io/dvote/crypto/ethereum"
dvotedb "go.vocdoni.io/dvote/db"
"go.vocdoni.io/dvote/httprouter"
"go.vocdoni.io/dvote/httprouter/bearerstdapi"
Expand All @@ -38,6 +39,7 @@ type URLAPI struct {
db database.Database
kv *transactions.TxCacheDB
vocClient *vocclient.Client
faucet *ethereum.SignKeys
}

func NewURLAPI(router *httprouter.HTTProuter,
Expand Down Expand Up @@ -88,6 +90,10 @@ func NewURLAPI(router *httprouter.HTTProuter,
return &urlapi, nil
}

func (u *URLAPI) SetFaucet(faucet *ethereum.SignKeys) {
u.faucet = faucet
}

func (u *URLAPI) EnableVotingServiceHandlers(db database.Database,
client *vocclient.Client, kv dvotedb.Database) error {
if db == nil {
Expand Down
Loading

0 comments on commit 93aa0b0

Please sign in to comment.