Skip to content

Commit

Permalink
feature: extended sign included faucet package in more tx types (#13)
Browse files Browse the repository at this point in the history
* proto dependencies updated, tx sign extended to include faucet package in more tx with some formal checks
* include the election price calculation for new process and set process txs
* include tx costs from the vochain and increase it for specific txs such as create or some set election types
  • Loading branch information
lucasmenendez authored Sep 25, 2024
1 parent 709e70e commit 83bb3af
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 17 deletions.
19 changes: 17 additions & 2 deletions account/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import (
"go.vocdoni.io/dvote/crypto/ethereum"
"go.vocdoni.io/dvote/log"
"go.vocdoni.io/dvote/vochain"
"go.vocdoni.io/dvote/vochain/state/electionprice"
"go.vocdoni.io/proto/build/go/models"
)

// Account handles the account operations that include signing transactions, creating faucet packages, etc.
type Account struct {
client *apiclient.HTTPclient
signer *ethereum.SignKeys

TxCosts map[models.TxType]uint64
ElectionPriceCalc *electionprice.Calculator
}

// New creates a new account with the given private key and API endpoint.
Expand Down Expand Up @@ -50,9 +54,20 @@ func New(privateKey string, apiEndpoint string) (*Account, error) {
"address", account.Address,
"balance", account.Balance,
)
// initialize the election price calculator
electionPriceCalc, err := InitElectionPriceCalculator(apiEndpoint)
if err != nil {
return nil, fmt.Errorf("failed to initialize election price calculator: %w", err)
}
txCosts, err := vochainTxCosts(apiEndpoint)
if err != nil {
return nil, fmt.Errorf("failed to get transaction costs: %w", err)
}
return &Account{
client: apiClient,
signer: &signer,
client: apiClient,
signer: &signer,
TxCosts: txCosts,
ElectionPriceCalc: electionPriceCalc,
}, nil
}

Expand Down
102 changes: 102 additions & 0 deletions account/price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package account

import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"

"go.vocdoni.io/dvote/api"
"go.vocdoni.io/dvote/vochain/genesis"
"go.vocdoni.io/dvote/vochain/state/electionprice"
"go.vocdoni.io/proto/build/go/models"
)

const (
// electionPriceEndpoint is the endpoint to get the election price factors
// from the Vochain.
electionPriceEndpoint = "/chain/info/electionPriceFactors"
// txCostsEndpoint is the endpoint to get the transaction costs from the
// Vochain.
txCostsEndpoint = "/chain/transactions/cost"
)

// InitElectionPriceCalculator initializes the election price calculator with
// the factors from the Vochain. It returns the election price calculator or an
// error if it fails to get the factors.
func InitElectionPriceCalculator(vochainURI string) (*electionprice.Calculator, error) {
basePrice, capacity, factors, err := electionPriceFactors(vochainURI)
if err != nil {
return nil, fmt.Errorf("failed to get election price factors: %w", err)
}
electionPriceCalc := electionprice.NewElectionPriceCalculator(factors)
electionPriceCalc.SetBasePrice(basePrice)
electionPriceCalc.SetCapacity(capacity)
return electionPriceCalc, nil
}

// ElectionPriceFactors returns the election price factors from the Vochain. It
// returns the base price, capacity, and factors. If there is an error, it
// returns the error.
func electionPriceFactors(vochainURI string) (uint64, uint64, electionprice.Factors, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
// create the request to get the election price factors
url := vochainURI + electionPriceEndpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return 0, 0, electionprice.Factors{}, fmt.Errorf("failed to create request: %w", err)
}
// send the request
resp, err := http.DefaultClient.Do(req)
if err != nil {
return 0, 0, electionprice.Factors{}, fmt.Errorf("failed to send request: %w", err)
}
defer func() {
_ = resp.Body.Close()
}()
// parse the response
if resp.StatusCode != http.StatusOK {
return 0, 0, electionprice.Factors{}, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
var data electionprice.Calculator
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return 0, 0, electionprice.Factors{}, fmt.Errorf("failed to decode response: %w", err)
}
return data.BasePrice, data.Capacity, data.Factors, nil
}

// vochainTxCosts returns the transaction costs from the Vochain. It returns the
// transaction costs or an error if it fails to get them.
func vochainTxCosts(vochainURI string) (map[models.TxType]uint64, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
// create the request to get the transactions costs
url := vochainURI + txCostsEndpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
// send the request
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send request: %w", err)
}
defer func() {
_ = resp.Body.Close()
}()
// parse the response
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
var strTxCosts api.Transaction
if err := json.NewDecoder(resp.Body).Decode(&strTxCosts); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}
txCosts := make(map[models.TxType]uint64)
for strType, cost := range strTxCosts.Costs {
txCosts[genesis.TxCostNameToTxType(strType)] = cost
}
return txCosts, nil
}
1 change: 1 addition & 0 deletions api/errors_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ var (
ErrMarshalingServerJSONFailed = Error{Code: 50001, HTTPstatus: http.StatusInternalServerError, Err: fmt.Errorf("marshaling (server-side) JSON failed")}
ErrGenericInternalServerError = Error{Code: 50002, HTTPstatus: http.StatusInternalServerError, Err: fmt.Errorf("internal server error")}
ErrCouldNotCreateFaucetPackage = Error{Code: 50003, HTTPstatus: http.StatusInternalServerError, Err: fmt.Errorf("could not create faucet package")}
ErrVochainRequestFailed = Error{Code: 50004, HTTPstatus: http.StatusInternalServerError, Err: fmt.Errorf("vochain request failed")}
)
Loading

0 comments on commit 83bb3af

Please sign in to comment.