Compare commits
27 Commits
foo4
...
v0.7.0-rc.
Author | SHA1 | Date | |
---|---|---|---|
|
28d24497a3 | ||
|
05cea4c1da | ||
|
260f5edfd6 | ||
|
7105136595 | ||
|
54db379bf2 | ||
|
effbf0b978 | ||
|
8e7a2a9587 | ||
|
18e6ff4167 | ||
|
fa1cdaa91a | ||
|
b538b67524 | ||
|
2b0f6355af | ||
|
11b9a0323d | ||
|
710fa822a0 | ||
|
aaf6ce5aea | ||
|
34ea483736 | ||
|
a3ff40476e | ||
|
4cca3ff454 | ||
|
3d9acdd970 | ||
|
428f220b88 | ||
|
10add6a8ac | ||
|
f06a8dceda | ||
|
545f4f1c87 | ||
|
77543d83ff | ||
|
eb6a30cb7c | ||
|
97372b8e63 | ||
|
cea29ed772 | ||
|
b5006b8f2b |
@@ -37,10 +37,6 @@ path = "src/bin/fullnode-config.rs"
|
|||||||
name = "solana-genesis"
|
name = "solana-genesis"
|
||||||
path = "src/bin/genesis.rs"
|
path = "src/bin/genesis.rs"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "solana-mint"
|
|
||||||
path = "src/bin/mint.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "solana-drone"
|
name = "solana-drone"
|
||||||
path = "src/bin/drone.rs"
|
path = "src/bin/drone.rs"
|
||||||
@@ -85,6 +81,7 @@ futures = "0.1.21"
|
|||||||
clap = "2.31"
|
clap = "2.31"
|
||||||
reqwest = "0.8.6"
|
reqwest = "0.8.6"
|
||||||
influx_db_client = "0.3.4"
|
influx_db_client = "0.3.4"
|
||||||
|
dirs = "1.0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.2"
|
criterion = "0.2"
|
||||||
|
@@ -1,4 +1,38 @@
|
|||||||
steps:
|
steps:
|
||||||
|
- command: "ci/docker-run.sh rust ci/test-stable.sh"
|
||||||
|
name: "stable [public]"
|
||||||
|
env:
|
||||||
|
CARGO_TARGET_CACHE_NAME: "stable"
|
||||||
|
timeout_in_minutes: 30
|
||||||
|
- command: "ci/shellcheck.sh"
|
||||||
|
name: "shellcheck [public]"
|
||||||
|
timeout_in_minutes: 20
|
||||||
|
- command: "ci/docker-run.sh solanalabs/rust-nightly ci/test-nightly.sh"
|
||||||
|
name: "nightly [public]"
|
||||||
|
env:
|
||||||
|
CARGO_TARGET_CACHE_NAME: "nightly"
|
||||||
|
timeout_in_minutes: 30
|
||||||
|
- command: "ci/test-stable-perf.sh"
|
||||||
|
name: "stable-perf [public]"
|
||||||
|
env:
|
||||||
|
CARGO_TARGET_CACHE_NAME: "stable-perf"
|
||||||
|
timeout_in_minutes: 20
|
||||||
|
retry:
|
||||||
|
automatic:
|
||||||
|
- exit_status: "*"
|
||||||
|
limit: 2
|
||||||
|
agents:
|
||||||
|
- "queue=cuda"
|
||||||
|
- command: "ci/pr-snap.sh"
|
||||||
|
timeout_in_minutes: 20
|
||||||
|
name: "snap [public]"
|
||||||
|
- wait
|
||||||
|
- command: "ci/publish-crate.sh"
|
||||||
|
timeout_in_minutes: 20
|
||||||
|
name: "publish crate [public]"
|
||||||
|
- command: "ci/hoover.sh"
|
||||||
|
timeout_in_minutes: 20
|
||||||
|
name: "clean agent [public]"
|
||||||
- trigger: "solana-snap"
|
- trigger: "solana-snap"
|
||||||
branches: "!pull/*"
|
branches: "!pull/*"
|
||||||
async: true
|
async: true
|
||||||
@@ -7,5 +41,4 @@ steps:
|
|||||||
commit: "${BUILDKITE_COMMIT}"
|
commit: "${BUILDKITE_COMMIT}"
|
||||||
branch: "${BUILDKITE_BRANCH}"
|
branch: "${BUILDKITE_BRANCH}"
|
||||||
env:
|
env:
|
||||||
BUILDKITE_TAG: "${BUILDKITE_TAG}"
|
TRIGGERED_BUILDKITE_TAG: "${BUILDKITE_TAG}"
|
||||||
PARENT_BUILDKITE_TAG: "${BUILDKITE_TAG}"
|
|
||||||
|
@@ -31,19 +31,24 @@ done < <(gcloud compute instances list --filter="labels.testnet-mode=validator"
|
|||||||
|
|
||||||
|
|
||||||
echo "--- Refreshing"
|
echo "--- Refreshing"
|
||||||
mode=leader+drone
|
leader=true
|
||||||
for info in "${vmlist[@]}"; do
|
for info in "${vmlist[@]}"; do
|
||||||
vmName=${info%:*}
|
vmName=${info%:*}
|
||||||
vmZone=${info#*:}
|
vmZone=${info#*:}
|
||||||
echo "Starting refresh for $vmName"
|
echo "Starting refresh for $vmName"
|
||||||
|
|
||||||
(
|
(
|
||||||
echo "--- Processing $vmName in zone $vmZone as $mode"
|
echo "--- Processing $vmName in zone $vmZone"
|
||||||
|
if $leader; then
|
||||||
|
nodeConfig="mode=leader+drone enable-cuda=1 metrics-config=$SOLANA_METRICS_CONFIG"
|
||||||
|
else
|
||||||
|
nodeConfig="mode=validator metrics-config=$SOLANA_METRICS_CONFIG"
|
||||||
|
fi
|
||||||
cat > "autogen-refresh-$vmName.sh" <<EOF
|
cat > "autogen-refresh-$vmName.sh" <<EOF
|
||||||
set -x
|
set -x
|
||||||
sudo snap remove solana
|
sudo snap remove solana
|
||||||
sudo snap install solana $SOLANA_SNAP_CHANNEL --devmode
|
sudo snap install solana $SOLANA_SNAP_CHANNEL --devmode
|
||||||
sudo snap set solana mode=$mode metrics-config=$SOLANA_METRICS_CONFIG
|
sudo snap set solana $nodeConfig
|
||||||
snap info solana
|
snap info solana
|
||||||
sudo snap logs solana -n200
|
sudo snap logs solana -n200
|
||||||
EOF
|
EOF
|
||||||
@@ -53,10 +58,17 @@ EOF
|
|||||||
--ssh-flag="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t" \
|
--ssh-flag="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t" \
|
||||||
--command="bash ./autogen-refresh-$vmName.sh"
|
--command="bash ./autogen-refresh-$vmName.sh"
|
||||||
) > "log-$vmName.txt" 2>&1 &
|
) > "log-$vmName.txt" 2>&1 &
|
||||||
mode=validator
|
|
||||||
|
if $leader; then
|
||||||
|
echo Waiting for leader...
|
||||||
|
# Wait for the leader to initialize before starting the validators
|
||||||
|
# TODO: Remove this limitation eventually.
|
||||||
|
wait
|
||||||
|
fi
|
||||||
|
leader=false
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Waiting..."
|
echo Waiting for validators...
|
||||||
wait
|
wait
|
||||||
|
|
||||||
for info in "${vmlist[@]}"; do
|
for info in "${vmlist[@]}"; do
|
||||||
|
@@ -7,7 +7,11 @@ if [[ -z $BUILDKITE_BRANCH ]] || ./ci/is-pr.sh; then
|
|||||||
DRYRUN="echo"
|
DRYRUN="echo"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$BUILDKITE_TAG" ]]; then
|
# BUILDKITE_TAG is the normal environment variable set by Buildkite. However
|
||||||
|
# when this script is run from a triggered pipeline, TRIGGERED_BUILDKITE_TAG is
|
||||||
|
# used instead of BUILDKITE_TAG (due to Buildkite limitations that prevents
|
||||||
|
# BUILDKITE_TAG from propagating through to triggered pipelines)
|
||||||
|
if [[ -z "$BUILDKITE_TAG" && -z "$TRIGGERED_BUILDKITE_TAG" ]]; then
|
||||||
SNAP_CHANNEL=edge
|
SNAP_CHANNEL=edge
|
||||||
else
|
else
|
||||||
SNAP_CHANNEL=beta
|
SNAP_CHANNEL=beta
|
||||||
|
@@ -23,9 +23,9 @@ fi
|
|||||||
|
|
||||||
client_json="$SOLANA_CONFIG_CLIENT_DIR"/client.json
|
client_json="$SOLANA_CONFIG_CLIENT_DIR"/client.json
|
||||||
if [[ ! -r $client_json ]]; then
|
if [[ ! -r $client_json ]]; then
|
||||||
$solana_mint <<<0 > "$client_json"
|
$solana_keygen -o "$client_json"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2086 # $solana_client_demo should not be quoted
|
# shellcheck disable=SC2086 # $solana_client_demo should not be quoted
|
||||||
exec $solana_client_demo \
|
exec $solana_client_demo \
|
||||||
-n "$count" -l "$SOLANA_CONFIG_CLIENT_DIR"/leader.json -m "$SOLANA_CONFIG_CLIENT_DIR"/client.json
|
-n "$count" -l "$SOLANA_CONFIG_CLIENT_DIR"/leader.json -k "$SOLANA_CONFIG_CLIENT_DIR"/client.json
|
||||||
|
@@ -53,7 +53,7 @@ solana_fullnode=$(solana_program fullnode)
|
|||||||
solana_fullnode_config=$(solana_program fullnode-config)
|
solana_fullnode_config=$(solana_program fullnode-config)
|
||||||
solana_fullnode_cuda=$(solana_program fullnode-cuda)
|
solana_fullnode_cuda=$(solana_program fullnode-cuda)
|
||||||
solana_genesis=$(solana_program genesis)
|
solana_genesis=$(solana_program genesis)
|
||||||
solana_mint=$(solana_program mint)
|
solana_keygen=$(solana_program keygen)
|
||||||
|
|
||||||
export RUST_LOG=${RUST_LOG:-solana=info} # if RUST_LOG is unset, default to info
|
export RUST_LOG=${RUST_LOG:-solana=info} # if RUST_LOG is unset, default to info
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
@@ -107,15 +107,19 @@ tune_networking() {
|
|||||||
# Reference: https://medium.com/@CameronSparr/increase-os-udp-buffers-to-improve-performance-51d167bb1360
|
# Reference: https://medium.com/@CameronSparr/increase-os-udp-buffers-to-improve-performance-51d167bb1360
|
||||||
[[ $(uname) = Linux ]] && (
|
[[ $(uname) = Linux ]] && (
|
||||||
set -x
|
set -x
|
||||||
# TODO: Check values and warn instead, it's a little rude to set them here.
|
# test the existence of the sysctls before trying to set them
|
||||||
sudo sysctl -w net.core.rmem_max=26214400 1>/dev/null 2>/dev/null
|
sysctl net.core.rmem_max 2>/dev/null 1>/dev/null &&
|
||||||
sudo sysctl -w net.core.rmem_default=26214400 1>/dev/null 2>/dev/null
|
sudo sysctl -w net.core.rmem_max=26214400 1>/dev/null 2>/dev/null
|
||||||
|
|
||||||
|
sysctl net.core.rmem_default 2>/dev/null 1>/dev/null &&
|
||||||
|
sudo sysctl -w net.core.rmem_default=26214400 1>/dev/null 2>/dev/null
|
||||||
)
|
)
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
SOLANA_CONFIG_DIR=${SNAP_DATA:-$PWD}/config
|
SOLANA_CONFIG_DIR=${SNAP_DATA:-$PWD}/config
|
||||||
SOLANA_CONFIG_PRIVATE_DIR=${SNAP_DATA:-$PWD}/config-private
|
SOLANA_CONFIG_PRIVATE_DIR=${SNAP_DATA:-$PWD}/config-private
|
||||||
SOLANA_CONFIG_CLIENT_DIR=${SNAP_USER_DATA:-$PWD}/config-client-client
|
SOLANA_CONFIG_CLIENT_DIR=${SNAP_USER_DATA:-$PWD}/config-client
|
||||||
|
|
||||||
rsync_url() { # adds the 'rsync://` prefix to URLs that need it
|
rsync_url() { # adds the 'rsync://` prefix to URLs that need it
|
||||||
declare url="$1"
|
declare url="$1"
|
||||||
|
@@ -38,4 +38,4 @@ $rsync -vPz "$rsync_leader_url"/config/leader.json "$SOLANA_CONFIG_DIR"/
|
|||||||
|
|
||||||
# shellcheck disable=SC2086 # $solana_drone should not be quoted
|
# shellcheck disable=SC2086 # $solana_drone should not be quoted
|
||||||
exec $solana_drone \
|
exec $solana_drone \
|
||||||
-l "$SOLANA_CONFIG_DIR"/leader.json -m "$SOLANA_CONFIG_PRIVATE_DIR"/mint.json
|
-l "$SOLANA_CONFIG_DIR"/leader.json -k "$SOLANA_CONFIG_PRIVATE_DIR"/mint.json
|
||||||
|
@@ -25,9 +25,15 @@ fi
|
|||||||
|
|
||||||
tune_networking
|
tune_networking
|
||||||
|
|
||||||
|
# migrate from old ledger format? why not...
|
||||||
|
if [[ ! -f "$SOLANA_CONFIG_DIR"/ledger.log &&
|
||||||
|
-f "$SOLANA_CONFIG_DIR"/genesis.log ]]; then
|
||||||
|
(shopt -s nullglob &&
|
||||||
|
cat "$SOLANA_CONFIG_DIR"/genesis.log \
|
||||||
|
"$SOLANA_CONFIG_DIR"/tx-*.log) > "$SOLANA_CONFIG_DIR"/ledger.log
|
||||||
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2086 # $program should not be quoted
|
# shellcheck disable=SC2086 # $program should not be quoted
|
||||||
exec $program \
|
exec $program \
|
||||||
-l "$SOLANA_CONFIG_DIR"/leader.json \
|
--identity "$SOLANA_CONFIG_DIR"/leader.json \
|
||||||
< <(shopt -s nullglob && cat "$SOLANA_CONFIG_DIR"/genesis.log \
|
--ledger "$SOLANA_CONFIG_DIR"/ledger.log
|
||||||
"$SOLANA_CONFIG_DIR"/tx-*.log) \
|
|
||||||
> "$SOLANA_CONFIG_DIR"/tx-"$(date -u +%Y%m%d%H%M%S%N)".log
|
|
||||||
|
@@ -1,59 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function myip()
|
|
||||||
{
|
|
||||||
# shellcheck disable=SC2207
|
|
||||||
declare ipaddrs=(
|
|
||||||
# query interwebs
|
|
||||||
$(curl -s ifconfig.co)
|
|
||||||
# machine's interfaces
|
|
||||||
$(ifconfig |
|
|
||||||
awk '/inet addr:/ {gsub("addr:","",$2); print $2; next}
|
|
||||||
/inet6 addr:/ {gsub("/.*", "", $3); print $3; next}
|
|
||||||
/inet(6)? / {print $2}'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (( ! ${#ipaddrs[*]} ))
|
|
||||||
then
|
|
||||||
echo "
|
|
||||||
myip: error: I'm having trouble determining what our IP address is...
|
|
||||||
Are we connected to a network?
|
|
||||||
|
|
||||||
"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
declare prompt="
|
|
||||||
Please choose the IP address you want to advertise to the network:
|
|
||||||
|
|
||||||
0) ${ipaddrs[0]} <====== this one was returned by the interwebs...
|
|
||||||
"
|
|
||||||
|
|
||||||
for ((i=1; i < ${#ipaddrs[*]}; i++))
|
|
||||||
do
|
|
||||||
prompt+=" $i) ${ipaddrs[i]}
|
|
||||||
"
|
|
||||||
done
|
|
||||||
|
|
||||||
while read -r -p "${prompt}
|
|
||||||
please enter a number [0 for default]: " which
|
|
||||||
do
|
|
||||||
[[ -z ${which} ]] && break;
|
|
||||||
[[ ${which} =~ [0-9]+ ]] && (( which < ${#ipaddrs[*]} )) && break;
|
|
||||||
echo "Ug. invalid entry \"${which}\"...
|
|
||||||
"
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
which=${which:-0}
|
|
||||||
|
|
||||||
echo "${ipaddrs[which]}"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ ${0} == "${BASH_SOURCE[0]}" ]]
|
|
||||||
then
|
|
||||||
myip "$@"
|
|
||||||
fi
|
|
@@ -71,6 +71,8 @@ done
|
|||||||
|
|
||||||
leader_address_args=("$ip_address_arg")
|
leader_address_args=("$ip_address_arg")
|
||||||
validator_address_args=("$ip_address_arg" -b 9000)
|
validator_address_args=("$ip_address_arg" -b 9000)
|
||||||
|
id_path="$SOLANA_CONFIG_PRIVATE_DIR"/id.json
|
||||||
|
mint_path="$SOLANA_CONFIG_PRIVATE_DIR"/mint.json
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -78,25 +80,26 @@ echo "Cleaning $SOLANA_CONFIG_DIR"
|
|||||||
rm -rvf "$SOLANA_CONFIG_DIR"
|
rm -rvf "$SOLANA_CONFIG_DIR"
|
||||||
mkdir -p "$SOLANA_CONFIG_DIR"
|
mkdir -p "$SOLANA_CONFIG_DIR"
|
||||||
|
|
||||||
|
rm -rvf "$SOLANA_CONFIG_PRIVATE_DIR"
|
||||||
|
mkdir -p "$SOLANA_CONFIG_PRIVATE_DIR"
|
||||||
|
|
||||||
|
$solana_keygen -o "$id_path"
|
||||||
|
|
||||||
if $node_type_leader; then
|
if $node_type_leader; then
|
||||||
rm -rvf "$SOLANA_CONFIG_PRIVATE_DIR"
|
|
||||||
mkdir -p "$SOLANA_CONFIG_PRIVATE_DIR"
|
|
||||||
|
|
||||||
echo "Creating $SOLANA_CONFIG_DIR/mint.json with $num_tokens tokens"
|
echo "Creating $SOLANA_CONFIG_DIR/mint.json with $num_tokens tokens"
|
||||||
$solana_mint <<<"$num_tokens" > "$SOLANA_CONFIG_PRIVATE_DIR"/mint.json
|
$solana_keygen -o "$mint_path"
|
||||||
|
|
||||||
echo "Creating $SOLANA_CONFIG_DIR/genesis.log"
|
echo "Creating $SOLANA_CONFIG_DIR/ledger.log"
|
||||||
$solana_genesis < "$SOLANA_CONFIG_PRIVATE_DIR"/mint.json > "$SOLANA_CONFIG_DIR"/genesis.log
|
$solana_genesis --tokens="$num_tokens" < "$mint_path" > "$SOLANA_CONFIG_DIR"/ledger.log
|
||||||
|
|
||||||
echo "Creating $SOLANA_CONFIG_DIR/leader.json"
|
echo "Creating $SOLANA_CONFIG_DIR/leader.json"
|
||||||
$solana_fullnode_config "${leader_address_args[@]}" > "$SOLANA_CONFIG_DIR"/leader.json
|
$solana_fullnode_config --keypair="$id_path" "${leader_address_args[@]}" > "$SOLANA_CONFIG_DIR"/leader.json
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if $node_type_validator; then
|
if $node_type_validator; then
|
||||||
echo "Creating $SOLANA_CONFIG_DIR/validator.json"
|
echo "Creating $SOLANA_CONFIG_DIR/validator.json"
|
||||||
$solana_fullnode_config "${validator_address_args[@]}" > "$SOLANA_CONFIG_DIR"/validator.json
|
$solana_fullnode_config --keypair="$id_path" "${validator_address_args[@]}" > "$SOLANA_CONFIG_DIR"/validator.json
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ls -lh "$SOLANA_CONFIG_DIR"/
|
ls -lh "$SOLANA_CONFIG_DIR"/
|
||||||
|
@@ -73,8 +73,24 @@ ls -lh "$SOLANA_LEADER_CONFIG_DIR"
|
|||||||
|
|
||||||
tune_networking
|
tune_networking
|
||||||
|
|
||||||
|
# migrate from old ledger format? why not...
|
||||||
|
if [[ ! -f "$SOLANA_LEADER_CONFIG_DIR"/ledger.log &&
|
||||||
|
-f "$SOLANA_LEADER_CONFIG_DIR"/genesis.log ]]; then
|
||||||
|
(shopt -s nullglob &&
|
||||||
|
cat "$SOLANA_LEADER_CONFIG_DIR"/genesis.log \
|
||||||
|
"$SOLANA_LEADER_CONFIG_DIR"/tx-*.log) > "$SOLANA_LEADER_CONFIG_DIR"/ledger.log
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure the validator has at least 1 token before connecting to the network
|
||||||
|
# TODO: Remove this workaround
|
||||||
|
while ! $solana_wallet \
|
||||||
|
-l "$SOLANA_LEADER_CONFIG_DIR"/leader.json \
|
||||||
|
-k "$SOLANA_CONFIG_PRIVATE_DIR"/id.json airdrop --tokens 1; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
# shellcheck disable=SC2086 # $program should not be quoted
|
# shellcheck disable=SC2086 # $program should not be quoted
|
||||||
exec $program \
|
exec $program \
|
||||||
-l "$SOLANA_CONFIG_DIR"/validator.json -t "$leader_address:$leader_port" \
|
--identity "$SOLANA_CONFIG_DIR"/validator.json \
|
||||||
< <(shopt -s nullglob && cat "$SOLANA_LEADER_CONFIG_DIR"/genesis.log \
|
--testnet "$leader_address:$leader_port" \
|
||||||
"$SOLANA_LEADER_CONFIG_DIR"/tx-*.log)
|
--ledger "$SOLANA_LEADER_CONFIG_DIR"/ledger.log
|
||||||
|
@@ -36,12 +36,12 @@ if [[ ! -r "$SOLANA_CONFIG_CLIENT_DIR"/leader.json ]]; then
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
client_json="$SOLANA_CONFIG_CLIENT_DIR"/client.json
|
client_id_path="$SOLANA_CONFIG_CLIENT_DIR"/id.json
|
||||||
if [[ ! -r $client_json ]]; then
|
if [[ ! -r $client_id_path ]]; then
|
||||||
$solana_mint <<<0 > "$client_json"
|
$solana_keygen -o "$client_id_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
# shellcheck disable=SC2086 # $solana_wallet should not be quoted
|
# shellcheck disable=SC2086 # $solana_wallet should not be quoted
|
||||||
exec $solana_wallet \
|
exec $solana_wallet \
|
||||||
-l "$SOLANA_CONFIG_CLIENT_DIR"/leader.json -m "$client_json" "$@"
|
-l "$SOLANA_CONFIG_CLIENT_DIR"/leader.json -k "$client_id_path" "$@"
|
||||||
|
@@ -37,16 +37,26 @@ apps:
|
|||||||
plugs:
|
plugs:
|
||||||
- network
|
- network
|
||||||
- network-bind
|
- network-bind
|
||||||
|
- home
|
||||||
genesis:
|
genesis:
|
||||||
command: solana-genesis
|
command: solana-genesis
|
||||||
mint:
|
keygen:
|
||||||
command: solana-mint
|
command: solana-keygen
|
||||||
|
plugs:
|
||||||
|
- home
|
||||||
client-demo:
|
client-demo:
|
||||||
command: solana-client-demo
|
command: solana-client-demo
|
||||||
|
plugs:
|
||||||
|
- network
|
||||||
|
- network-bind
|
||||||
|
- home
|
||||||
wallet:
|
wallet:
|
||||||
# TODO: Merge wallet.sh functionality into solana-wallet proper
|
# TODO: Merge wallet.sh functionality into solana-wallet proper
|
||||||
command: wallet.sh
|
command: wallet.sh
|
||||||
#command: solana-wallet
|
#command: solana-wallet
|
||||||
|
plugs:
|
||||||
|
- network
|
||||||
|
- home
|
||||||
|
|
||||||
daemon-validator:
|
daemon-validator:
|
||||||
daemon: simple
|
daemon: simple
|
||||||
|
@@ -12,11 +12,10 @@ use solana::crdt::{Crdt, NodeInfo};
|
|||||||
use solana::drone::DroneRequest;
|
use solana::drone::DroneRequest;
|
||||||
use solana::fullnode::Config;
|
use solana::fullnode::Config;
|
||||||
use solana::hash::Hash;
|
use solana::hash::Hash;
|
||||||
use solana::mint::Mint;
|
|
||||||
use solana::nat::{udp_public_bind, udp_random_bind};
|
use solana::nat::{udp_public_bind, udp_random_bind};
|
||||||
use solana::ncp::Ncp;
|
use solana::ncp::Ncp;
|
||||||
use solana::service::Service;
|
use solana::service::Service;
|
||||||
use solana::signature::{GenKeys, KeyPair, KeyPairUtil};
|
use solana::signature::{read_keypair, GenKeys, KeyPair, KeyPairUtil};
|
||||||
use solana::streamer::default_window;
|
use solana::streamer::default_window;
|
||||||
use solana::thin_client::ThinClient;
|
use solana::thin_client::ThinClient;
|
||||||
use solana::timing::{duration_as_ms, duration_as_s};
|
use solana::timing::{duration_as_ms, duration_as_s};
|
||||||
@@ -77,7 +76,7 @@ fn sample_tx_count(
|
|||||||
fn generate_and_send_txs(
|
fn generate_and_send_txs(
|
||||||
client: &mut ThinClient,
|
client: &mut ThinClient,
|
||||||
tx_clients: &[ThinClient],
|
tx_clients: &[ThinClient],
|
||||||
id: &Mint,
|
id: &KeyPair,
|
||||||
keypairs: &[KeyPair],
|
keypairs: &[KeyPair],
|
||||||
leader: &NodeInfo,
|
leader: &NodeInfo,
|
||||||
txs: i64,
|
txs: i64,
|
||||||
@@ -91,7 +90,7 @@ fn generate_and_send_txs(
|
|||||||
let transactions: Vec<_> = if !reclaim {
|
let transactions: Vec<_> = if !reclaim {
|
||||||
keypairs
|
keypairs
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.map(|keypair| Transaction::new(&id.keypair(), keypair.pubkey(), 1, *last_id))
|
.map(|keypair| Transaction::new(&id, keypair.pubkey(), 1, *last_id))
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
keypairs
|
keypairs
|
||||||
@@ -164,12 +163,13 @@ fn main() {
|
|||||||
.help("/path/to/leader.json"),
|
.help("/path/to/leader.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("mint")
|
Arg::with_name("keypair")
|
||||||
.short("m")
|
.short("k")
|
||||||
.long("mint")
|
.long("keypair")
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("/path/to/mint.json"),
|
.default_value("~/.config/solana/id.json")
|
||||||
|
.help("/path/to/id.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("num_nodes")
|
Arg::with_name("num_nodes")
|
||||||
@@ -205,13 +205,7 @@ fn main() {
|
|||||||
leader = NodeInfo::new_leader(&server_addr);
|
leader = NodeInfo::new_leader(&server_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
let id: Mint;
|
let id = read_keypair(matches.value_of("keypair").unwrap()).expect("client keypair");
|
||||||
if let Some(m) = matches.value_of("mint") {
|
|
||||||
id = read_mint(m).expect("client mint");
|
|
||||||
} else {
|
|
||||||
eprintln!("No mint found!");
|
|
||||||
exit(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(t) = matches.value_of("threads") {
|
if let Some(t) = matches.value_of("threads") {
|
||||||
threads = t.to_string().parse().expect("integer");
|
threads = t.to_string().parse().expect("integer");
|
||||||
@@ -259,7 +253,7 @@ fn main() {
|
|||||||
println!("Got last ID {:?}", last_id);
|
println!("Got last ID {:?}", last_id);
|
||||||
|
|
||||||
let mut seed = [0u8; 32];
|
let mut seed = [0u8; 32];
|
||||||
seed.copy_from_slice(&id.keypair().public_key_bytes()[..32]);
|
seed.copy_from_slice(&id.public_key_bytes()[..32]);
|
||||||
let rnd = GenKeys::new(seed);
|
let rnd = GenKeys::new(seed);
|
||||||
|
|
||||||
println!("Creating keypairs...");
|
println!("Creating keypairs...");
|
||||||
@@ -433,15 +427,9 @@ fn read_leader(path: &str) -> Config {
|
|||||||
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_mint(path: &str) -> Result<Mint, Box<error::Error>> {
|
|
||||||
let file = File::open(path.to_string())?;
|
|
||||||
let mint = serde_json::from_reader(file)?;
|
|
||||||
Ok(mint)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn request_airdrop(
|
fn request_airdrop(
|
||||||
drone_addr: &SocketAddr,
|
drone_addr: &SocketAddr,
|
||||||
id: &Mint,
|
id: &KeyPair,
|
||||||
tokens: u64,
|
tokens: u64,
|
||||||
) -> Result<(), Box<error::Error>> {
|
) -> Result<(), Box<error::Error>> {
|
||||||
let mut stream = TcpStream::connect(drone_addr)?;
|
let mut stream = TcpStream::connect(drone_addr)?;
|
||||||
|
@@ -12,11 +12,9 @@ use clap::{App, Arg};
|
|||||||
use solana::crdt::NodeInfo;
|
use solana::crdt::NodeInfo;
|
||||||
use solana::drone::{Drone, DroneRequest};
|
use solana::drone::{Drone, DroneRequest};
|
||||||
use solana::fullnode::Config;
|
use solana::fullnode::Config;
|
||||||
use solana::mint::Mint;
|
use solana::signature::read_keypair;
|
||||||
use std::error;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::process::exit;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
@@ -35,11 +33,12 @@ fn main() {
|
|||||||
.help("/path/to/leader.json"),
|
.help("/path/to/leader.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("mint")
|
Arg::with_name("keypair")
|
||||||
.short("m")
|
.short("k")
|
||||||
.long("mint")
|
.long("keypair")
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.required(true)
|
||||||
.help("/path/to/mint.json"),
|
.help("/path/to/mint.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -68,13 +67,9 @@ fn main() {
|
|||||||
leader = NodeInfo::new_leader(&server_addr);
|
leader = NodeInfo::new_leader(&server_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mint: Mint;
|
let mint_keypair =
|
||||||
if let Some(m) = matches.value_of("mint") {
|
read_keypair(matches.value_of("keypair").expect("keypair")).expect("client keypair");
|
||||||
mint = read_mint(m).expect("client mint");
|
|
||||||
} else {
|
|
||||||
eprintln!("No mint found!");
|
|
||||||
exit(1);
|
|
||||||
};
|
|
||||||
let time_slice: Option<u64>;
|
let time_slice: Option<u64>;
|
||||||
if let Some(t) = matches.value_of("time") {
|
if let Some(t) = matches.value_of("time") {
|
||||||
time_slice = Some(t.to_string().parse().expect("integer"));
|
time_slice = Some(t.to_string().parse().expect("integer"));
|
||||||
@@ -88,8 +83,6 @@ fn main() {
|
|||||||
request_cap = None;
|
request_cap = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mint_keypair = mint.keypair();
|
|
||||||
|
|
||||||
let drone_addr: SocketAddr = "0.0.0.0:9900".parse().unwrap();
|
let drone_addr: SocketAddr = "0.0.0.0:9900".parse().unwrap();
|
||||||
|
|
||||||
let drone = Arc::new(Mutex::new(Drone::new(
|
let drone = Arc::new(Mutex::new(Drone::new(
|
||||||
@@ -152,9 +145,3 @@ fn read_leader(path: &str) -> Config {
|
|||||||
let file = File::open(path).unwrap_or_else(|_| panic!("file not found: {}", path));
|
let file = File::open(path).unwrap_or_else(|_| panic!("file not found: {}", path));
|
||||||
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_mint(path: &str) -> Result<Mint, Box<error::Error>> {
|
|
||||||
let file = File::open(path.to_string())?;
|
|
||||||
let mint = serde_json::from_reader(file)?;
|
|
||||||
Ok(mint)
|
|
||||||
}
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
extern crate dirs;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate solana;
|
extern crate solana;
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ use clap::{App, Arg};
|
|||||||
use solana::crdt::{get_ip_addr, parse_port_or_addr};
|
use solana::crdt::{get_ip_addr, parse_port_or_addr};
|
||||||
use solana::fullnode::Config;
|
use solana::fullnode::Config;
|
||||||
use solana::nat::get_public_ip_addr;
|
use solana::nat::get_public_ip_addr;
|
||||||
|
use solana::signature::read_pkcs8;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
@@ -18,6 +20,14 @@ fn main() {
|
|||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("detect network address from local machine configuration"),
|
.help("detect network address from local machine configuration"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("keypair")
|
||||||
|
.short("k")
|
||||||
|
.long("keypair")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("/path/to/id.json"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("public")
|
Arg::with_name("public")
|
||||||
.short("p")
|
.short("p")
|
||||||
@@ -54,9 +64,18 @@ fn main() {
|
|||||||
bind_addr
|
bind_addr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut path = dirs::home_dir().expect("home directory");
|
||||||
|
let id_path = if matches.is_present("keypair") {
|
||||||
|
matches.value_of("keypair").unwrap()
|
||||||
|
} else {
|
||||||
|
path.extend(&[".config", "solana", "id.json"]);
|
||||||
|
path.to_str().unwrap()
|
||||||
|
};
|
||||||
|
let pkcs8 = read_pkcs8(id_path).expect("client keypair");
|
||||||
|
|
||||||
// we need all the receiving sockets to be bound within the expected
|
// we need all the receiving sockets to be bound within the expected
|
||||||
// port range that we open on aws
|
// port range that we open on aws
|
||||||
let config = Config::new(&bind_addr);
|
let config = Config::new(&bind_addr, pkcs8);
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
serde_json::to_writer(stdout, &config).expect("serialize");
|
serde_json::to_writer(stdout, &config).expect("serialize");
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
extern crate atty;
|
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
@@ -6,10 +5,9 @@ extern crate log;
|
|||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate solana;
|
extern crate solana;
|
||||||
|
|
||||||
use atty::{is, Stream};
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use solana::crdt::{NodeInfo, TestNode};
|
use solana::crdt::{NodeInfo, TestNode};
|
||||||
use solana::fullnode::{Config, FullNode, InFile, OutFile};
|
use solana::fullnode::{Config, FullNode, LedgerFile};
|
||||||
use solana::service::Service;
|
use solana::service::Service;
|
||||||
use solana::signature::{KeyPair, KeyPairUtil};
|
use solana::signature::{KeyPair, KeyPairUtil};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -22,8 +20,8 @@ fn main() -> () {
|
|||||||
let matches = App::new("fullnode")
|
let matches = App::new("fullnode")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("identity")
|
Arg::with_name("identity")
|
||||||
.short("l")
|
.short("i")
|
||||||
.long("local")
|
.long("identity")
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("run with the identity found in FILE"),
|
.help("run with the identity found in FILE"),
|
||||||
@@ -34,27 +32,23 @@ fn main() -> () {
|
|||||||
.long("testnet")
|
.long("testnet")
|
||||||
.value_name("HOST:PORT")
|
.value_name("HOST:PORT")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("testnet; connect to the network at this gossip entry point"),
|
.help("connect to the network at this gossip entry point"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("output")
|
Arg::with_name("ledger")
|
||||||
.short("o")
|
.short("L")
|
||||||
.long("output")
|
.long("ledger")
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("output log to FILE, defaults to stdout (ignored by validators)"),
|
.help("use FILE as persistent ledger (defaults to stdin/stdout)"),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
if is(Stream::Stdin) {
|
|
||||||
eprintln!("nothing found on stdin, expected a log file");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let bind_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8000);
|
let bind_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8000);
|
||||||
let mut keypair = KeyPair::new();
|
let mut keypair = KeyPair::new();
|
||||||
let mut repl_data = NodeInfo::new_leader_with_pubkey(keypair.pubkey(), &bind_addr);
|
let mut repl_data = NodeInfo::new_leader_with_pubkey(keypair.pubkey(), &bind_addr);
|
||||||
if let Some(l) = matches.value_of("identity") {
|
if let Some(i) = matches.value_of("identity") {
|
||||||
let path = l.to_string();
|
let path = i.to_string();
|
||||||
if let Ok(file) = File::open(path.clone()) {
|
if let Ok(file) = File::open(path.clone()) {
|
||||||
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
|
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
|
||||||
if let Ok(data) = parse {
|
if let Ok(data) = parse {
|
||||||
@@ -69,27 +63,22 @@ fn main() -> () {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let ledger = if let Some(l) = matches.value_of("ledger") {
|
||||||
|
LedgerFile::Path(l.to_string())
|
||||||
|
} else {
|
||||||
|
LedgerFile::StdInOut
|
||||||
|
};
|
||||||
|
|
||||||
let mut node = TestNode::new_with_bind_addr(repl_data, bind_addr);
|
let mut node = TestNode::new_with_bind_addr(repl_data, bind_addr);
|
||||||
let fullnode = if let Some(t) = matches.value_of("testnet") {
|
let fullnode = if let Some(t) = matches.value_of("testnet") {
|
||||||
let testnet_address_string = t.to_string();
|
let testnet_address_string = t.to_string();
|
||||||
let testnet_addr = testnet_address_string.parse().unwrap();
|
let testnet_addr = testnet_address_string.parse().unwrap();
|
||||||
FullNode::new(
|
|
||||||
node,
|
FullNode::new(node, false, ledger, Some(keypair), Some(testnet_addr))
|
||||||
false,
|
|
||||||
InFile::StdIn,
|
|
||||||
Some(keypair),
|
|
||||||
Some(testnet_addr),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
node.data.leader_id = node.data.id;
|
node.data.leader_id = node.data.id;
|
||||||
|
|
||||||
let outfile = if let Some(o) = matches.value_of("output") {
|
FullNode::new(node, true, ledger, None, None)
|
||||||
OutFile::Path(o.to_string())
|
|
||||||
} else {
|
|
||||||
OutFile::StdOut
|
|
||||||
};
|
|
||||||
FullNode::new(node, true, InFile::StdIn, None, None, Some(outfile))
|
|
||||||
};
|
};
|
||||||
fullnode.join().expect("join");
|
fullnode.join().expect("join");
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
//! A command-line executable for generating the chain's genesis block.
|
//! A command-line executable for generating the chain's genesis block.
|
||||||
|
|
||||||
extern crate atty;
|
extern crate atty;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate clap;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate solana;
|
extern crate solana;
|
||||||
|
|
||||||
use atty::{is, Stream};
|
use atty::{is, Stream};
|
||||||
|
use clap::{App, Arg};
|
||||||
use solana::entry_writer::EntryWriter;
|
use solana::entry_writer::EntryWriter;
|
||||||
use solana::mint::Mint;
|
use solana::mint::Mint;
|
||||||
use std::error;
|
use std::error;
|
||||||
@@ -12,6 +15,20 @@ use std::io::{stdin, stdout, Read};
|
|||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<error::Error>> {
|
fn main() -> Result<(), Box<error::Error>> {
|
||||||
|
let matches = App::new("solana-genesis")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("tokens")
|
||||||
|
.short("t")
|
||||||
|
.long("tokens")
|
||||||
|
.value_name("NUMBER")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(true)
|
||||||
|
.help("Number of tokens with which to initialize mint"),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
let tokens = value_t_or_exit!(matches, "tokens", i64);
|
||||||
|
|
||||||
if is(Stream::Stdin) {
|
if is(Stream::Stdin) {
|
||||||
eprintln!("nothing found on stdin, expected a json file");
|
eprintln!("nothing found on stdin, expected a json file");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -24,7 +41,9 @@ fn main() -> Result<(), Box<error::Error>> {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mint: Mint = serde_json::from_str(&buffer)?;
|
let pkcs8: Vec<u8> = serde_json::from_str(&buffer)?;
|
||||||
|
let mint = Mint::new_with_pkcs8(tokens, pkcs8);
|
||||||
|
|
||||||
let mut writer = stdout();
|
let mut writer = stdout();
|
||||||
EntryWriter::write_entries(&mut writer, mint.create_entries())?;
|
EntryWriter::write_entries(&mut writer, mint.create_entries())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@@ -1,14 +1,49 @@
|
|||||||
|
extern crate clap;
|
||||||
|
extern crate dirs;
|
||||||
extern crate ring;
|
extern crate ring;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use clap::{App, Arg};
|
||||||
use ring::rand::SystemRandom;
|
use ring::rand::SystemRandom;
|
||||||
use ring::signature::Ed25519KeyPair;
|
use ring::signature::Ed25519KeyPair;
|
||||||
use std::error;
|
use std::error;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<error::Error>> {
|
fn main() -> Result<(), Box<error::Error>> {
|
||||||
|
let matches = App::new("solana-keygen")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("outfile")
|
||||||
|
.short("o")
|
||||||
|
.long("outfile")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("path to generated file"),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
let rnd = SystemRandom::new();
|
let rnd = SystemRandom::new();
|
||||||
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rnd)?;
|
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rnd)?;
|
||||||
let serialized = serde_json::to_string(&pkcs8_bytes.to_vec())?;
|
let serialized = serde_json::to_string(&pkcs8_bytes.to_vec())?;
|
||||||
println!("{}", serialized);
|
|
||||||
|
let mut path = dirs::home_dir().expect("home directory");
|
||||||
|
let outfile = if matches.is_present("outfile") {
|
||||||
|
matches.value_of("outfile").unwrap()
|
||||||
|
} else {
|
||||||
|
path.extend(&[".config", "solana", "id.json"]);
|
||||||
|
path.to_str().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
if outfile == "-" {
|
||||||
|
println!("{}", serialized);
|
||||||
|
} else {
|
||||||
|
if let Some(outdir) = Path::new(outfile).parent() {
|
||||||
|
fs::create_dir_all(outdir)?;
|
||||||
|
}
|
||||||
|
let mut f = File::create(outfile)?;
|
||||||
|
f.write_all(&serialized.into_bytes())?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
extern crate atty;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate solana;
|
|
||||||
|
|
||||||
use atty::{is, Stream};
|
|
||||||
use solana::mint::Mint;
|
|
||||||
use std::io;
|
|
||||||
use std::process::exit;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut input_text = String::new();
|
|
||||||
if is(Stream::Stdin) {
|
|
||||||
eprintln!("nothing found on stdin, expected a token number");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
io::stdin().read_line(&mut input_text).unwrap();
|
|
||||||
let trimmed = input_text.trim();
|
|
||||||
let tokens = trimmed.parse::<i64>().unwrap_or_else(|e| {
|
|
||||||
eprintln!("{}", e);
|
|
||||||
exit(1);
|
|
||||||
});
|
|
||||||
let mint = Mint::new(tokens);
|
|
||||||
let serialized = serde_json::to_string(&mint).unwrap_or_else(|e| {
|
|
||||||
eprintln!("failed to serialize: {}", e);
|
|
||||||
exit(1);
|
|
||||||
});
|
|
||||||
println!("{}", serialized);
|
|
||||||
}
|
|
@@ -2,6 +2,7 @@ extern crate atty;
|
|||||||
extern crate bincode;
|
extern crate bincode;
|
||||||
extern crate bs58;
|
extern crate bs58;
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
extern crate dirs;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate solana;
|
extern crate solana;
|
||||||
@@ -11,8 +12,7 @@ use clap::{App, Arg, SubCommand};
|
|||||||
use solana::crdt::NodeInfo;
|
use solana::crdt::NodeInfo;
|
||||||
use solana::drone::DroneRequest;
|
use solana::drone::DroneRequest;
|
||||||
use solana::fullnode::Config;
|
use solana::fullnode::Config;
|
||||||
use solana::mint::Mint;
|
use solana::signature::{read_keypair, KeyPair, KeyPairUtil, PublicKey, Signature};
|
||||||
use solana::signature::{PublicKey, Signature};
|
|
||||||
use solana::thin_client::ThinClient;
|
use solana::thin_client::ThinClient;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -20,7 +20,6 @@ use std::fs::File;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream, UdpSocket};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream, UdpSocket};
|
||||||
use std::process::exit;
|
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ impl error::Error for WalletError {
|
|||||||
|
|
||||||
struct WalletConfig {
|
struct WalletConfig {
|
||||||
leader: NodeInfo,
|
leader: NodeInfo,
|
||||||
id: Mint,
|
id: KeyPair,
|
||||||
drone_addr: SocketAddr,
|
drone_addr: SocketAddr,
|
||||||
command: WalletCommand,
|
command: WalletCommand,
|
||||||
}
|
}
|
||||||
@@ -67,7 +66,7 @@ impl Default for WalletConfig {
|
|||||||
let default_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8000);
|
let default_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8000);
|
||||||
WalletConfig {
|
WalletConfig {
|
||||||
leader: NodeInfo::new_leader(&default_addr),
|
leader: NodeInfo::new_leader(&default_addr),
|
||||||
id: Mint::new(0),
|
id: KeyPair::new(),
|
||||||
drone_addr: default_addr,
|
drone_addr: default_addr,
|
||||||
command: WalletCommand::Balance,
|
command: WalletCommand::Balance,
|
||||||
}
|
}
|
||||||
@@ -85,12 +84,12 @@ fn parse_args() -> Result<WalletConfig, Box<error::Error>> {
|
|||||||
.help("/path/to/leader.json"),
|
.help("/path/to/leader.json"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("mint")
|
Arg::with_name("keypair")
|
||||||
.short("m")
|
.short("k")
|
||||||
.long("mint")
|
.long("keypair")
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("/path/to/mint.json"),
|
.help("/path/to/id.json"),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("airdrop")
|
SubCommand::with_name("airdrop")
|
||||||
@@ -101,6 +100,7 @@ fn parse_args() -> Result<WalletConfig, Box<error::Error>> {
|
|||||||
.long("tokens")
|
.long("tokens")
|
||||||
.value_name("NUMBER")
|
.value_name("NUMBER")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.required(true)
|
||||||
.help("The number of tokens to request"),
|
.help("The number of tokens to request"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -122,7 +122,6 @@ fn parse_args() -> Result<WalletConfig, Box<error::Error>> {
|
|||||||
.long("to")
|
.long("to")
|
||||||
.value_name("PUBKEY")
|
.value_name("PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true)
|
|
||||||
.help("The pubkey of recipient"),
|
.help("The pubkey of recipient"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -149,24 +148,27 @@ fn parse_args() -> Result<WalletConfig, Box<error::Error>> {
|
|||||||
leader = NodeInfo::new_leader(&server_addr);
|
leader = NodeInfo::new_leader(&server_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
let id: Mint;
|
let mut path = dirs::home_dir().expect("home directory");
|
||||||
if let Some(m) = matches.value_of("mint") {
|
let id_path = if matches.is_present("keypair") {
|
||||||
id = read_mint(m)?;
|
matches.value_of("keypair").unwrap()
|
||||||
} else {
|
} else {
|
||||||
eprintln!("No mint found!");
|
path.extend(&[".config", "solana", "id.json"]);
|
||||||
exit(1);
|
path.to_str().unwrap()
|
||||||
};
|
};
|
||||||
|
let id = read_keypair(id_path).or_else(|err| {
|
||||||
|
display_actions();
|
||||||
|
Err(WalletError::BadParameter(format!(
|
||||||
|
"{}: Unable to open keypair file: {}",
|
||||||
|
err, id_path
|
||||||
|
)))
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut drone_addr = leader.contact_info.tpu;
|
let mut drone_addr = leader.contact_info.tpu;
|
||||||
drone_addr.set_port(9900);
|
drone_addr.set_port(9900);
|
||||||
|
|
||||||
let command = match matches.subcommand() {
|
let command = match matches.subcommand() {
|
||||||
("airdrop", Some(airdrop_matches)) => {
|
("airdrop", Some(airdrop_matches)) => {
|
||||||
let tokens = if airdrop_matches.is_present("tokens") {
|
let tokens = airdrop_matches.value_of("tokens").unwrap().parse()?;
|
||||||
airdrop_matches.value_of("tokens").unwrap().parse()?
|
|
||||||
} else {
|
|
||||||
id.tokens
|
|
||||||
};
|
|
||||||
Ok(WalletCommand::AirDrop(tokens))
|
Ok(WalletCommand::AirDrop(tokens))
|
||||||
}
|
}
|
||||||
("pay", Some(pay_matches)) => {
|
("pay", Some(pay_matches)) => {
|
||||||
@@ -184,11 +186,7 @@ fn parse_args() -> Result<WalletConfig, Box<error::Error>> {
|
|||||||
id.pubkey()
|
id.pubkey()
|
||||||
};
|
};
|
||||||
|
|
||||||
let tokens = if pay_matches.is_present("tokens") {
|
let tokens = pay_matches.value_of("tokens").unwrap().parse()?;
|
||||||
pay_matches.value_of("tokens").unwrap().parse()?
|
|
||||||
} else {
|
|
||||||
id.tokens
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(WalletCommand::Pay(tokens, to))
|
Ok(WalletCommand::Pay(tokens, to))
|
||||||
}
|
}
|
||||||
@@ -264,7 +262,7 @@ fn process_command(
|
|||||||
// If client has positive balance, spend tokens in {balance} number of transactions
|
// If client has positive balance, spend tokens in {balance} number of transactions
|
||||||
WalletCommand::Pay(tokens, to) => {
|
WalletCommand::Pay(tokens, to) => {
|
||||||
let last_id = client.get_last_id();
|
let last_id = client.get_last_id();
|
||||||
let sig = client.transfer(tokens, &config.id.keypair(), to, &last_id)?;
|
let sig = client.transfer(tokens, &config.id, to, &last_id)?;
|
||||||
println!("{}", bs58::encode(sig).into_string());
|
println!("{}", bs58::encode(sig).into_string());
|
||||||
}
|
}
|
||||||
// Confirm the last client transaction by signature
|
// Confirm the last client transaction by signature
|
||||||
@@ -295,12 +293,6 @@ fn read_leader(path: &str) -> Config {
|
|||||||
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
serde_json::from_reader(file).unwrap_or_else(|_| panic!("failed to parse {}", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_mint(path: &str) -> Result<Mint, Box<error::Error>> {
|
|
||||||
let file = File::open(path.to_string())?;
|
|
||||||
let mint = serde_json::from_reader(file)?;
|
|
||||||
Ok(mint)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mk_client(r: &NodeInfo) -> io::Result<ThinClient> {
|
fn mk_client(r: &NodeInfo) -> io::Result<ThinClient> {
|
||||||
let requests_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let requests_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
@@ -318,7 +310,7 @@ fn mk_client(r: &NodeInfo) -> io::Result<ThinClient> {
|
|||||||
|
|
||||||
fn request_airdrop(
|
fn request_airdrop(
|
||||||
drone_addr: &SocketAddr,
|
drone_addr: &SocketAddr,
|
||||||
id: &Mint,
|
id: &KeyPair,
|
||||||
tokens: u64,
|
tokens: u64,
|
||||||
) -> Result<(), Box<error::Error>> {
|
) -> Result<(), Box<error::Error>> {
|
||||||
let mut stream = TcpStream::connect(drone_addr)?;
|
let mut stream = TcpStream::connect(drone_addr)?;
|
||||||
|
@@ -7,13 +7,12 @@ use entry_writer;
|
|||||||
use ledger::Block;
|
use ledger::Block;
|
||||||
use ncp::Ncp;
|
use ncp::Ncp;
|
||||||
use packet::BlobRecycler;
|
use packet::BlobRecycler;
|
||||||
use ring::rand::SystemRandom;
|
|
||||||
use rpu::Rpu;
|
use rpu::Rpu;
|
||||||
use service::Service;
|
use service::Service;
|
||||||
use signature::{KeyPair, KeyPairUtil};
|
use signature::{KeyPair, KeyPairUtil};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{sink, stdin, stdout, BufReader};
|
use std::io::{stdin, stdout, BufReader};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
@@ -31,13 +30,8 @@ pub struct FullNode {
|
|||||||
thread_hdls: Vec<JoinHandle<()>>,
|
thread_hdls: Vec<JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum InFile {
|
pub enum LedgerFile {
|
||||||
StdIn,
|
StdInOut,
|
||||||
Path(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum OutFile {
|
|
||||||
StdOut,
|
|
||||||
Path(String),
|
Path(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +44,7 @@ pub struct Config {
|
|||||||
|
|
||||||
/// Structure to be replicated by the network
|
/// Structure to be replicated by the network
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new(bind_addr: &SocketAddr) -> Self {
|
pub fn new(bind_addr: &SocketAddr, pkcs8: Vec<u8>) -> Self {
|
||||||
let rnd = SystemRandom::new();
|
|
||||||
let pkcs8 = KeyPair::generate_pkcs8(&rnd)
|
|
||||||
.expect("generate_pkcs8 in mint pub fn new")
|
|
||||||
.to_vec();
|
|
||||||
let keypair =
|
let keypair =
|
||||||
KeyPair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in fullnode::Config new");
|
KeyPair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in fullnode::Config new");
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
@@ -71,16 +61,24 @@ impl FullNode {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
mut node: TestNode,
|
mut node: TestNode,
|
||||||
leader: bool,
|
leader: bool,
|
||||||
infile: InFile,
|
ledger: LedgerFile,
|
||||||
keypair_for_validator: Option<KeyPair>,
|
keypair_for_validator: Option<KeyPair>,
|
||||||
network_entry_for_validator: Option<SocketAddr>,
|
network_entry_for_validator: Option<SocketAddr>,
|
||||||
outfile_for_leader: Option<OutFile>,
|
|
||||||
) -> FullNode {
|
) -> FullNode {
|
||||||
info!("creating bank...");
|
info!("creating bank...");
|
||||||
let bank = Bank::default();
|
let bank = Bank::default();
|
||||||
let infile: Box<Read> = match infile {
|
let (infile, outfile): (Box<Read>, Box<Write + Send>) = match ledger {
|
||||||
InFile::Path(path) => Box::new(File::open(path).unwrap()),
|
LedgerFile::Path(path) => (
|
||||||
InFile::StdIn => Box::new(stdin()),
|
Box::new(File::open(path.clone()).expect("opening ledger file")),
|
||||||
|
Box::new(
|
||||||
|
OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open(path)
|
||||||
|
.expect("opening ledger file"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
LedgerFile::StdInOut => (Box::new(stdin()), Box::new(stdout())),
|
||||||
};
|
};
|
||||||
let reader = BufReader::new(infile);
|
let reader = BufReader::new(infile);
|
||||||
let entries = entry_writer::read_entries(reader).map(|e| e.expect("failed to parse entry"));
|
let entries = entry_writer::read_entries(reader).map(|e| e.expect("failed to parse entry"));
|
||||||
@@ -122,17 +120,6 @@ impl FullNode {
|
|||||||
server
|
server
|
||||||
} else {
|
} else {
|
||||||
node.data.leader_id = node.data.id;
|
node.data.leader_id = node.data.id;
|
||||||
let outfile_for_leader: Box<Write + Send> = match outfile_for_leader {
|
|
||||||
Some(OutFile::Path(file)) => Box::new(
|
|
||||||
OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.append(true)
|
|
||||||
.open(file)
|
|
||||||
.expect("opening ledger file"),
|
|
||||||
),
|
|
||||||
Some(OutFile::StdOut) => Box::new(stdout()),
|
|
||||||
None => Box::new(sink()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let server = FullNode::new_leader(
|
let server = FullNode::new_leader(
|
||||||
bank,
|
bank,
|
||||||
@@ -142,7 +129,7 @@ impl FullNode {
|
|||||||
None,
|
None,
|
||||||
node,
|
node,
|
||||||
exit.clone(),
|
exit.clone(),
|
||||||
outfile_for_leader,
|
outfile,
|
||||||
);
|
);
|
||||||
info!(
|
info!(
|
||||||
"leader ready... local request address: {} (advertising {})",
|
"leader ready... local request address: {} (advertising {})",
|
||||||
|
15
src/mint.rs
15
src/mint.rs
@@ -15,11 +15,7 @@ pub struct Mint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Mint {
|
impl Mint {
|
||||||
pub fn new(tokens: i64) -> Self {
|
pub fn new_with_pkcs8(tokens: i64, pkcs8: Vec<u8>) -> Self {
|
||||||
let rnd = SystemRandom::new();
|
|
||||||
let pkcs8 = KeyPair::generate_pkcs8(&rnd)
|
|
||||||
.expect("generate_pkcs8 in mint pub fn new")
|
|
||||||
.to_vec();
|
|
||||||
let keypair =
|
let keypair =
|
||||||
KeyPair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in mint pub fn new");
|
KeyPair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in mint pub fn new");
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
@@ -29,6 +25,15 @@ impl Mint {
|
|||||||
tokens,
|
tokens,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new(tokens: i64) -> Self {
|
||||||
|
let rnd = SystemRandom::new();
|
||||||
|
let pkcs8 = KeyPair::generate_pkcs8(&rnd)
|
||||||
|
.expect("generate_pkcs8 in mint pub fn new")
|
||||||
|
.to_vec();
|
||||||
|
Self::new_with_pkcs8(tokens, pkcs8)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn seed(&self) -> Hash {
|
pub fn seed(&self) -> Hash {
|
||||||
hash(&self.pkcs8)
|
hash(&self.pkcs8)
|
||||||
}
|
}
|
||||||
|
@@ -8,8 +8,11 @@ use ring::error::Unspecified;
|
|||||||
use ring::rand::SecureRandom;
|
use ring::rand::SecureRandom;
|
||||||
use ring::signature::Ed25519KeyPair;
|
use ring::signature::Ed25519KeyPair;
|
||||||
use ring::{rand, signature};
|
use ring::{rand, signature};
|
||||||
|
use serde_json;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use untrusted;
|
use std::error;
|
||||||
|
use std::fs::File;
|
||||||
|
use untrusted::Input;
|
||||||
|
|
||||||
pub type KeyPair = Ed25519KeyPair;
|
pub type KeyPair = Ed25519KeyPair;
|
||||||
pub type PublicKey = GenericArray<u8, U32>;
|
pub type PublicKey = GenericArray<u8, U32>;
|
||||||
@@ -24,10 +27,8 @@ impl KeyPairUtil for Ed25519KeyPair {
|
|||||||
/// Return a new ED25519 keypair
|
/// Return a new ED25519 keypair
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let rng = rand::SystemRandom::new();
|
let rng = rand::SystemRandom::new();
|
||||||
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng)
|
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rng).expect("generate_pkcs8");
|
||||||
.expect("generate_pkcs8 in signature pb fn new");
|
Ed25519KeyPair::from_pkcs8(Input::from(&pkcs8_bytes)).expect("from_pcks8")
|
||||||
signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes))
|
|
||||||
.expect("from_pcks8 in signature pb fn new")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the public key for the given keypair
|
/// Return the public key for the given keypair
|
||||||
@@ -42,9 +43,9 @@ pub trait SignatureUtil {
|
|||||||
|
|
||||||
impl SignatureUtil for GenericArray<u8, U64> {
|
impl SignatureUtil for GenericArray<u8, U64> {
|
||||||
fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool {
|
fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool {
|
||||||
let peer_public_key = untrusted::Input::from(peer_public_key_bytes);
|
let peer_public_key = Input::from(peer_public_key_bytes);
|
||||||
let msg = untrusted::Input::from(msg_bytes);
|
let msg = Input::from(msg_bytes);
|
||||||
let sig = untrusted::Input::from(self);
|
let sig = Input::from(self);
|
||||||
signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok()
|
signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,7 @@ impl GenKeys {
|
|||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|seed| {
|
.map(|seed| {
|
||||||
let pkcs8 = GenKeys::new(seed).new_key();
|
let pkcs8 = GenKeys::new(seed).new_key();
|
||||||
KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8)).unwrap()
|
KeyPair::from_pkcs8(Input::from(&pkcs8)).unwrap()
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@@ -91,6 +92,18 @@ impl SecureRandom for GenKeys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_pkcs8(path: &str) -> Result<Vec<u8>, Box<error::Error>> {
|
||||||
|
let file = File::open(path.to_string())?;
|
||||||
|
let pkcs8: Vec<u8> = serde_json::from_reader(file)?;
|
||||||
|
Ok(pkcs8)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_keypair(path: &str) -> Result<KeyPair, Box<error::Error>> {
|
||||||
|
let pkcs8 = read_pkcs8(path)?;
|
||||||
|
let keypair = Ed25519KeyPair::from_pkcs8(Input::from(&pkcs8))?;
|
||||||
|
Ok(keypair)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@@ -7,7 +7,7 @@ extern crate solana;
|
|||||||
use solana::crdt::TestNode;
|
use solana::crdt::TestNode;
|
||||||
use solana::crdt::{Crdt, NodeInfo};
|
use solana::crdt::{Crdt, NodeInfo};
|
||||||
use solana::entry_writer::EntryWriter;
|
use solana::entry_writer::EntryWriter;
|
||||||
use solana::fullnode::{FullNode, InFile, OutFile};
|
use solana::fullnode::{FullNode, LedgerFile};
|
||||||
use solana::logger;
|
use solana::logger;
|
||||||
use solana::mint::Mint;
|
use solana::mint::Mint;
|
||||||
use solana::ncp::Ncp;
|
use solana::ncp::Ncp;
|
||||||
@@ -94,8 +94,7 @@ fn test_multi_node_validator_catchup_from_zero() {
|
|||||||
let server = FullNode::new(
|
let server = FullNode::new(
|
||||||
leader,
|
leader,
|
||||||
true,
|
true,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
None,
|
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -106,10 +105,9 @@ fn test_multi_node_validator_catchup_from_zero() {
|
|||||||
let mut val = FullNode::new(
|
let mut val = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
nodes.push(val);
|
nodes.push(val);
|
||||||
}
|
}
|
||||||
@@ -141,10 +139,9 @@ fn test_multi_node_validator_catchup_from_zero() {
|
|||||||
let val = FullNode::new(
|
let val = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
nodes.push(val);
|
nodes.push(val);
|
||||||
//contains the leader and new node
|
//contains the leader and new node
|
||||||
@@ -196,8 +193,7 @@ fn test_multi_node_basic() {
|
|||||||
let server = FullNode::new(
|
let server = FullNode::new(
|
||||||
leader,
|
leader,
|
||||||
true,
|
true,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
None,
|
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -208,10 +204,9 @@ fn test_multi_node_basic() {
|
|||||||
let val = FullNode::new(
|
let val = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
nodes.push(val);
|
nodes.push(val);
|
||||||
}
|
}
|
||||||
@@ -251,10 +246,9 @@ fn test_boot_validator_from_file() {
|
|||||||
let leader_fullnode = FullNode::new(
|
let leader_fullnode = FullNode::new(
|
||||||
leader,
|
leader,
|
||||||
true,
|
true,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Some(OutFile::Path(ledger_path.clone())),
|
|
||||||
);
|
);
|
||||||
let leader_balance =
|
let leader_balance =
|
||||||
send_tx_and_retry_get_balance(&leader_data, &alice, &bob_pubkey, Some(500)).unwrap();
|
send_tx_and_retry_get_balance(&leader_data, &alice, &bob_pubkey, Some(500)).unwrap();
|
||||||
@@ -269,12 +263,10 @@ fn test_boot_validator_from_file() {
|
|||||||
let val_fullnode = FullNode::new(
|
let val_fullnode = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut client = mk_client(&validator_data);
|
let mut client = mk_client(&validator_data);
|
||||||
let getbal = retry_get_balance(&mut client, &bob_pubkey, Some(leader_balance));
|
let getbal = retry_get_balance(&mut client, &bob_pubkey, Some(leader_balance));
|
||||||
assert!(getbal == Some(leader_balance));
|
assert!(getbal == Some(leader_balance));
|
||||||
@@ -290,10 +282,9 @@ fn create_leader(ledger_path: &str) -> (NodeInfo, FullNode) {
|
|||||||
let leader_fullnode = FullNode::new(
|
let leader_fullnode = FullNode::new(
|
||||||
leader,
|
leader,
|
||||||
true,
|
true,
|
||||||
InFile::Path(ledger_path.to_string()),
|
LedgerFile::Path(ledger_path.to_string()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Some(OutFile::Path(ledger_path.to_string())),
|
|
||||||
);
|
);
|
||||||
(leader_data, leader_fullnode)
|
(leader_data, leader_fullnode)
|
||||||
}
|
}
|
||||||
@@ -342,10 +333,9 @@ fn test_leader_restart_validator_start_from_old_ledger() {
|
|||||||
let val_fullnode = FullNode::new(
|
let val_fullnode = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(stale_ledger_path.clone()),
|
LedgerFile::Path(stale_ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// trigger broadcast, validator should catch up from leader, whose window contains
|
// trigger broadcast, validator should catch up from leader, whose window contains
|
||||||
@@ -386,10 +376,9 @@ fn test_multi_node_dynamic_network() {
|
|||||||
let server = FullNode::new(
|
let server = FullNode::new(
|
||||||
leader,
|
leader,
|
||||||
true,
|
true,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Some(OutFile::Path(ledger_path.clone())),
|
|
||||||
);
|
);
|
||||||
info!("{:x} LEADER", leader_data.debug_id());
|
info!("{:x} LEADER", leader_data.debug_id());
|
||||||
let leader_balance =
|
let leader_balance =
|
||||||
@@ -412,10 +401,9 @@ fn test_multi_node_dynamic_network() {
|
|||||||
let val = FullNode::new(
|
let val = FullNode::new(
|
||||||
validator,
|
validator,
|
||||||
false,
|
false,
|
||||||
InFile::Path(ledger_path.clone()),
|
LedgerFile::Path(ledger_path.clone()),
|
||||||
Some(keypair),
|
Some(keypair),
|
||||||
Some(leader_data.contact_info.ncp),
|
Some(leader_data.contact_info.ncp),
|
||||||
Some(OutFile::Path(ledger_path.clone())),
|
|
||||||
);
|
);
|
||||||
info!("started[{}/{}] {:x}", n, N, rd.debug_id());
|
info!("started[{}/{}] {:x}", n, N, rd.debug_id());
|
||||||
(rd, val)
|
(rd, val)
|
||||||
|
Reference in New Issue
Block a user