Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend faucet package support for other transactions #1380

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions cmd/end2endtest/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,16 @@ func testCreateAndSetAccount(api *apiclient.HTTPclient, fp *models.FaucetPackage
return err
}

// get the create account transaction cost
txCost, err := api.TransactionCost(models.TxType_CREATE_ACCOUNT)
if err != nil {
return fmt.Errorf("error fetching transaction cost: %w", err)
}

// create account for bob with faucet package from alice
afp, err := vochain.GenerateFaucetPackage(alice, bob.Address(), aliceAcc.Balance/2)
if err != nil {
return fmt.Errorf("error in GenerateFaucetPackage %v", err)
return fmt.Errorf("error in GenerateFaucetPackage %w", err)
}

bobAcc, err := ensureAccountExists(api.Clone(hex.EncodeToString(bob.PrivateKey())), afp)
Expand All @@ -134,9 +140,9 @@ func testCreateAndSetAccount(api *apiclient.HTTPclient, fp *models.FaucetPackage
}

// check balance added from payload
if bobAcc.Balance != aliceAcc.Balance/2 {
if bobAcc.Balance+txCost != aliceAcc.Balance/2 {
return fmt.Errorf("expected balance for bob (%s) is %d but got %d",
bob.Address(), aliceAcc.Balance/2, bobAcc.Balance)
bob.Address(), (aliceAcc.Balance/2)-txCost, bobAcc.Balance)
}
log.Infow("account for bob successfully created with payload signed by alice",
"alice", alice.Address(), "bob", bobAcc)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a
github.com/vocdoni/storage-proofs-eth-go v0.1.6
go.mongodb.org/mongo-driver v1.12.1
go.vocdoni.io/proto v1.15.8
go.vocdoni.io/proto v1.15.10-0.20240903073233-86144b1e2165
golang.org/x/crypto v0.26.0
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
golang.org/x/net v0.28.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1598,8 +1598,8 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.vocdoni.io/proto v1.15.8 h1:I5HVHffQwXyp0jootnCVj83+PoJ8L703RJ2CFSPTa2Q=
go.vocdoni.io/proto v1.15.8/go.mod h1:oi/WtiBFJ6QwNDv2aUQYwOnUKzYuS/fBqXF8xDNwcGo=
go.vocdoni.io/proto v1.15.10-0.20240903073233-86144b1e2165 h1:7r0RaKfYyGCVh1qeS2795jOk7WnpP9CI0IJOB/lxFVk=
go.vocdoni.io/proto v1.15.10-0.20240903073233-86144b1e2165/go.mod h1:oi/WtiBFJ6QwNDv2aUQYwOnUKzYuS/fBqXF8xDNwcGo=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
Expand Down
10 changes: 9 additions & 1 deletion test/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,15 @@ func createAccount(t testing.TB, c *testutil.TestHTTPclient,
metaData, err := json.Marshal(meta)
qt.Assert(t, err, qt.IsNil)

fp, err := vochain.GenerateFaucetPackage(server.Account, signer.Address(), initialBalance)
// get the txCost for the create account transacction
data, statusCode := c.Request("GET", nil, "chain", "transactions", "cost")
qt.Assert(t, statusCode, qt.Equals, 200)
var txCosts api.Transaction
qt.Assert(t, json.Unmarshal(data, &txCosts), qt.IsNil)
txCost := txCosts.Costs[genesis.TxTypeToCostName(models.TxType_CREATE_ACCOUNT)]

// add the tx cost to the initialBalance for the faucet package
fp, err := vochain.GenerateFaucetPackage(server.Account, signer.Address(), initialBalance+txCost)
qt.Assert(t, err, qt.IsNil)

// transaction
Expand Down
200 changes: 158 additions & 42 deletions vochain/account_test.go

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions vochain/state/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package state

import (
"bytes"
"encoding/hex"
"errors"
"fmt"

Expand Down Expand Up @@ -102,6 +103,20 @@ func (v *State) GetAccount(address common.Address, committed bool) (*Account, er
return &acc, acc.Unmarshal(raw)
}

// AccountBalance retrieves the Account.Balance for an address.
// Returns 0 and no error if the account does not exist.
// Committed is relative to the state on which the function is executed.
func (v *State) AccountBalance(address common.Address, committed bool) (uint64, error) {
acc, err := v.GetAccount(address, committed)
if err != nil {
return 0, err
}
if acc == nil {
return 0, nil
}
return acc.Balance, nil
}

// CountAccounts returns the overall number of accounts the vochain has
func (v *State) CountAccounts(committed bool) (uint64, error) {
// TODO: Once statedb.TreeView.Size() works, replace this by that.
Expand Down Expand Up @@ -310,16 +325,16 @@ func (v *State) SetAccountDelegate(accountAddr common.Address,
}
switch txType {
case models.TxType_ADD_DELEGATE_FOR_ACCOUNT:
log.Debugf("adding delegates %+v for account %s", delegateAddrs, accountAddr)
for _, delegate := range delegateAddrs {
log.Debugw("adding delegate", "account", accountAddr.Hex(), "delegate", hex.EncodeToString(delegate))
if err := acc.AddDelegate(common.BytesToAddress(delegate)); err != nil {
return fmt.Errorf("cannot add delegate, AddDelegate: %w", err)
}
}
return v.SetAccount(accountAddr, acc)
case models.TxType_DEL_DELEGATE_FOR_ACCOUNT:
log.Debugf("deleting delegates %+v for account %s", delegateAddrs, accountAddr)
for _, delegate := range delegateAddrs {
log.Debugw("deleting delegate", "account", accountAddr.Hex(), "delegate", hex.EncodeToString(delegate))
if err := acc.DelDelegate(common.BytesToAddress(delegate)); err != nil {
return fmt.Errorf("cannot delete delegate, DelDelegate: %w", err)
}
Expand Down
56 changes: 6 additions & 50 deletions vochain/transaction/account_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package transaction

import (
"bytes"
"encoding/binary"
"errors"
"fmt"

Expand All @@ -13,7 +12,6 @@ import (
vstate "go.vocdoni.io/dvote/vochain/state"
"go.vocdoni.io/dvote/vochain/transaction/vochaintx"
"go.vocdoni.io/proto/build/go/models"
"google.golang.org/protobuf/proto"
)

// CreateAccountTxCheck checks if an account creation tx is valid
Expand Down Expand Up @@ -56,56 +54,13 @@ func (t *TransactionHandler) CreateAccountTxCheck(vtx *vochaintx.Tx) error {
if err != nil {
return fmt.Errorf("cannot get tx cost: %w", err)
}
if txCost == 0 {
return nil
}
if tx.FaucetPackage == nil {
return fmt.Errorf("invalid faucet package provided")
}
if tx.FaucetPackage.Payload == nil {
return fmt.Errorf("invalid faucet package payload")
}
faucetPayload := &models.FaucetPayload{}
if err := proto.Unmarshal(tx.FaucetPackage.Payload, faucetPayload); err != nil {
return fmt.Errorf("could not unmarshal faucet package: %w", err)
}
if faucetPayload.Amount == 0 {
return fmt.Errorf("invalid faucet payload amount provided")
}
if faucetPayload.To == nil {
return fmt.Errorf("invalid to address provided")
}
if !bytes.Equal(faucetPayload.To, txSenderAddress.Bytes()) {
return fmt.Errorf("payload to and tx sender missmatch (%x != %x)",
faucetPayload.To, txSenderAddress.Bytes())
}
issuerAddress, err := ethereum.AddrFromSignature(tx.FaucetPackage.Payload, tx.FaucetPackage.Signature)
// Check the faucet package
canPayForTx, err := t.checkFaucetPackageAndTransfer(tx.FaucetPackage, txCost, txSenderAddress, vtx.TxID[:], false)
if err != nil {
return fmt.Errorf("cannot extract issuer address from faucet package vtx.Signature: %w", err)
}
issuerAcc, err := t.state.GetAccount(issuerAddress, false)
if err != nil {
return fmt.Errorf("cannot get faucet issuer address account: %w", err)
}
if issuerAcc == nil {
return fmt.Errorf("the account signing the faucet payload does not exist (%s)", issuerAddress)
}
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, faucetPayload.Identifier)
keyHash := ethereum.HashRaw(append(issuerAddress.Bytes(), b...))
used, err := t.state.FaucetNonce(keyHash, false)
if err != nil {
return fmt.Errorf("cannot check if faucet payload already used: %w", err)
}
if used {
return fmt.Errorf("faucet payload %x already used", keyHash)
return err
}
if issuerAcc.Balance < faucetPayload.Amount+txCost {
return fmt.Errorf(
"issuer address does not have enough balance %d, required %d",
issuerAcc.Balance,
faucetPayload.Amount+txCost,
)
if !canPayForTx {
return fmt.Errorf("faucet package is not enough for paying for the transaction cost")
}
return nil
}
Expand All @@ -126,6 +81,7 @@ func (t *TransactionHandler) SetAccountDelegateTxCheck(vtx *vochaintx.Tx) error
if len(tx.Delegates) == 0 {
return fmt.Errorf("invalid delegates")
}

txSenderAccount, txSenderAddr, err := t.checkAccountCanPayCost(tx.Txtype, vtx)
if err != nil {
return err
Expand Down
Loading
Loading