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

testnet PoW #969

Merged
merged 27 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5f219bf
Adds fee burning and checks
grarco Dec 23, 2022
0b51129
Fixes fee value in tx contruction
grarco Dec 23, 2022
b934636
Fixes process proposal fee token
grarco Dec 23, 2022
0081be6
Fixes unit tests
grarco Dec 23, 2022
db0cac3
changelog: add #962
grarco Dec 27, 2022
d5cb262
Adds const and default token to basic fee
grarco Dec 30, 2022
9976043
Add `max_proposal_bytes` ledger param
sug0 Dec 22, 2022
5dd1273
Fix consensus params config for ABCI++
sug0 Jan 3, 2023
ee159ff
wasm: update checksums.json
juped Jan 10, 2023
80292e6
changelog: add #975
juped Jan 10, 2023
614e6ae
Merge remote-tracking branch 'namada/tiago/main/max-block-size-genesi…
juped Jan 10, 2023
2215a72
Merge remote-tracking branch 'namada/grarco/basic-fee' (#962) into main
juped Jan 10, 2023
535e9ab
re-export `namada` from `namada_tests` for `namada_core` dev-deps
tzemanovic Dec 28, 2022
19f1373
core/ledger: add testnet_pow module
tzemanovic Dec 30, 2022
72d9f36
storage_api/lazy_map: export `get_data_key` fn for client
tzemanovic Dec 30, 2022
9ca9c94
add "mainnet" feature flag, off by default for now
tzemanovic Dec 30, 2022
19134a7
genesis: add faucet_pow_difficulty and faucet_withdrawal_limit
tzemanovic Dec 30, 2022
33832d4
add `faucet_account` parameter and set it from `init_chain` if found
tzemanovic Dec 30, 2022
473c43a
shell/init_chain: init faucet storage, if used
tzemanovic Dec 30, 2022
2225839
validate PoW in mempool, proposal and finalize and keep the result
tzemanovic Dec 30, 2022
c22a8e1
expose the `has_valid_pow` result via VP wasm host env
tzemanovic Dec 30, 2022
fff5b1e
wasm/vp_testnet_faucet: check PoW, use withdrawal_limit set in storage
tzemanovic Dec 30, 2022
bb85eaf
ledger/queries/vp: add testnet pow and faucet methods
tzemanovic Dec 30, 2022
50630e3
client/tx and signing: add wrapper signer balance check and add PoW
tzemanovic Dec 30, 2022
b4aaeb9
test/e2e: add a case to withdraw from PoW faucet
tzemanovic Dec 26, 2022
c36c0ac
changelog: add #969
tzemanovic Dec 30, 2022
5e26b4d
wasm: update checksums.json
juped Jan 10, 2023
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
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/962-basic-fee.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added a basic fee implementation for testnet.
([#962](https://github.com/anoma/namada/pull/962))
4 changes: 4 additions & 0 deletions .changelog/unreleased/improvements/969-testnet-pow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Added an optional PoW challenge to the wrapper transactions for testnets,
to allow to submit transactions without having enough balance to cover
the minimum transaction fee and to withdraw tokens from a faucet account.
([#969](https://github.com/anoma/namada/pull/969))
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/975-max-block-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add a max_proposal_bytes parameter to the ledger.
([#975](https://github.com/anoma/namada/pull/975))
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ check-abcipp:
--no-default-features \
--features "abcipp ibc-mocks-abcipp testing"

check-mainnet:
$(cargo) check --workspace --features "mainnet"

clippy-wasm = $(cargo) +$(nightly) clippy --manifest-path $(wasm)/Cargo.toml --all-targets -- -D warnings

clippy:
Expand Down Expand Up @@ -76,6 +79,9 @@ clippy-abcipp:
make -C $(wasms) clippy && \
$(foreach wasm,$(wasm_templates),$(clippy-wasm) && ) true

clippy-mainnet:
$(cargo) +$(nightly) clippy --all-targets --features "mainnet" -- -D warnings

clippy-fix:
$(cargo) +$(nightly) clippy --fix -Z unstable-options --all-targets --allow-dirty --allow-staged

Expand Down Expand Up @@ -143,6 +149,13 @@ test-unit:
--skip e2e \
-Z unstable-options --report-time

test-unit-mainnet:
$(cargo) test \
--features "mainnet" \
$(TEST_FILTER) -- \
--skip e2e \
-Z unstable-options --report-time

test-unit-debug:
$(debug-cargo) test \
$(TEST_FILTER) -- \
Expand Down
3 changes: 3 additions & 0 deletions apps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ path = "src/bin/namada-wallet/main.rs"

[features]
default = ["std", "abciplus"]
mainnet = [
"namada/mainnet",
]
dev = ["namada/dev"]
std = ["ed25519-consensus/std", "rand/std", "rand_core/std"]
# for integration tests and test utilies
Expand Down
46 changes: 44 additions & 2 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use masp_primitives::primitives::ViewingKey;
use masp_primitives::sapling::Node;
use masp_primitives::transaction::components::Amount;
use masp_primitives::zip32::ExtendedFullViewingKey;
#[cfg(not(feature = "mainnet"))]
use namada::core::ledger::testnet_pow;
use namada::ledger::events::Event;
use namada::ledger::governance::parameters::GovParams;
use namada::ledger::governance::storage as gov_storage;
Expand Down Expand Up @@ -389,15 +391,23 @@ fn extract_payload(
let privkey = <EllipticCurve as PairingEngine>::G2Affine::prime_subgroup_generator();
extract_payload(
Tx::from(match wrapper_tx.decrypt(privkey) {
Ok(tx) => DecryptedTx::Decrypted(tx),
Ok(tx) => DecryptedTx::Decrypted {
tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
},
_ => DecryptedTx::Undecryptable(wrapper_tx.clone()),
}),
wrapper,
transfer,
);
*wrapper = Some(wrapper_tx);
}
Ok(TxType::Decrypted(DecryptedTx::Decrypted(tx))) => {
Ok(TxType::Decrypted(DecryptedTx::Decrypted {
tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: _,
})) => {
let empty_vec = vec![];
let tx_data = tx.data.as_ref().unwrap_or(&empty_vec);
let _ = SignedTxData::try_from_slice(tx_data).map(|signed| {
Expand Down Expand Up @@ -2005,6 +2015,38 @@ pub async fn known_address(
}
}

#[cfg(not(feature = "mainnet"))]
/// Check if the given address is a testnet faucet account address.
pub async fn is_faucet_account(
address: &Address,
ledger_address: TendermintAddress,
) -> bool {
let client = HttpClient::new(ledger_address).unwrap();
unwrap_client_response(RPC.vp().is_faucet(&client, address).await)
}

#[cfg(not(feature = "mainnet"))]
/// Get faucet account address, if any is setup for the network.
pub async fn get_faucet_address(
ledger_address: TendermintAddress,
) -> Option<Address> {
let client = HttpClient::new(ledger_address).unwrap();
unwrap_client_response(RPC.vp().get_faucet_address(&client).await)
}

#[cfg(not(feature = "mainnet"))]
/// Obtain a PoW challenge for a withdrawal from a testnet faucet account, if
/// any is setup for the network.
pub async fn get_testnet_pow_challenge(
source: Address,
ledger_address: TendermintAddress,
) -> testnet_pow::Challenge {
let client = HttpClient::new(ledger_address).unwrap();
unwrap_client_response(
RPC.vp().testnet_pow_challenge(&client, source).await,
)
}

/// Accumulate slashes starting from `epoch_start` until (optionally)
/// `withdraw_epoch` and apply them to the token amount `delta`.
fn apply_slashes(
Expand Down
65 changes: 61 additions & 4 deletions apps/src/lib/client/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use namada::proto::Tx;
use namada::types::address::{Address, ImplicitAddress};
use namada::types::key::*;
use namada::types::storage::Epoch;
use namada::types::transaction::{hash_tx, Fee, WrapperTx};
use namada::types::token;
use namada::types::token::Amount;
use namada::types::transaction::{hash_tx, Fee, WrapperTx, MIN_FEE};

use super::rpc;
use crate::cli::context::{WalletAddress, WalletKeypair};
use crate::cli::{self, args, Context};
use crate::client::tendermint_rpc_types::TxBroadcastData;
use crate::facade::tendermint_config::net::Address as TendermintAddress;
use crate::facade::tendermint_rpc::HttpClient;
use crate::wallet::Wallet;

/// Find the public key for the given address and try to load the keypair
Expand Down Expand Up @@ -145,6 +148,7 @@ pub async fn sign_tx(
tx: Tx,
args: &args::Tx,
default: TxSigningKey,
#[cfg(not(feature = "mainnet"))] requires_pow: bool,
) -> (Context, TxBroadcastData) {
let keypair = tx_signer(&mut ctx, args, default).await;
let tx = tx.sign(&keypair);
Expand All @@ -156,7 +160,16 @@ pub async fn sign_tx(
let broadcast_data = if args.dry_run {
TxBroadcastData::DryRun(tx)
} else {
sign_wrapper(&ctx, args, epoch, tx, &keypair).await
sign_wrapper(
&ctx,
args,
epoch,
tx,
&keypair,
#[cfg(not(feature = "mainnet"))]
requires_pow,
)
.await
};
(ctx, broadcast_data)
}
Expand All @@ -170,19 +183,63 @@ pub async fn sign_wrapper(
epoch: Epoch,
tx: Tx,
keypair: &common::SecretKey,
#[cfg(not(feature = "mainnet"))] requires_pow: bool,
) -> TxBroadcastData {
let fee_amount = Amount::from(MIN_FEE);
let fee_token = ctx.get(&args.fee_token);
let source = Address::from(&keypair.ref_to());
let balance_key = token::balance_key(&fee_token, &source);
let client = HttpClient::new(args.ledger_address.clone()).unwrap();
let balance =
rpc::query_storage_value::<token::Amount>(&client, &balance_key)
.await
.unwrap_or_default();
if balance < fee_amount {
eprintln!(
"The wrapper transaction source doesn't have enough balance to \
pay fee {fee_amount}, got {balance}."
);
if !args.force && cfg!(feature = "mainnet") {
cli::safe_exit(1);
}
}

#[cfg(not(feature = "mainnet"))]
// A PoW solution can be used to allow zero-fee testnet transactions
let pow_solution: Option<namada::core::ledger::testnet_pow::Solution> = {
// If the address derived from the keypair doesn't have enough balance
// to pay for the fee, allow to find a PoW solution instead.
if requires_pow || balance < fee_amount {
println!("The transaction requires to a PoW challenge.");
// Obtain a PoW challenge for faucet withdrawal
let challenge = rpc::get_testnet_pow_challenge(
source,
args.ledger_address.clone(),
)
.await;

// Solve the solution, this blocks until a solution is found
let solution = challenge.solve();
Some(solution)
} else {
None
}
};

let tx = {
WrapperTx::new(
Fee {
amount: args.fee_amount,
token: ctx.get(&args.fee_token),
amount: fee_amount,
token: fee_token,
},
keypair,
epoch,
args.gas_limit.clone(),
tx,
// TODO: Actually use the fetched encryption key
Default::default(),
#[cfg(not(feature = "mainnet"))]
pow_solution,
)
};

Expand Down
Loading