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

Enable transaction fees for multinode-demo/ and net/ #4527

Merged
merged 2 commits into from
Jun 4, 2019
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
5 changes: 1 addition & 4 deletions ci/localnet-sanity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,7 @@ flag_error() {
}

if ! $skipSetup; then
multinode-demo/setup.sh \
--hashes-per-tick auto \
--lamports-per-signature 1 \

multinode-demo/setup.sh --hashes-per-tick auto
else
verifyLedger
fi
Expand Down
28 changes: 17 additions & 11 deletions multinode-demo/fullnode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ setup_validator_accounts() {
declare vote_keypair_path=$3
declare stake_keypair_path=$4
declare storage_keypair_path=$5
declare stake=$6
declare node_lamports=$6
declare stake_lamports=$7

declare node_pubkey
node_pubkey=$($solana_keygen pubkey "$node_keypair_path")
Expand All @@ -98,15 +99,15 @@ setup_validator_accounts() {
else
# Fund the node with enough tokens to fund its Vote, Staking, and Storage accounts
declare fees=100 # TODO: No hardcoded transaction fees, fetch the current cluster fees
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" airdrop $((stake*2+fees)) || return $?
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" airdrop $((node_lamports+stake_lamports+fees)) || return $?

# Fund the vote account from the node, with the node as the node_pubkey
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" \
create-vote-account "$vote_pubkey" "$node_pubkey" 1 || return $?

# Fund the stake account from the node, with the node as the node_pubkey
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" \
create-stake-account "$stake_pubkey" "$stake" || return $?
create-stake-account "$stake_pubkey" "$stake_lamports" || return $?

# Delegate the stake. The transaction fee is paid by the node but the
# transaction must be signed by the stake_keypair
Expand All @@ -127,22 +128,25 @@ setup_validator_accounts() {
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" \
show-storage-account "$storage_pubkey"

echo "Identity account balance:"
$solana_wallet --keypair "$identity_keypair_path" --url "http://$entrypoint_ip:8899" balance
echo "========================================================================"
return 0
}

setup_replicator_account() {
declare entrypoint_ip=$1
declare node_keypair_path=$2
declare storage_keypair_path=$3
declare stake=$4
declare node_lamports=$4

declare storage_pubkey
storage_pubkey=$($solana_keygen pubkey "$storage_keypair_path")

if [[ -f "$node_keypair_path".configured ]]; then
echo "Replicator account has already been configured"
else
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" airdrop "$stake" || return $?
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" airdrop "$node_lamports" || return $?

# Setup replicator storage account
$solana_wallet --keypair "$node_keypair_path" --url "http://$entrypoint_ip:8899" \
Expand All @@ -166,7 +170,8 @@ ledger_not_setup() {

args=()
node_type=validator
stake=42 # number of lamports to assign as stake
node_lamports=424242 # number of lamports to assign the node for transaction fees
stake_lamports=42 # number of lamports to assign as stake
poll_for_new_genesis_block=0
label=
identity_keypair_path=
Expand Down Expand Up @@ -194,7 +199,7 @@ while [[ -n $1 ]]; do
poll_for_new_genesis_block=1
shift
elif [[ $1 = --blockstream ]]; then
stake=0
stake_lamports=0
args+=("$1" "$2")
shift 2
elif [[ $1 = --identity ]]; then
Expand All @@ -208,7 +213,7 @@ while [[ -n $1 ]]; do
args+=("$1" "$2")
shift 2
elif [[ $1 = --stake ]]; then
stake="$2"
stake_lamports="$2"
shift 2
elif [[ $1 = --no-voting ]]; then
args+=("$1")
Expand Down Expand Up @@ -387,19 +392,20 @@ while true; do

trap '[[ -n $pid ]] && kill "$pid" >/dev/null 2>&1 && wait "$pid"' INT TERM ERR

if ((stake)); then
if ((stake_lamports)); then
if [[ $node_type = validator ]]; then
setup_validator_accounts "${entrypoint_address%:*}" \
"$identity_keypair_path" \
"$vote_keypair_path" \
"$stake_keypair_path" \
"$storage_keypair_path" \
"$stake"
"$node_lamports" \
"$stake_lamports"
elif [[ $node_type = replicator ]]; then
setup_replicator_account "${entrypoint_address%:*}" \
"$identity_keypair_path" \
"$storage_keypair_path" \
"$stake"
"$node_lamports"
fi
fi

Expand Down
3 changes: 2 additions & 1 deletion multinode-demo/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ default_arg --bootstrap-storage-keypair "$SOLANA_CONFIG_DIR"/bootstrap-leader-st
default_arg --ledger "$SOLANA_RSYNC_CONFIG_DIR"/ledger
default_arg --mint "$SOLANA_CONFIG_DIR"/mint-keypair.json
default_arg --lamports 100000000000000
default_arg --bootstrap-leader-lamports 424242
default_arg --lamports-per-signature 1
default_arg --hashes-per-tick sleep

$solana_genesis "${args[@]}"

test -d "$SOLANA_RSYNC_CONFIG_DIR"/ledger
Expand Down
3 changes: 1 addition & 2 deletions net/remote/remote-node.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ genesisOptions="$8"
set +x
export RUST_LOG

# Use a very large stake (relative to the default multinode-demo/ stake of 43)
# Use a very large stake (relative to the default multinode-demo/ stake of 42)
# for the testnet validators setup by net/. This make it less likely that
# low-staked ephemeral validator a random user may attach to testnet will cause
# trouble
Expand Down Expand Up @@ -78,7 +78,6 @@ local|tar)
set -x
if [[ $skipSetup != true ]]; then
args=(
--bootstrap-leader-lamports "$stake"
--bootstrap-leader-stake-lamports "$stake"
)
# shellcheck disable=SC2206 # Do not want to quote $genesisOptions
Expand Down
29 changes: 25 additions & 4 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ pub struct Bank {
/// The pubkey to send transactions fees to.
collector_id: Pubkey,

/// Fees that have been collected
#[serde(serialize_with = "serialize_atomicusize")]
#[serde(deserialize_with = "deserialize_atomicusize")]
collector_fees: AtomicUsize, // TODO: Use AtomicU64 if/when available

/// An object to calculate transaction fees.
pub fee_calculator: FeeCalculator,

Expand Down Expand Up @@ -380,6 +385,11 @@ impl Bank {
let mut hash = self.hash.write().unwrap();

if *hash == Hash::default() {
let collector_fees = self.collector_fees.load(Ordering::SeqCst) as u64;
if collector_fees != 0 {
self.deposit(&self.collector_id, collector_fees);
}

// freeze is a one-way trip, idempotent
*hash = self.hash_internal_state();
true
Expand Down Expand Up @@ -899,7 +909,9 @@ impl Bank {
}
})
.collect();
self.deposit(&self.collector_id, fees);

self.collector_fees
.fetch_add(fees as usize, Ordering::Relaxed);
results
}

Expand Down Expand Up @@ -1482,32 +1494,40 @@ mod tests {

let tx =
system_transaction::transfer(&mint_keypair, &key1.pubkey(), 2, genesis_block.hash());

let initial_balance = bank.get_balance(&leader);
assert_eq!(bank.process_transaction(&tx), Ok(()));
assert_eq!(bank.get_balance(&leader), initial_balance + 3);
assert_eq!(bank.get_balance(&leader), initial_balance);
assert_eq!(bank.get_balance(&key1.pubkey()), 2);
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 100 - 5);
bank.freeze();
assert_eq!(bank.get_balance(&leader), initial_balance + 3); // leader collects fee after the bank is frozen

let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
bank.fee_calculator.lamports_per_signature = 1;
let tx = system_transaction::transfer(&key1, &key2.pubkey(), 1, genesis_block.hash());

assert_eq!(bank.process_transaction(&tx), Ok(()));
assert_eq!(bank.get_balance(&leader), initial_balance + 4);
assert_eq!(bank.get_balance(&leader), initial_balance + 3);
assert_eq!(bank.get_balance(&key1.pubkey()), 0);
assert_eq!(bank.get_balance(&key2.pubkey()), 1);
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 100 - 5);
bank.freeze();
assert_eq!(bank.get_balance(&leader), initial_balance + 4); // leader collects fee after the bank is frozen

// verify that an InstructionError collects fees, too
let bank = Bank::new_from_parent(&Arc::new(bank), &leader, 2);
let mut tx =
system_transaction::transfer(&mint_keypair, &key2.pubkey(), 1, genesis_block.hash());
// send a bogus instruction to system_program, cause an instruction error
tx.message.instructions[0].data[0] = 40;

bank.process_transaction(&tx)
.expect_err("instruction error"); // fails with an instruction error
assert_eq!(bank.get_balance(&leader), initial_balance + 5); // gots our bucks
assert_eq!(bank.get_balance(&key2.pubkey()), 1); // our fee --V
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 100 - 5 - 1);
bank.freeze();
assert_eq!(bank.get_balance(&leader), initial_balance + 5); // gots our bucks
}

#[test]
Expand Down Expand Up @@ -1537,6 +1557,7 @@ mod tests {
bank.fee_calculator.lamports_per_signature = 2;
let initial_balance = bank.get_balance(&leader);
let results = bank.filter_program_errors_and_collect_fee(&vec![tx1, tx2], &results);
bank.freeze();
assert_eq!(bank.get_balance(&leader), initial_balance + 2 + 2);
assert_eq!(results[0], Ok(()));
assert_eq!(results[1], Ok(()));
Expand Down