Move drone into its own crate
This commit is contained in:
parent
cf95708c18
commit
d96a6b42a5
|
@ -21,10 +21,6 @@ path = "src/bin/bench-streamer.rs"
|
|||
name = "solana-bench-tps"
|
||||
path = "src/bin/bench-tps.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "solana-drone"
|
||||
path = "src/bin/drone.rs"
|
||||
|
||||
[[bin]]
|
||||
required-features = ["chacha"]
|
||||
name = "solana-replicator"
|
||||
|
@ -113,6 +109,7 @@ tokio = "0.1"
|
|||
tokio-codec = "0.1"
|
||||
untrusted = "0.6.2"
|
||||
solana-bpfloader = { path = "programs/native/bpf_loader", version = "0.11.0" }
|
||||
solana-drone = { path = "drone", version = "0.11.0" }
|
||||
solana-erc20 = { path = "programs/native/erc20", version = "0.11.0" }
|
||||
solana-lualoader = { path = "programs/native/lua_loader", version = "0.11.0" }
|
||||
solana-noop = { path = "programs/native/noop", version = "0.11.0" }
|
||||
|
@ -139,6 +136,7 @@ name = "chacha"
|
|||
[workspace]
|
||||
members = [
|
||||
".",
|
||||
"drone",
|
||||
"metrics",
|
||||
"sdk",
|
||||
"programs/bpf/rust/noop",
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
extern crate bincode;
|
||||
extern crate rayon;
|
||||
extern crate solana;
|
||||
extern crate solana_sdk;
|
||||
extern crate test;
|
||||
|
||||
use solana::bank::*;
|
||||
use solana::hash::hash;
|
||||
use solana::mint::Mint;
|
||||
use solana::signature::{Keypair, KeypairUtil};
|
||||
use solana::system_transaction::SystemTransaction;
|
||||
use solana::transaction::Transaction;
|
||||
use solana_sdk::hash::hash;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
|
|
|
@ -11,12 +11,12 @@ use rayon::prelude::*;
|
|||
use solana::bank::{Bank, MAX_ENTRY_IDS};
|
||||
use solana::banking_stage::{BankingStage, NUM_THREADS};
|
||||
use solana::entry::Entry;
|
||||
use solana::hash::hash;
|
||||
use solana::mint::Mint;
|
||||
use solana::packet::to_packets_chunked;
|
||||
use solana::signature::{KeypairUtil, Signature};
|
||||
use solana::system_transaction::SystemTransaction;
|
||||
use solana::transaction::Transaction;
|
||||
use solana_sdk::hash::hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::iter;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#![feature(test)]
|
||||
extern crate solana;
|
||||
extern crate solana_sdk;
|
||||
extern crate test;
|
||||
|
||||
use solana::entry::reconstruct_entries_from_blobs;
|
||||
use solana::hash::{hash, Hash};
|
||||
use solana::ledger::{next_entries, Block};
|
||||
use solana::signature::{Keypair, KeypairUtil};
|
||||
use solana::system_transaction::SystemTransaction;
|
||||
use solana::transaction::Transaction;
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
cargo-install/
|
||||
usr/
|
||||
|
|
|
@ -18,8 +18,11 @@ if [[ -z $CHANNEL ]]; then
|
|||
fi
|
||||
|
||||
rm -rf usr/
|
||||
../docker-run.sh solanalabs/rust:1.30.0 \
|
||||
../docker-run.sh solanalabs/rust:1.30.1 bash -c "
|
||||
set -ex
|
||||
cargo install --path drone --root ci/docker-solana/usr
|
||||
cargo install --path . --root ci/docker-solana/usr
|
||||
"
|
||||
cp -f entrypoint.sh usr/bin/solana-entrypoint.sh
|
||||
../../scripts/install-native-programs.sh usr/bin/
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ if [[ -n $CI ]]; then
|
|||
fi
|
||||
|
||||
# shellcheck disable=2044 # Disable 'For loops over find output are fragile...'
|
||||
for Cargo_toml in {sdk,metrics,programs/native/{bpf_loader,lua_loader,noop},.}/Cargo.toml; do
|
||||
for Cargo_toml in {sdk,metrics,drone,programs/native/{bpf_loader,lua_loader,noop},.}/Cargo.toml; do
|
||||
# TODO: Ensure the published version matches the contents of BUILDKITE_TAG
|
||||
(
|
||||
set -x
|
||||
|
|
|
@ -43,7 +43,8 @@ echo --- Creating tarball
|
|||
git rev-parse HEAD
|
||||
) > solana-release/version.txt
|
||||
|
||||
cargo install --root solana-release
|
||||
cargo install --path drone --root solana-release
|
||||
cargo install --path . --root solana-release
|
||||
./scripts/install-native-programs.sh solana-release/bin
|
||||
|
||||
./fetch-perf-libs.sh
|
||||
|
|
|
@ -25,6 +25,7 @@ _() {
|
|||
}
|
||||
|
||||
FEATURES=cuda,erasure,chacha
|
||||
_ cargo build --all --verbose --features="$FEATURES"
|
||||
_ cargo test --verbose --features="$FEATURES" --lib
|
||||
|
||||
# Run integration tests serially
|
||||
|
|
|
@ -25,7 +25,7 @@ maybe_install() {
|
|||
}
|
||||
|
||||
_ cargo fmt -- --check
|
||||
_ cargo build --verbose
|
||||
_ cargo build --all --verbose
|
||||
_ cargo test --verbose --lib
|
||||
_ cargo clippy -- --deny=warnings || true
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
[package]
|
||||
name = "solana-drone"
|
||||
version = "0.11.0"
|
||||
description = "Solana Drone"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.0.0"
|
||||
bytes = "0.4"
|
||||
byteorder = "1.2.1"
|
||||
clap = "2.31"
|
||||
log = "0.4.2"
|
||||
serde = "1.0.27"
|
||||
serde_derive = "1.0.27"
|
||||
solana-sdk = { path = "../sdk", version = "0.11.0" }
|
||||
solana-metrics = { path = "../metrics", version = "0.11.0" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
[lib]
|
||||
name = "solana_drone"
|
||||
crate-type = ["lib"]
|
||||
|
||||
[[bin]]
|
||||
name = "solana-drone"
|
||||
path = "src/bin/drone.rs"
|
||||
|
|
@ -4,9 +4,10 @@ extern crate bytes;
|
|||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate log;
|
||||
extern crate serde_json;
|
||||
extern crate solana;
|
||||
#[macro_use]
|
||||
extern crate solana_drone;
|
||||
extern crate solana_metrics;
|
||||
extern crate solana_sdk;
|
||||
extern crate tokio;
|
||||
extern crate tokio_codec;
|
||||
|
||||
|
@ -14,9 +15,9 @@ use bincode::{deserialize, serialize};
|
|||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use bytes::Bytes;
|
||||
use clap::{App, Arg};
|
||||
use solana::drone::{Drone, DroneRequest, DRONE_PORT};
|
||||
use solana::logger;
|
||||
use solana::signature::read_keypair;
|
||||
use solana_drone::drone::{Drone, DroneRequest, DRONE_PORT};
|
||||
//use solana::logger;
|
||||
use solana_sdk::signature::read_keypair;
|
||||
use std::error;
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
@ -26,18 +27,8 @@ use tokio::net::TcpListener;
|
|||
use tokio::prelude::*;
|
||||
use tokio_codec::{BytesCodec, Decoder};
|
||||
|
||||
macro_rules! socketaddr {
|
||||
($ip:expr, $port:expr) => {
|
||||
SocketAddr::from((Ipv4Addr::from($ip), $port))
|
||||
};
|
||||
($str:expr) => {{
|
||||
let a: SocketAddr = $str.parse().unwrap();
|
||||
a
|
||||
}};
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<error::Error>> {
|
||||
logger::setup();
|
||||
//logger::setup();
|
||||
solana_metrics::set_panic_hook("drone");
|
||||
let matches = App::new("drone")
|
||||
.version(crate_version!())
|
|
@ -7,13 +7,14 @@
|
|||
use bincode::{deserialize, serialize};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use bytes::Bytes;
|
||||
use hash::Hash;
|
||||
|
||||
use packet::PACKET_DATA_SIZE;
|
||||
use signature::Keypair;
|
||||
use solana_metrics;
|
||||
use solana_metrics::influxdb;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Keypair;
|
||||
use solana_sdk::system_instruction::{SystemInstruction, SYSTEM_PROGRAM_ID};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use std::io;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
|
||||
|
@ -21,12 +22,21 @@ use std::sync::mpsc::Sender;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use system_transaction::SystemTransaction;
|
||||
use tokio;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::prelude::*;
|
||||
use tokio_codec::{BytesCodec, Decoder};
|
||||
use transaction::Transaction;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! socketaddr {
|
||||
($ip:expr, $port:expr) => {
|
||||
SocketAddr::from((Ipv4Addr::from($ip), $port))
|
||||
};
|
||||
($str:expr) => {{
|
||||
let a: SocketAddr = $str.parse().unwrap();
|
||||
a
|
||||
}};
|
||||
}
|
||||
|
||||
pub const TIME_SLICE: u64 = 60;
|
||||
pub const REQUEST_CAP: u64 = 500_000_000;
|
||||
|
@ -124,9 +134,23 @@ impl Drone {
|
|||
);
|
||||
|
||||
info!("Requesting airdrop of {} to {:?}", tokens, to);
|
||||
let mut tx = Transaction::system_new(&self.mint_keypair, to, tokens, last_id);
|
||||
tx.sign(&[&self.mint_keypair], last_id);
|
||||
Ok(tx)
|
||||
|
||||
let create_instruction = SystemInstruction::CreateAccount {
|
||||
tokens,
|
||||
space: 0,
|
||||
program_id: Pubkey::default(),
|
||||
};
|
||||
let mut transaction = Transaction::new(
|
||||
&self.mint_keypair,
|
||||
&[to],
|
||||
Pubkey::new(&SYSTEM_PROGRAM_ID),
|
||||
&create_instruction,
|
||||
last_id,
|
||||
0, /*fee*/
|
||||
);
|
||||
|
||||
transaction.sign(&[&self.mint_keypair], last_id);
|
||||
Ok(transaction)
|
||||
} else {
|
||||
Err(Error::new(ErrorKind::Other, "token limit reached"))
|
||||
}
|
||||
|
@ -276,7 +300,7 @@ mod tests {
|
|||
use logger;
|
||||
use mint::Mint;
|
||||
use netutil::get_ip_addr;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::net::{SocketAddr, UdpSocket};
|
||||
use std::sync::{Arc, RwLock};
|
|
@ -0,0 +1,14 @@
|
|||
pub mod drone;
|
||||
|
||||
extern crate bincode;
|
||||
extern crate byteorder;
|
||||
extern crate bytes;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate solana_metrics;
|
||||
extern crate solana_sdk;
|
||||
extern crate tokio;
|
||||
extern crate tokio_codec;
|
|
@ -57,10 +57,13 @@ else
|
|||
program=${BASH_REMATCH[1]}
|
||||
features="--features=cuda"
|
||||
fi
|
||||
if [[ "$program" = drone ]]; then
|
||||
maybe_package="--package solana-drone"
|
||||
fi
|
||||
if [[ -z $DEBUG ]]; then
|
||||
maybe_release=--release
|
||||
fi
|
||||
printf "cargo run $maybe_release --bin solana-%s %s -- " "$program" "$features"
|
||||
printf "cargo run $maybe_release $maybe_package --bin solana-%s %s -- " "$program" "$features"
|
||||
}
|
||||
if [[ -n $SOLANA_CUDA ]]; then
|
||||
# shellcheck disable=2154 # 'here' is referenced but not assigned
|
||||
|
|
|
@ -136,7 +136,11 @@ build() {
|
|||
# shellcheck source=/dev/null
|
||||
source target/perf-libs/env.sh
|
||||
fi
|
||||
$MAYBE_DOCKER cargo install --features="$cargoFeatures" --root farf
|
||||
$MAYBE_DOCKER bash -c "
|
||||
set -ex
|
||||
cargo install --path drone --features=$cargoFeatures --root farf
|
||||
cargo install --path . --features=$cargoFeatures --root farf
|
||||
"
|
||||
./scripts/install-native-programs.sh farf/
|
||||
)
|
||||
echo "Build took $SECONDS seconds"
|
||||
|
|
|
@ -11,7 +11,10 @@ bincode = "1.0.0"
|
|||
bs58 = "0.2.0"
|
||||
generic-array = { version = "0.12.0", default-features = false, features = ["serde"] }
|
||||
log = "0.4.2"
|
||||
ring = "0.13.2"
|
||||
sha2 = "0.8.0"
|
||||
serde = "1.0.27"
|
||||
serde_derive = "1.0.27"
|
||||
|
||||
serde_json = "1.0.10"
|
||||
untrusted = "0.6.2"
|
||||
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
pub mod account;
|
||||
pub mod hash;
|
||||
pub mod loader_instruction;
|
||||
pub mod native_program;
|
||||
pub mod packet;
|
||||
pub mod pubkey;
|
||||
pub mod signature;
|
||||
pub mod system_instruction;
|
||||
pub mod timing;
|
||||
pub mod transaction;
|
||||
|
||||
extern crate bincode;
|
||||
extern crate bs58;
|
||||
extern crate generic_array;
|
||||
extern crate log;
|
||||
extern crate ring;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
extern crate sha2;
|
||||
extern crate untrusted;
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
/// Maximum over-the-wire size of a Transaction
|
||||
pub const PACKET_DATA_SIZE: usize = 512;
|
|
@ -0,0 +1,80 @@
|
|||
//! The `signature` module provides functionality for public, and private keys.
|
||||
|
||||
use bs58;
|
||||
use generic_array::typenum::U64;
|
||||
use generic_array::GenericArray;
|
||||
use pubkey::Pubkey;
|
||||
use ring::signature::Ed25519KeyPair;
|
||||
use ring::{rand, signature};
|
||||
use serde_json;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
use untrusted::Input;
|
||||
|
||||
pub type Keypair = Ed25519KeyPair;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Signature(GenericArray<u8, U64>);
|
||||
|
||||
impl Signature {
|
||||
pub fn new(signature_slice: &[u8]) -> Self {
|
||||
Signature(GenericArray::clone_from_slice(&signature_slice))
|
||||
}
|
||||
|
||||
pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
|
||||
let pubkey = Input::from(pubkey_bytes);
|
||||
let message = Input::from(message_bytes);
|
||||
let signature = Input::from(self.0.as_slice());
|
||||
signature::verify(&signature::ED25519, pubkey, message, signature).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Signature {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", bs58::encode(self.0).into_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", bs58::encode(self.0).into_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait KeypairUtil {
|
||||
fn new() -> Self;
|
||||
fn pubkey(&self) -> Pubkey;
|
||||
}
|
||||
|
||||
impl KeypairUtil for Ed25519KeyPair {
|
||||
/// Return a new ED25519 keypair
|
||||
fn new() -> Self {
|
||||
let rng = rand::SystemRandom::new();
|
||||
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rng).expect("generate_pkcs8");
|
||||
Ed25519KeyPair::from_pkcs8(Input::from(&pkcs8_bytes)).expect("from_pcks8")
|
||||
}
|
||||
|
||||
/// Return the public key for the given keypair
|
||||
fn pubkey(&self) -> Pubkey {
|
||||
Pubkey::new(self.public_key_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
use pubkey::Pubkey;
|
||||
|
||||
pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum SystemInstruction {
|
||||
/// Create a new account
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - new account key
|
||||
/// * tokens - number of tokens to transfer to the new account
|
||||
/// * space - memory to allocate if greater then zero
|
||||
/// * program_id - the program id of the new account
|
||||
CreateAccount {
|
||||
tokens: u64,
|
||||
space: u64,
|
||||
program_id: Pubkey,
|
||||
},
|
||||
/// Assign account to a program
|
||||
/// * Transaction::keys[0] - account to assign
|
||||
Assign { program_id: Pubkey },
|
||||
/// Move tokens
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - destination
|
||||
Move { tokens: u64 },
|
||||
|
||||
/// Spawn a new program from an account
|
||||
Spawn,
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
//! The `transaction` module provides functionality for creating log transactions.
|
||||
|
||||
use bincode::serialize;
|
||||
use hash::{Hash, Hasher};
|
||||
use pubkey::Pubkey;
|
||||
use serde::Serialize;
|
||||
use signature::{Keypair, KeypairUtil, Signature};
|
||||
use std::mem::size_of;
|
||||
|
||||
pub const SIG_OFFSET: usize = size_of::<u64>();
|
||||
|
||||
/// An instruction to execute a program under the `program_id` of `program_ids_index` with the
|
||||
/// specified accounts and userdata
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Instruction {
|
||||
/// The program code that executes this transaction is identified by the program_id.
|
||||
/// this is an offset into the Transaction::program_ids field
|
||||
pub program_ids_index: u8,
|
||||
/// Indices into the keys array of which accounts to load
|
||||
pub accounts: Vec<u8>,
|
||||
/// Userdata to be stored in the account
|
||||
pub userdata: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
pub fn new<T: Serialize>(program_ids_index: u8, userdata: &T, accounts: Vec<u8>) -> Self {
|
||||
let userdata = serialize(userdata).unwrap();
|
||||
Instruction {
|
||||
program_ids_index,
|
||||
userdata,
|
||||
accounts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An atomic transaction
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Transaction {
|
||||
/// A set of digital signature of `account_keys`, `program_ids`, `last_id`, `fee` and `instructions`, signed by the first
|
||||
/// signatures.len() keys of account_keys
|
||||
pub signatures: Vec<Signature>,
|
||||
|
||||
/// The `Pubkeys` that are executing this transaction userdata. The meaning of each key is
|
||||
/// program-specific.
|
||||
/// * account_keys[0] - Typically this is the `caller` public key. `signature` is verified with account_keys[0].
|
||||
/// In the future which key pays the fee and which keys have signatures would be configurable.
|
||||
/// * account_keys[1] - Typically this is the program context or the recipient of the tokens
|
||||
pub account_keys: Vec<Pubkey>,
|
||||
|
||||
/// The ID of a recent ledger entry.
|
||||
pub last_id: Hash,
|
||||
|
||||
/// The number of tokens paid for processing and storage of this transaction.
|
||||
pub fee: u64,
|
||||
|
||||
/// Keys identifying programs in the instructions vector.
|
||||
pub program_ids: Vec<Pubkey>,
|
||||
/// Programs that will be executed in sequence and commited in one atomic transaction if all
|
||||
/// succeed.
|
||||
pub instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
impl Transaction {
|
||||
pub fn new<T: Serialize>(
|
||||
from_keypair: &Keypair,
|
||||
transaction_keys: &[Pubkey],
|
||||
program_id: Pubkey,
|
||||
userdata: &T,
|
||||
last_id: Hash,
|
||||
fee: u64,
|
||||
) -> Self {
|
||||
let program_ids = vec![program_id];
|
||||
let accounts = (0..=transaction_keys.len() as u8).collect();
|
||||
let instructions = vec![Instruction::new(0, userdata, accounts)];
|
||||
Self::new_with_instructions(
|
||||
&[from_keypair],
|
||||
transaction_keys,
|
||||
last_id,
|
||||
fee,
|
||||
program_ids,
|
||||
instructions,
|
||||
)
|
||||
}
|
||||
/// Create a signed transaction
|
||||
/// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0]
|
||||
/// * `account_keys` - The keys for the transaction. These are the program state
|
||||
/// instances or token recipient keys.
|
||||
/// * `last_id` - The PoH hash.
|
||||
/// * `fee` - The transaction fee.
|
||||
/// * `program_ids` - The keys that identify programs used in the `instruction` vector.
|
||||
/// * `instructions` - The programs and their arguments that the transaction will execute atomically
|
||||
pub fn new_with_instructions(
|
||||
from_keypairs: &[&Keypair],
|
||||
keys: &[Pubkey],
|
||||
last_id: Hash,
|
||||
fee: u64,
|
||||
program_ids: Vec<Pubkey>,
|
||||
instructions: Vec<Instruction>,
|
||||
) -> Self {
|
||||
let mut account_keys: Vec<_> = from_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.pubkey())
|
||||
.collect();
|
||||
account_keys.extend_from_slice(keys);
|
||||
let mut tx = Transaction {
|
||||
signatures: vec![],
|
||||
account_keys,
|
||||
last_id: Hash::default(),
|
||||
fee,
|
||||
program_ids,
|
||||
instructions,
|
||||
};
|
||||
tx.sign(from_keypairs, last_id);
|
||||
tx
|
||||
}
|
||||
pub fn userdata(&self, instruction_index: usize) -> &[u8] {
|
||||
&self.instructions[instruction_index].userdata
|
||||
}
|
||||
fn key_index(&self, instruction_index: usize, accounts_index: usize) -> Option<usize> {
|
||||
self.instructions
|
||||
.get(instruction_index)
|
||||
.and_then(|instruction| instruction.accounts.get(accounts_index))
|
||||
.map(|&account_keys_index| account_keys_index as usize)
|
||||
}
|
||||
pub fn key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
|
||||
self.key_index(instruction_index, accounts_index)
|
||||
.and_then(|account_keys_index| self.account_keys.get(account_keys_index))
|
||||
}
|
||||
pub fn signed_key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
|
||||
match self.key_index(instruction_index, accounts_index) {
|
||||
None => None,
|
||||
Some(signature_index) => {
|
||||
if signature_index >= self.signatures.len() {
|
||||
return None;
|
||||
}
|
||||
self.account_keys.get(signature_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn program_id(&self, instruction_index: usize) -> &Pubkey {
|
||||
let program_ids_index = self.instructions[instruction_index].program_ids_index;
|
||||
&self.program_ids[program_ids_index as usize]
|
||||
}
|
||||
/// Get the transaction data to sign.
|
||||
pub fn get_sign_data(&self) -> Vec<u8> {
|
||||
let mut data = serialize(&self.account_keys).expect("serialize account_keys");
|
||||
|
||||
let last_id_data = serialize(&self.last_id).expect("serialize last_id");
|
||||
data.extend_from_slice(&last_id_data);
|
||||
|
||||
let fee_data = serialize(&self.fee).expect("serialize fee");
|
||||
data.extend_from_slice(&fee_data);
|
||||
|
||||
let program_ids = serialize(&self.program_ids).expect("serialize program_ids");
|
||||
data.extend_from_slice(&program_ids);
|
||||
|
||||
let instructions = serialize(&self.instructions).expect("serialize instructions");
|
||||
data.extend_from_slice(&instructions);
|
||||
data
|
||||
}
|
||||
|
||||
/// Sign this transaction.
|
||||
pub fn sign(&mut self, keypairs: &[&Keypair], last_id: Hash) {
|
||||
self.last_id = last_id;
|
||||
let sign_data = self.get_sign_data();
|
||||
self.signatures = keypairs
|
||||
.iter()
|
||||
.map(|keypair| Signature::new(&keypair.sign(&sign_data).as_ref()))
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Verify only the transaction signature.
|
||||
pub fn verify_signature(&self) -> bool {
|
||||
self.signatures
|
||||
.iter()
|
||||
.all(|s| s.verify(&self.from().as_ref(), &self.get_sign_data()))
|
||||
}
|
||||
|
||||
/// Verify that references in the instructions are valid
|
||||
pub fn verify_refs(&self) -> bool {
|
||||
for instruction in &self.instructions {
|
||||
if (instruction.program_ids_index as usize) >= self.program_ids.len() {
|
||||
return false;
|
||||
}
|
||||
for account_index in &instruction.accounts {
|
||||
if (*account_index as usize) >= self.account_keys.len() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn from(&self) -> &Pubkey {
|
||||
&self.account_keys[0]
|
||||
}
|
||||
|
||||
// a hash of a slice of transactions only needs to hash the signatures
|
||||
pub fn hash(transactions: &[Transaction]) -> Hash {
|
||||
let mut hasher = Hasher::default();
|
||||
transactions
|
||||
.iter()
|
||||
.for_each(|tx| hasher.hash(&tx.signatures[0].as_ref()));
|
||||
hasher.result()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
|
||||
#[test]
|
||||
fn test_refs() {
|
||||
let key = Keypair::new();
|
||||
let key1 = Keypair::new().pubkey();
|
||||
let key2 = Keypair::new().pubkey();
|
||||
let prog1 = Keypair::new().pubkey();
|
||||
let prog2 = Keypair::new().pubkey();
|
||||
let instructions = vec![
|
||||
Instruction::new(0, &(), vec![0, 1]),
|
||||
Instruction::new(1, &(), vec![0, 2]),
|
||||
];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[key1, key2],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![prog1, prog2],
|
||||
instructions,
|
||||
);
|
||||
assert!(tx.verify_refs());
|
||||
|
||||
assert_eq!(tx.key(0, 0), Some(&key.pubkey()));
|
||||
assert_eq!(tx.signed_key(0, 0), Some(&key.pubkey()));
|
||||
|
||||
assert_eq!(tx.key(1, 0), Some(&key.pubkey()));
|
||||
assert_eq!(tx.signed_key(1, 0), Some(&key.pubkey()));
|
||||
|
||||
assert_eq!(tx.key(0, 1), Some(&key1));
|
||||
assert_eq!(tx.signed_key(0, 1), None);
|
||||
|
||||
assert_eq!(tx.key(1, 1), Some(&key2));
|
||||
assert_eq!(tx.signed_key(1, 1), None);
|
||||
|
||||
assert_eq!(tx.key(2, 0), None);
|
||||
assert_eq!(tx.signed_key(2, 0), None);
|
||||
|
||||
assert_eq!(tx.key(0, 2), None);
|
||||
assert_eq!(tx.signed_key(0, 2), None);
|
||||
|
||||
assert_eq!(*tx.program_id(0), prog1);
|
||||
assert_eq!(*tx.program_id(1), prog2);
|
||||
}
|
||||
#[test]
|
||||
fn test_refs_invalid_program_id() {
|
||||
let key = Keypair::new();
|
||||
let instructions = vec![Instruction::new(1, &(), vec![])];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![],
|
||||
instructions,
|
||||
);
|
||||
assert!(!tx.verify_refs());
|
||||
}
|
||||
#[test]
|
||||
fn test_refs_invalid_account() {
|
||||
let key = Keypair::new();
|
||||
let instructions = vec![Instruction::new(0, &(), vec![1])];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![Default::default()],
|
||||
instructions,
|
||||
);
|
||||
assert_eq!(*tx.program_id(0), Default::default());
|
||||
assert!(!tx.verify_refs());
|
||||
}
|
||||
|
||||
/// Detect binary changes in the serialized contract userdata, which could have a downstream
|
||||
/// affect on SDKs and DApps
|
||||
#[test]
|
||||
fn test_sdk_serialize() {
|
||||
use untrusted::Input;
|
||||
let keypair = Keypair::from_pkcs8(Input::from(&[
|
||||
48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 255, 101, 36, 24, 124, 23,
|
||||
167, 21, 132, 204, 155, 5, 185, 58, 121, 75, 156, 227, 116, 193, 215, 38, 142, 22, 8,
|
||||
14, 229, 239, 119, 93, 5, 218, 161, 35, 3, 33, 0, 36, 100, 158, 252, 33, 161, 97, 185,
|
||||
62, 89, 99, 195, 250, 249, 187, 189, 171, 118, 241, 90, 248, 14, 68, 219, 231, 62, 157,
|
||||
5, 142, 27, 210, 117,
|
||||
])).expect("fu");
|
||||
let to = Pubkey::new(&[
|
||||
1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4,
|
||||
1, 1, 1,
|
||||
]);
|
||||
|
||||
let program_id = Pubkey::new(&[
|
||||
2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4,
|
||||
2, 2, 2,
|
||||
]);
|
||||
|
||||
let tx = Transaction::new(
|
||||
&keypair,
|
||||
&[keypair.pubkey(), to],
|
||||
program_id,
|
||||
&(1u8, 2u8, 3u8),
|
||||
Hash::default(),
|
||||
99,
|
||||
);
|
||||
assert_eq!(
|
||||
serialize(&tx).unwrap(),
|
||||
vec![
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 213, 248, 255, 179, 219, 217, 130, 31, 27, 85, 33, 217, 62,
|
||||
28, 180, 204, 186, 141, 178, 150, 153, 184, 205, 87, 123, 128, 101, 254, 222, 111,
|
||||
152, 17, 153, 210, 169, 1, 81, 208, 254, 64, 229, 205, 145, 10, 213, 241, 255, 31,
|
||||
184, 52, 242, 148, 213, 131, 241, 165, 144, 181, 18, 4, 58, 171, 44, 11, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 36, 100, 158, 252, 33, 161, 97, 185, 62, 89, 99, 195, 250, 249, 187,
|
||||
189, 171, 118, 241, 90, 248, 14, 68, 219, 231, 62, 157, 5, 142, 27, 210, 117, 36,
|
||||
100, 158, 252, 33, 161, 97, 185, 62, 89, 99, 195, 250, 249, 187, 189, 171, 118,
|
||||
241, 90, 248, 14, 68, 219, 231, 62, 157, 5, 142, 27, 210, 117, 1, 1, 1, 4, 5, 6, 7,
|
||||
8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
13
src/bank.rs
13
src/bank.rs
|
@ -9,7 +9,6 @@ use bpf_loader;
|
|||
use budget_program::BudgetState;
|
||||
use counter::Counter;
|
||||
use entry::Entry;
|
||||
use hash::{hash, Hash};
|
||||
use itertools::Itertools;
|
||||
use jsonrpc_macros::pubsub::Sink;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
|
@ -25,7 +24,9 @@ use rpc::RpcSignatureStatus;
|
|||
use signature::Keypair;
|
||||
use signature::Signature;
|
||||
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::timing::{duration_as_us, timestamp};
|
||||
use std;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||
|
@ -1229,15 +1230,15 @@ impl Bank {
|
|||
let tx = &entry1.transactions[0];
|
||||
assert!(SystemProgram::check_id(tx.program_id(0)), "Invalid ledger");
|
||||
assert!(SystemProgram::check_id(tx.program_id(1)), "Invalid ledger");
|
||||
let mut instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap();
|
||||
let mint_deposit = if let SystemProgram::Move { tokens } = instruction {
|
||||
let mut instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
|
||||
let mint_deposit = if let SystemInstruction::Move { tokens } = instruction {
|
||||
Some(tokens)
|
||||
} else {
|
||||
None
|
||||
}.expect("invalid ledger, needs to start with mint deposit");
|
||||
|
||||
instruction = deserialize(tx.userdata(1)).unwrap();
|
||||
let leader_payment = if let SystemProgram::Move { tokens } = instruction {
|
||||
let leader_payment = if let SystemInstruction::Move { tokens } = instruction {
|
||||
Some(tokens)
|
||||
} else {
|
||||
None
|
||||
|
@ -1495,11 +1496,11 @@ mod tests {
|
|||
use budget_program::BudgetState;
|
||||
use entry::next_entry;
|
||||
use entry::Entry;
|
||||
use hash::hash;
|
||||
use jsonrpc_macros::pubsub::{Subscriber, SubscriptionId};
|
||||
use ledger;
|
||||
use signature::Keypair;
|
||||
use signature::{GenKeys, KeypairUtil};
|
||||
use solana_sdk::hash::hash;
|
||||
use std;
|
||||
use system_transaction::SystemTransaction;
|
||||
use tokio::prelude::{Async, Stream};
|
||||
|
@ -1573,7 +1574,7 @@ mod tests {
|
|||
let key1 = Keypair::new().pubkey();
|
||||
let key2 = Keypair::new().pubkey();
|
||||
let bank = Bank::new(&mint);
|
||||
let spend = SystemProgram::Move { tokens: 1 };
|
||||
let spend = SystemInstruction::Move { tokens: 1 };
|
||||
let instructions = vec![
|
||||
Instruction {
|
||||
program_ids_index: 0,
|
||||
|
|
|
@ -7,7 +7,6 @@ use bincode::deserialize;
|
|||
use compute_leader_finality_service::ComputeLeaderFinalityService;
|
||||
use counter::Counter;
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use log::Level;
|
||||
use packet::Packets;
|
||||
use poh_recorder::{PohRecorder, PohRecorderError};
|
||||
|
@ -15,6 +14,7 @@ use poh_service::{Config, PohService};
|
|||
use result::{Error, Result};
|
||||
use service::Service;
|
||||
use sigverify_stage::VerifiedPackets;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::timing;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
|
|
@ -8,6 +8,7 @@ extern crate log;
|
|||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate solana;
|
||||
extern crate solana_drone;
|
||||
extern crate solana_metrics;
|
||||
extern crate solana_sdk;
|
||||
|
||||
|
@ -17,8 +18,6 @@ use rand::{thread_rng, Rng};
|
|||
use rayon::prelude::*;
|
||||
use solana::client::mk_client;
|
||||
use solana::cluster_info::{ClusterInfo, NodeInfo};
|
||||
use solana::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use solana::hash::Hash;
|
||||
use solana::logger;
|
||||
use solana::ncp::Ncp;
|
||||
use solana::service::Service;
|
||||
|
@ -27,7 +26,9 @@ use solana::system_transaction::SystemTransaction;
|
|||
use solana::thin_client::{poll_gossip_for_leader, ThinClient};
|
||||
use solana::transaction::Transaction;
|
||||
use solana::window::default_window;
|
||||
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use solana_metrics::influxdb;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use solana_sdk::timing::{duration_as_ms, duration_as_s};
|
||||
use std::cmp;
|
||||
|
|
|
@ -4,12 +4,12 @@ extern crate getopts;
|
|||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate solana;
|
||||
extern crate solana_drone;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use solana::chacha::{chacha_cbc_encrypt_file, CHACHA_BLOCK_SIZE};
|
||||
use solana::client::mk_client;
|
||||
use solana::cluster_info::Node;
|
||||
use solana::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use solana::fullnode::Config;
|
||||
use solana::ledger::LEDGER_DATA_FILE;
|
||||
use solana::logger;
|
||||
|
@ -17,6 +17,7 @@ use solana::replicator::{sample_file, Replicator};
|
|||
use solana::signature::{Keypair, KeypairUtil};
|
||||
use solana::storage_transaction::StorageTransaction;
|
||||
use solana::transaction::Transaction;
|
||||
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use std::fs::File;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::path::Path;
|
||||
|
|
|
@ -59,7 +59,7 @@ impl<T: BloomHashIndex> Bloom<T> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use hash::{hash, Hash};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
|
||||
#[test]
|
||||
fn test_bloom_filter() {
|
||||
|
|
|
@ -254,9 +254,9 @@ mod test {
|
|||
use budget_program::{BudgetError, BudgetState};
|
||||
use budget_transaction::BudgetTransaction;
|
||||
use chrono::prelude::{DateTime, NaiveDate, Utc};
|
||||
use hash::Hash;
|
||||
use signature::{GenKeys, Keypair, KeypairUtil};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use transaction::Transaction;
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ use budget_expr::{BudgetExpr, Condition};
|
|||
use budget_instruction::Instruction;
|
||||
use budget_program::BudgetState;
|
||||
use chrono::prelude::*;
|
||||
use hash::Hash;
|
||||
use payment_plan::Payment;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use system_program::SystemProgram;
|
||||
use solana_sdk::system_instruction::{SystemInstruction, SYSTEM_PROGRAM_ID};
|
||||
use transaction::{self, Transaction};
|
||||
|
||||
pub trait BudgetTransaction {
|
||||
|
@ -60,7 +60,7 @@ pub trait BudgetTransaction {
|
|||
) -> Self;
|
||||
|
||||
fn instruction(&self, program_index: usize) -> Option<Instruction>;
|
||||
fn system_instruction(&self, program_index: usize) -> Option<SystemProgram>;
|
||||
fn system_instruction(&self, program_index: usize) -> Option<SystemInstruction>;
|
||||
|
||||
fn verify_plan(&self) -> bool;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ impl BudgetTransaction for Transaction {
|
|||
let contract = Keypair::new().pubkey();
|
||||
let keys = vec![from_keypair.pubkey(), contract];
|
||||
|
||||
let system_instruction = SystemProgram::Move { tokens };
|
||||
let system_instruction = SystemInstruction::Move { tokens };
|
||||
|
||||
let payment = Payment {
|
||||
tokens: tokens - fee,
|
||||
|
@ -85,7 +85,7 @@ impl BudgetTransaction for Transaction {
|
|||
};
|
||||
let budget_instruction = Instruction::NewBudget(BudgetExpr::Pay(payment));
|
||||
|
||||
let program_ids = vec![SystemProgram::id(), BudgetState::id()];
|
||||
let program_ids = vec![Pubkey::new(&SYSTEM_PROGRAM_ID), BudgetState::id()];
|
||||
|
||||
let instructions = vec![
|
||||
transaction::Instruction::new(0, &system_instruction, vec![0, 1]),
|
||||
|
@ -206,13 +206,13 @@ impl BudgetTransaction for Transaction {
|
|||
deserialize(&self.userdata(instruction_index)).ok()
|
||||
}
|
||||
|
||||
fn system_instruction(&self, instruction_index: usize) -> Option<SystemProgram> {
|
||||
fn system_instruction(&self, instruction_index: usize) -> Option<SystemInstruction> {
|
||||
deserialize(&self.userdata(instruction_index)).ok()
|
||||
}
|
||||
|
||||
/// Verify only the payment plan.
|
||||
fn verify_plan(&self) -> bool {
|
||||
if let Some(SystemProgram::Move { tokens }) = self.system_instruction(0) {
|
||||
if let Some(SystemInstruction::Move { tokens }) = self.system_instruction(0) {
|
||||
if let Some(Instruction::NewBudget(expr)) = self.instruction(1) {
|
||||
if !(self.fee <= tokens && expr.verify(tokens - self.fee)) {
|
||||
return false;
|
||||
|
@ -284,7 +284,7 @@ mod tests {
|
|||
let pubkey = keypair.pubkey();
|
||||
let mut tx = Transaction::budget_new(&keypair, pubkey, 42, zero);
|
||||
let mut system_instruction = tx.system_instruction(0).unwrap();
|
||||
if let SystemProgram::Move { ref mut tokens } = system_instruction {
|
||||
if let SystemInstruction::Move { ref mut tokens } = system_instruction {
|
||||
*tokens = 1_000_000; // <-- attack, part 1!
|
||||
let mut instruction = tx.instruction(1).unwrap();
|
||||
if let Instruction::NewBudget(ref mut expr) = instruction {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use chacha::{CHACHA_BLOCK_SIZE, CHACHA_KEY_SIZE};
|
||||
use hash::Hash;
|
||||
use ledger::LedgerWindow;
|
||||
use sigverify::{chacha_cbc_encrypt_many_sample, chacha_end_sha_state, chacha_init_sha_state};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::io;
|
||||
use std::mem::size_of;
|
||||
|
||||
|
@ -102,10 +102,10 @@ pub fn chacha_cbc_encrypt_file_many_keys(
|
|||
mod tests {
|
||||
use chacha::chacha_cbc_encrypt_file;
|
||||
use chacha_cuda::chacha_cbc_encrypt_file_many_keys;
|
||||
use hash::Hash;
|
||||
use ledger::LedgerWriter;
|
||||
use ledger::{get_tmp_ledger_path, make_tiny_test_entries, LEDGER_DATA_FILE};
|
||||
use replicator::sample_file;
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::fs::{remove_dir_all, remove_file};
|
||||
use std::path::Path;
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ use counter::Counter;
|
|||
use crds_gossip::CrdsGossip;
|
||||
use crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
|
||||
use crds_value::{CrdsValue, CrdsValueLabel, LeaderId};
|
||||
use hash::Hash;
|
||||
use ledger::LedgerWindow;
|
||||
use log::Level;
|
||||
use netutil::{bind_in_range, bind_to, find_available_port_in_range, multi_bind_in_range};
|
||||
|
@ -29,6 +28,7 @@ use rayon::prelude::*;
|
|||
use result::Result;
|
||||
use rpc::RPC_PORT;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::timing::{duration_as_ms, timestamp};
|
||||
use std::collections::HashMap;
|
||||
|
@ -1046,12 +1046,12 @@ mod tests {
|
|||
use super::*;
|
||||
use crds_value::CrdsValueLabel;
|
||||
use entry::Entry;
|
||||
use hash::{hash, Hash};
|
||||
use ledger::{get_tmp_ledger_path, LedgerWindow, LedgerWriter};
|
||||
use logger;
|
||||
use packet::SharedBlob;
|
||||
use result::Error;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
|
|
@ -136,10 +136,10 @@ pub mod tests {
|
|||
use bank::Bank;
|
||||
use bincode::serialize;
|
||||
use compute_leader_finality_service::ComputeLeaderFinalityService;
|
||||
use hash::hash;
|
||||
use logger;
|
||||
use mint::Mint;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::hash;
|
||||
use std::sync::Arc;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
|
||||
use bincode::serialize;
|
||||
use crds_value::{CrdsValue, CrdsValueLabel};
|
||||
use hash::{hash, Hash};
|
||||
use indexmap::map::IndexMap;
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::cmp;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use crds_gossip_error::CrdsGossipError;
|
|||
use crds_gossip_pull::CrdsGossipPull;
|
||||
use crds_gossip_push::{CrdsGossipPush, CRDS_GOSSIP_NUM_ACTIVE};
|
||||
use crds_value::CrdsValue;
|
||||
use hash::Hash;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
pub struct CrdsGossip {
|
||||
|
|
|
@ -14,10 +14,10 @@ use bloom::Bloom;
|
|||
use crds::Crds;
|
||||
use crds_gossip_error::CrdsGossipError;
|
||||
use crds_value::{CrdsValue, CrdsValueLabel};
|
||||
use hash::Hash;
|
||||
use packet::BLOB_DATA_SIZE;
|
||||
use rand;
|
||||
use rand::distributions::{Distribution, Weighted, WeightedChoice};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
|
|
|
@ -13,10 +13,10 @@ use bloom::Bloom;
|
|||
use crds::{Crds, VersionedCrdsValue};
|
||||
use crds_gossip_error::CrdsGossipError;
|
||||
use crds_value::{CrdsValue, CrdsValueLabel};
|
||||
use hash::Hash;
|
||||
use indexmap::map::IndexMap;
|
||||
use packet::BLOB_DATA_SIZE;
|
||||
use rand::{self, Rng};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bloom::BloomHashIndex;
|
||||
use hash::Hash;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
fn slice_hash(slice: &[u8], hash_index: u64) -> u64 {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
//! transactions within it. Entries cannot be reordered, and its field `num_hashes`
|
||||
//! represents an approximate amount of time since the last Entry was created.
|
||||
use bincode::{deserialize, serialize_into, serialized_size};
|
||||
use hash::Hash;
|
||||
use packet::{SharedBlob, BLOB_DATA_SIZE};
|
||||
use poh::Poh;
|
||||
use result::Result;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::io::Cursor;
|
||||
use std::mem::size_of;
|
||||
|
@ -275,8 +275,8 @@ mod tests {
|
|||
use budget_transaction::BudgetTransaction;
|
||||
use chrono::prelude::*;
|
||||
use entry::Entry;
|
||||
use hash::hash;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::hash;
|
||||
use system_transaction::SystemTransaction;
|
||||
use transaction::Transaction;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use bank::Bank;
|
||||
use broadcast_stage::BroadcastStage;
|
||||
use cluster_info::{ClusterInfo, Node, NodeInfo};
|
||||
use hash::Hash;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use ledger::read_ledger;
|
||||
use ncp::Ncp;
|
||||
|
@ -11,6 +10,7 @@ use rpc::JsonRpcService;
|
|||
use rpc_pubsub::PubSubService;
|
||||
use service::Service;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::net::UdpSocket;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
|
|
|
@ -6,9 +6,9 @@ use bank::Bank;
|
|||
use bincode::serialize;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use entry::Entry;
|
||||
use hash::{hash, Hash};
|
||||
use ledger::create_ticks;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Cursor;
|
||||
|
@ -493,13 +493,13 @@ pub fn make_active_set_entries(
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bank::Bank;
|
||||
use hash::Hash;
|
||||
use leader_scheduler::{
|
||||
LeaderScheduler, LeaderSchedulerConfig, DEFAULT_BOOTSTRAP_HEIGHT,
|
||||
DEFAULT_LEADER_ROTATION_INTERVAL, DEFAULT_SEED_ROTATION_INTERVAL,
|
||||
};
|
||||
use mint::Mint;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash as StdHash;
|
||||
|
|
|
@ -8,14 +8,14 @@ use budget_transaction::BudgetTransaction;
|
|||
#[cfg(test)]
|
||||
use chrono::prelude::Utc;
|
||||
use entry::Entry;
|
||||
#[cfg(test)]
|
||||
use hash::hash;
|
||||
use hash::Hash;
|
||||
use log::Level::Trace;
|
||||
use mint::Mint;
|
||||
use packet::{SharedBlob, BLOB_DATA_SIZE};
|
||||
use rayon::prelude::*;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
#[cfg(test)]
|
||||
use solana_sdk::hash::hash;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::fs::{create_dir_all, remove_dir_all, File, OpenOptions};
|
||||
use std::io::prelude::*;
|
||||
|
@ -672,9 +672,9 @@ mod tests {
|
|||
use bincode::{deserialize, serialized_size};
|
||||
use budget_transaction::BudgetTransaction;
|
||||
use entry::{next_entry, reconstruct_entries_from_blobs, Entry};
|
||||
use hash::hash;
|
||||
use packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::hash;
|
||||
use std;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use transaction::Transaction;
|
||||
|
|
|
@ -36,13 +36,11 @@ pub mod budget_program;
|
|||
pub mod cluster_info;
|
||||
pub mod compute_leader_finality_service;
|
||||
pub mod db_ledger;
|
||||
pub mod drone;
|
||||
pub mod entry;
|
||||
#[cfg(feature = "erasure")]
|
||||
pub mod erasure;
|
||||
pub mod fetch_stage;
|
||||
pub mod fullnode;
|
||||
pub mod hash;
|
||||
pub mod leader_scheduler;
|
||||
pub mod ledger;
|
||||
pub mod ledger_write_stage;
|
||||
|
@ -122,6 +120,7 @@ extern crate serde_json;
|
|||
extern crate serde_cbor;
|
||||
extern crate sha2;
|
||||
extern crate socket2;
|
||||
extern crate solana_drone;
|
||||
extern crate solana_jsonrpc_core as jsonrpc_core;
|
||||
extern crate solana_jsonrpc_http_server as jsonrpc_http_server;
|
||||
#[macro_use]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! The `dynamic_transaction` module provides functionality for loading and calling a program
|
||||
|
||||
use hash::Hash;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::loader_instruction::LoaderInstruction;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use transaction::Transaction;
|
||||
|
|
15
src/mint.rs
15
src/mint.rs
|
@ -1,9 +1,9 @@
|
|||
//! The `mint` module is a library for generating the chain's genesis block.
|
||||
|
||||
use entry::Entry;
|
||||
use hash::{hash, Hash};
|
||||
use ring::rand::SystemRandom;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use system_transaction::SystemTransaction;
|
||||
use transaction::Transaction;
|
||||
|
@ -108,6 +108,7 @@ mod tests {
|
|||
use super::*;
|
||||
use bincode::deserialize;
|
||||
use ledger::Block;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use system_program::SystemProgram;
|
||||
|
||||
#[test]
|
||||
|
@ -116,8 +117,8 @@ mod tests {
|
|||
let tx = transactions.next().unwrap();
|
||||
assert_eq!(tx.instructions.len(), 1);
|
||||
assert!(SystemProgram::check_id(tx.program_id(0)));
|
||||
let instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap();
|
||||
if let SystemProgram::Move { tokens } = instruction {
|
||||
let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
|
||||
if let SystemInstruction::Move { tokens } = instruction {
|
||||
assert_eq!(tokens, 100);
|
||||
}
|
||||
assert_eq!(transactions.next(), None);
|
||||
|
@ -134,12 +135,12 @@ mod tests {
|
|||
assert_eq!(tx.instructions.len(), 2);
|
||||
assert!(SystemProgram::check_id(tx.program_id(0)));
|
||||
assert!(SystemProgram::check_id(tx.program_id(1)));
|
||||
let instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap();
|
||||
if let SystemProgram::Move { tokens } = instruction {
|
||||
let instruction: SystemInstruction = deserialize(tx.userdata(0)).unwrap();
|
||||
if let SystemInstruction::Move { tokens } = instruction {
|
||||
assert_eq!(tokens, 100);
|
||||
}
|
||||
let instruction: SystemProgram = deserialize(tx.userdata(1)).unwrap();
|
||||
if let SystemProgram::Move { tokens } = instruction {
|
||||
let instruction: SystemInstruction = deserialize(tx.userdata(1)).unwrap();
|
||||
if let SystemInstruction::Move { tokens } = instruction {
|
||||
assert_eq!(tokens, 1);
|
||||
}
|
||||
assert_eq!(transactions.next(), None);
|
||||
|
|
|
@ -5,13 +5,14 @@ use counter::Counter;
|
|||
#[cfg(test)]
|
||||
use entry::Entry;
|
||||
#[cfg(test)]
|
||||
use hash::Hash;
|
||||
#[cfg(test)]
|
||||
use ledger::Block;
|
||||
use log::Level;
|
||||
use recvmmsg::{recv_mmsg, NUM_RCVMMSGS};
|
||||
use result::{Error, Result};
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use solana_sdk::hash::Hash;
|
||||
pub use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
@ -27,7 +28,6 @@ pub type SharedBlobs = Vec<SharedBlob>;
|
|||
pub const NUM_PACKETS: usize = 1024 * 8;
|
||||
pub const BLOB_SIZE: usize = (64 * 1024 - 128); // wikipedia says there should be 20b for ipv4 headers
|
||||
pub const BLOB_DATA_SIZE: usize = BLOB_SIZE - (BLOB_HEADER_SIZE * 2);
|
||||
pub const PACKET_DATA_SIZE: usize = 512;
|
||||
pub const NUM_BLOBS: usize = (NUM_PACKETS * PACKET_DATA_SIZE) / BLOB_SIZE;
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq)]
|
||||
|
@ -457,12 +457,12 @@ pub fn make_consecutive_blobs(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hash::Hash;
|
||||
use packet::{
|
||||
to_packets, Blob, Meta, Packet, Packets, SharedBlob, SharedPackets, NUM_PACKETS,
|
||||
PACKET_DATA_SIZE,
|
||||
};
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::net::UdpSocket;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! The `Poh` module provides an object for generating a Proof of History.
|
||||
//! It records Hashes items on behalf of its users.
|
||||
use hash::{hash, hashv, Hash};
|
||||
use solana_sdk::hash::{hash, hashv, Hash};
|
||||
|
||||
pub struct Poh {
|
||||
prev_id: Hash,
|
||||
|
@ -96,8 +96,8 @@ pub fn verify(initial: Hash, entries: &[PohEntry]) -> bool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hash::Hash;
|
||||
use poh::{self, PohEntry};
|
||||
use solana_sdk::hash::Hash;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
//!
|
||||
use bank::Bank;
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use poh::Poh;
|
||||
use result::{Error, Result};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use transaction::Transaction;
|
||||
|
@ -118,8 +118,8 @@ impl PohRecorder {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use hash::hash;
|
||||
use mint::Mint;
|
||||
use solana_sdk::hash::hash;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Arc;
|
||||
use system_transaction::test_tx;
|
||||
|
|
|
@ -4,7 +4,7 @@ use bank::Bank;
|
|||
use cluster_info::ClusterInfo;
|
||||
use counter::Counter;
|
||||
use entry::{EntryReceiver, EntrySender};
|
||||
use hash::Hash;
|
||||
use solana_sdk::hash::Hash;
|
||||
|
||||
use ledger::Block;
|
||||
use log::Level;
|
||||
|
@ -246,7 +246,6 @@ mod test {
|
|||
use cluster_info::{ClusterInfo, Node};
|
||||
use entry::Entry;
|
||||
use fullnode::Fullnode;
|
||||
use hash::Hash;
|
||||
use leader_scheduler::{make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig};
|
||||
use ledger::{create_ticks, create_tmp_sample_ledger, LedgerWriter};
|
||||
use logger;
|
||||
|
@ -255,6 +254,7 @@ mod test {
|
|||
use result::Error;
|
||||
use service::Service;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::fs::remove_dir_all;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::channel;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use blob_fetch_stage::BlobFetchStage;
|
||||
use cluster_info::{ClusterInfo, Node, NodeInfo};
|
||||
use hash::{Hash, Hasher};
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use ncp::Ncp;
|
||||
use service::Service;
|
||||
use solana_sdk::hash::{Hash, Hasher};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufReader;
|
||||
|
@ -168,13 +168,13 @@ mod tests {
|
|||
use client::mk_client;
|
||||
use cluster_info::Node;
|
||||
use fullnode::Fullnode;
|
||||
use hash::Hash;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use ledger::{create_tmp_genesis, get_tmp_ledger_path, read_ledger};
|
||||
use logger;
|
||||
use replicator::sample_file;
|
||||
use replicator::Replicator;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::fs::File;
|
||||
use std::fs::{create_dir_all, remove_dir_all, remove_file};
|
||||
use std::io::Write;
|
||||
|
|
|
@ -4,12 +4,12 @@ use bank::{Bank, BankError};
|
|||
use bincode::{deserialize, serialize};
|
||||
use bs58;
|
||||
use cluster_info::ClusterInfo;
|
||||
use drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use jsonrpc_core::*;
|
||||
use jsonrpc_http_server::*;
|
||||
use packet::PACKET_DATA_SIZE;
|
||||
use service::Service;
|
||||
use signature::Signature;
|
||||
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::mem;
|
||||
|
@ -363,7 +363,6 @@ mod tests {
|
|||
use bincode::serialize;
|
||||
use cluster_info::{Node, NodeInfo};
|
||||
use fullnode::Fullnode;
|
||||
use hash::{hash, Hash};
|
||||
use jsonrpc_core::Response;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use ledger::create_tmp_ledger_with_mint;
|
||||
|
@ -371,6 +370,7 @@ mod tests {
|
|||
use reqwest;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use system_transaction::SystemTransaction;
|
||||
|
|
|
@ -1,72 +1,10 @@
|
|||
//! The `signature` module provides functionality for public, and private keys.
|
||||
|
||||
use bs58;
|
||||
use generic_array::typenum::U64;
|
||||
use generic_array::GenericArray;
|
||||
use rand::{ChaChaRng, Rng, SeedableRng};
|
||||
use rayon::prelude::*;
|
||||
use ring::signature::Ed25519KeyPair;
|
||||
use ring::{rand, signature};
|
||||
use serde_json;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
use untrusted::Input;
|
||||
|
||||
pub type Keypair = Ed25519KeyPair;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Signature(GenericArray<u8, U64>);
|
||||
|
||||
impl Signature {
|
||||
pub fn new(signature_slice: &[u8]) -> Self {
|
||||
Signature(GenericArray::clone_from_slice(&signature_slice))
|
||||
}
|
||||
pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
|
||||
let pubkey = Input::from(pubkey_bytes);
|
||||
let message = Input::from(message_bytes);
|
||||
let signature = Input::from(self.0.as_slice());
|
||||
signature::verify(&signature::ED25519, pubkey, message, signature).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Signature {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", bs58::encode(self.0).into_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", bs58::encode(self.0).into_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait KeypairUtil {
|
||||
fn new() -> Self;
|
||||
fn pubkey(&self) -> Pubkey;
|
||||
}
|
||||
|
||||
impl KeypairUtil for Ed25519KeyPair {
|
||||
/// Return a new ED25519 keypair
|
||||
fn new() -> Self {
|
||||
let rng = rand::SystemRandom::new();
|
||||
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rng).expect("generate_pkcs8");
|
||||
Ed25519KeyPair::from_pkcs8(Input::from(&pkcs8_bytes)).expect("from_pcks8")
|
||||
}
|
||||
|
||||
/// Return the public key for the given keypair
|
||||
fn pubkey(&self) -> Pubkey {
|
||||
Pubkey::new(self.public_key_bytes())
|
||||
}
|
||||
}
|
||||
pub use solana_sdk::signature::*;
|
||||
|
||||
pub struct GenKeys {
|
||||
generator: ChaChaRng,
|
||||
|
@ -96,21 +34,10 @@ impl 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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
pub use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -324,10 +324,11 @@ pub fn make_packet_from_transaction(tx: Transaction) -> Packet {
|
|||
mod tests {
|
||||
use bincode::serialize;
|
||||
use budget_program::BudgetState;
|
||||
use hash::Hash;
|
||||
use packet::{Packet, SharedPackets};
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use sigverify;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use system_program::SystemProgram;
|
||||
use system_transaction::{memfind, test_tx};
|
||||
use transaction;
|
||||
|
@ -426,7 +427,7 @@ mod tests {
|
|||
|
||||
let keys = vec![keypair0.pubkey(), keypair1.pubkey()];
|
||||
|
||||
let system_instruction = SystemProgram::Move { tokens };
|
||||
let system_instruction = SystemInstruction::Move { tokens };
|
||||
|
||||
let program_ids = vec![SystemProgram::id(), BudgetState::id()];
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
//! and give reward for good proofs.
|
||||
|
||||
use bincode::deserialize;
|
||||
use hash::Hash;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use transaction::Transaction;
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
#[cfg(all(feature = "chacha", feature = "cuda"))]
|
||||
use chacha_cuda::chacha_cbc_encrypt_file_many_keys;
|
||||
use entry::EntryReceiver;
|
||||
use hash::Hash;
|
||||
use rand::{ChaChaRng, Rng, SeedableRng};
|
||||
use result::{Error, Result};
|
||||
use service::Service;
|
||||
use signature::Keypair;
|
||||
use signature::Signature;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::mem::size_of;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -260,12 +260,12 @@ impl Service for StorageStage {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use ledger::make_tiny_test_entries;
|
||||
use ledger::{create_tmp_sample_ledger, LedgerWriter};
|
||||
use logger;
|
||||
use service::Service;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::cmp::{max, min};
|
||||
use std::fs::remove_dir_all;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use hash::Hash;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use storage_program::StorageProgram;
|
||||
use transaction::Transaction;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use bincode::deserialize;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use std;
|
||||
use transaction::Transaction;
|
||||
|
||||
|
@ -22,30 +23,7 @@ impl std::error::Error for Error {}
|
|||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum SystemProgram {
|
||||
/// Create a new account
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - new account key
|
||||
/// * tokens - number of tokens to transfer to the new account
|
||||
/// * space - memory to allocate if greater then zero
|
||||
/// * program_id - the program id of the new account
|
||||
CreateAccount {
|
||||
tokens: u64,
|
||||
space: u64,
|
||||
program_id: Pubkey,
|
||||
},
|
||||
/// Assign account to a program
|
||||
/// * Transaction::keys[0] - account to assign
|
||||
Assign { program_id: Pubkey },
|
||||
/// Move tokens
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - destination
|
||||
Move { tokens: u64 },
|
||||
|
||||
/// Spawn a new program from an account
|
||||
Spawn,
|
||||
}
|
||||
pub struct SystemProgram {}
|
||||
|
||||
pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];
|
||||
|
||||
|
@ -68,7 +46,7 @@ impl SystemProgram {
|
|||
if let Ok(syscall) = deserialize(tx.userdata(pix)) {
|
||||
trace!("process_transaction: {:?}", syscall);
|
||||
match syscall {
|
||||
SystemProgram::CreateAccount {
|
||||
SystemInstruction::CreateAccount {
|
||||
tokens,
|
||||
space,
|
||||
program_id,
|
||||
|
@ -95,13 +73,13 @@ impl SystemProgram {
|
|||
accounts[1].executable = false;
|
||||
accounts[1].loader = Pubkey::default();
|
||||
}
|
||||
SystemProgram::Assign { program_id } => {
|
||||
SystemInstruction::Assign { program_id } => {
|
||||
if !Self::check_id(&accounts[0].owner) {
|
||||
Err(Error::AssignOfUnownedAccount)?;
|
||||
}
|
||||
accounts[0].owner = program_id;
|
||||
}
|
||||
SystemProgram::Move { tokens } => {
|
||||
SystemInstruction::Move { tokens } => {
|
||||
//bank should be verifying correctness
|
||||
if tokens > accounts[0].tokens {
|
||||
info!("Insufficient tokens in account[0]");
|
||||
|
@ -110,7 +88,7 @@ impl SystemProgram {
|
|||
accounts[0].tokens -= tokens;
|
||||
accounts[1].tokens += tokens;
|
||||
}
|
||||
SystemProgram::Spawn => {
|
||||
SystemInstruction::Spawn => {
|
||||
if !accounts[0].executable || accounts[0].loader != Pubkey::default() {
|
||||
Err(Error::AccountNotFinalized)?;
|
||||
}
|
||||
|
@ -128,9 +106,9 @@ impl SystemProgram {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use hash::Hash;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use system_program::SystemProgram;
|
||||
use system_transaction::SystemTransaction;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
//! The `system_transaction` module provides functionality for creating system transactions.
|
||||
|
||||
use hash::Hash;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use system_program::SystemProgram;
|
||||
|
||||
use transaction::{Instruction, Transaction};
|
||||
|
||||
pub trait SystemTransaction {
|
||||
|
@ -40,7 +42,7 @@ pub trait SystemTransaction {
|
|||
}
|
||||
|
||||
impl SystemTransaction for Transaction {
|
||||
/// Create and sign new SystemProgram::CreateAccount transaction
|
||||
/// Create and sign new SystemInstruction::CreateAccount transaction
|
||||
fn system_create(
|
||||
from_keypair: &Keypair,
|
||||
to: Pubkey,
|
||||
|
@ -50,7 +52,7 @@ impl SystemTransaction for Transaction {
|
|||
program_id: Pubkey,
|
||||
fee: u64,
|
||||
) -> Self {
|
||||
let create = SystemProgram::CreateAccount {
|
||||
let create = SystemInstruction::CreateAccount {
|
||||
tokens, //TODO, the tokens to allocate might need to be higher then 0 in the future
|
||||
space,
|
||||
program_id,
|
||||
|
@ -64,9 +66,9 @@ impl SystemTransaction for Transaction {
|
|||
fee,
|
||||
)
|
||||
}
|
||||
/// Create and sign new SystemProgram::Assign transaction
|
||||
/// Create and sign new SystemInstruction::Assign transaction
|
||||
fn system_assign(from_keypair: &Keypair, last_id: Hash, program_id: Pubkey, fee: u64) -> Self {
|
||||
let assign = SystemProgram::Assign { program_id };
|
||||
let assign = SystemInstruction::Assign { program_id };
|
||||
Transaction::new(
|
||||
from_keypair,
|
||||
&[],
|
||||
|
@ -76,11 +78,11 @@ impl SystemTransaction for Transaction {
|
|||
fee,
|
||||
)
|
||||
}
|
||||
/// Create and sign new SystemProgram::CreateAccount transaction with some defaults
|
||||
/// Create and sign new SystemInstruction::CreateAccount transaction with some defaults
|
||||
fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: u64, last_id: Hash) -> Self {
|
||||
Transaction::system_create(from_keypair, to, last_id, tokens, 0, Pubkey::default(), 0)
|
||||
}
|
||||
/// Create and sign new SystemProgram::Move transaction
|
||||
/// Create and sign new SystemInstruction::Move transaction
|
||||
fn system_move(
|
||||
from_keypair: &Keypair,
|
||||
to: Pubkey,
|
||||
|
@ -88,7 +90,7 @@ impl SystemTransaction for Transaction {
|
|||
last_id: Hash,
|
||||
fee: u64,
|
||||
) -> Self {
|
||||
let move_tokens = SystemProgram::Move { tokens };
|
||||
let move_tokens = SystemInstruction::Move { tokens };
|
||||
Transaction::new(
|
||||
from_keypair,
|
||||
&[to],
|
||||
|
@ -98,13 +100,13 @@ impl SystemTransaction for Transaction {
|
|||
fee,
|
||||
)
|
||||
}
|
||||
/// Create and sign new SystemProgram::Move transaction to many destinations
|
||||
/// Create and sign new SystemInstruction::Move transaction to many destinations
|
||||
fn system_move_many(from: &Keypair, moves: &[(Pubkey, u64)], last_id: Hash, fee: u64) -> Self {
|
||||
let instructions: Vec<_> = moves
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (_, amount))| {
|
||||
let spend = SystemProgram::Move { tokens: *amount };
|
||||
let spend = SystemInstruction::Move { tokens: *amount };
|
||||
Instruction::new(0, &spend, vec![0, i as u8 + 1])
|
||||
}).collect();
|
||||
let to_keys: Vec<_> = moves.iter().map(|(to_key, _)| *to_key).collect();
|
||||
|
@ -118,9 +120,9 @@ impl SystemTransaction for Transaction {
|
|||
instructions,
|
||||
)
|
||||
}
|
||||
/// Create and sign new SystemProgram::Spawn transaction
|
||||
/// Create and sign new SystemInstruction::Spawn transaction
|
||||
fn system_spawn(from_keypair: &Keypair, last_id: Hash, fee: u64) -> Self {
|
||||
let spawn = SystemProgram::Spawn;
|
||||
let spawn = SystemInstruction::Spawn;
|
||||
Transaction::new(from_keypair, &[], SystemProgram::id(), &spawn, last_id, fee)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use bank::Bank;
|
|||
use bincode::serialize;
|
||||
use bs58;
|
||||
use cluster_info::{ClusterInfo, ClusterInfoError, NodeInfo};
|
||||
use hash::Hash;
|
||||
use log::Level;
|
||||
use ncp::Ncp;
|
||||
use packet::PACKET_DATA_SIZE;
|
||||
|
@ -18,6 +17,7 @@ use signature::{Keypair, Signature};
|
|||
use solana_metrics;
|
||||
use solana_metrics::influxdb;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::timing;
|
||||
use std;
|
||||
|
@ -417,8 +417,8 @@ mod tests {
|
|||
use logger;
|
||||
use mint::Mint;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use std::fs::remove_dir_all;
|
||||
use system_program::SystemProgram;
|
||||
use vote_program::VoteProgram;
|
||||
use vote_transaction::VoteTransaction;
|
||||
|
||||
|
@ -520,7 +520,7 @@ mod tests {
|
|||
|
||||
let mut tr2 = Transaction::system_new(&alice.keypair(), bob_pubkey, 501, last_id);
|
||||
let mut instruction2 = deserialize(tr2.userdata(0)).unwrap();
|
||||
if let SystemProgram::Move { ref mut tokens } = instruction2 {
|
||||
if let SystemInstruction::Move { ref mut tokens } = instruction2 {
|
||||
*tokens = 502;
|
||||
}
|
||||
tr2.instructions[0].userdata = serialize(&instruction2).unwrap();
|
||||
|
|
|
@ -5,11 +5,11 @@ use bank::Bank;
|
|||
use banking_stage::{BankingStage, BankingStageReturnType};
|
||||
use entry::Entry;
|
||||
use fetch_stage::FetchStage;
|
||||
use hash::Hash;
|
||||
use ledger_write_stage::LedgerWriteStage;
|
||||
use poh_service::Config;
|
||||
use service::Service;
|
||||
use sigverify_stage::SigVerifyStage;
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
|
|
@ -1,329 +1 @@
|
|||
//! The `transaction` module provides functionality for creating log transactions.
|
||||
|
||||
use bincode::serialize;
|
||||
use hash::{Hash, Hasher};
|
||||
use serde::Serialize;
|
||||
use signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::mem::size_of;
|
||||
|
||||
pub const SIG_OFFSET: usize = size_of::<u64>();
|
||||
|
||||
/// An instruction to execute a program under the `program_id` of `program_ids_index` with the
|
||||
/// specified accounts and userdata
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Instruction {
|
||||
/// The program code that executes this transaction is identified by the program_id.
|
||||
/// this is an offset into the Transaction::program_ids field
|
||||
pub program_ids_index: u8,
|
||||
/// Indices into the keys array of which accounts to load
|
||||
pub accounts: Vec<u8>,
|
||||
/// Userdata to be stored in the account
|
||||
pub userdata: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
pub fn new<T: Serialize>(program_ids_index: u8, userdata: &T, accounts: Vec<u8>) -> Self {
|
||||
let userdata = serialize(userdata).unwrap();
|
||||
Instruction {
|
||||
program_ids_index,
|
||||
userdata,
|
||||
accounts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An atomic transaction
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Transaction {
|
||||
/// A set of digital signature of `account_keys`, `program_ids`, `last_id`, `fee` and `instructions`, signed by the first
|
||||
/// signatures.len() keys of account_keys
|
||||
pub signatures: Vec<Signature>,
|
||||
|
||||
/// The `Pubkeys` that are executing this transaction userdata. The meaning of each key is
|
||||
/// program-specific.
|
||||
/// * account_keys[0] - Typically this is the `caller` public key. `signature` is verified with account_keys[0].
|
||||
/// In the future which key pays the fee and which keys have signatures would be configurable.
|
||||
/// * account_keys[1] - Typically this is the program context or the recipient of the tokens
|
||||
pub account_keys: Vec<Pubkey>,
|
||||
|
||||
/// The ID of a recent ledger entry.
|
||||
pub last_id: Hash,
|
||||
|
||||
/// The number of tokens paid for processing and storage of this transaction.
|
||||
pub fee: u64,
|
||||
|
||||
/// Keys identifying programs in the instructions vector.
|
||||
pub program_ids: Vec<Pubkey>,
|
||||
/// Programs that will be executed in sequence and commited in one atomic transaction if all
|
||||
/// succeed.
|
||||
pub instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
impl Transaction {
|
||||
pub fn new<T: Serialize>(
|
||||
from_keypair: &Keypair,
|
||||
transaction_keys: &[Pubkey],
|
||||
program_id: Pubkey,
|
||||
userdata: &T,
|
||||
last_id: Hash,
|
||||
fee: u64,
|
||||
) -> Self {
|
||||
let program_ids = vec![program_id];
|
||||
let accounts = (0..=transaction_keys.len() as u8).collect();
|
||||
let instructions = vec![Instruction::new(0, userdata, accounts)];
|
||||
Self::new_with_instructions(
|
||||
&[from_keypair],
|
||||
transaction_keys,
|
||||
last_id,
|
||||
fee,
|
||||
program_ids,
|
||||
instructions,
|
||||
)
|
||||
}
|
||||
/// Create a signed transaction
|
||||
/// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0]
|
||||
/// * `account_keys` - The keys for the transaction. These are the program state
|
||||
/// instances or token recipient keys.
|
||||
/// * `last_id` - The PoH hash.
|
||||
/// * `fee` - The transaction fee.
|
||||
/// * `program_ids` - The keys that identify programs used in the `instruction` vector.
|
||||
/// * `instructions` - The programs and their arguments that the transaction will execute atomically
|
||||
pub fn new_with_instructions(
|
||||
from_keypairs: &[&Keypair],
|
||||
keys: &[Pubkey],
|
||||
last_id: Hash,
|
||||
fee: u64,
|
||||
program_ids: Vec<Pubkey>,
|
||||
instructions: Vec<Instruction>,
|
||||
) -> Self {
|
||||
let mut account_keys: Vec<_> = from_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.pubkey())
|
||||
.collect();
|
||||
account_keys.extend_from_slice(keys);
|
||||
let mut tx = Transaction {
|
||||
signatures: vec![],
|
||||
account_keys,
|
||||
last_id: Hash::default(),
|
||||
fee,
|
||||
program_ids,
|
||||
instructions,
|
||||
};
|
||||
tx.sign(from_keypairs, last_id);
|
||||
tx
|
||||
}
|
||||
pub fn userdata(&self, instruction_index: usize) -> &[u8] {
|
||||
&self.instructions[instruction_index].userdata
|
||||
}
|
||||
fn key_index(&self, instruction_index: usize, accounts_index: usize) -> Option<usize> {
|
||||
self.instructions
|
||||
.get(instruction_index)
|
||||
.and_then(|instruction| instruction.accounts.get(accounts_index))
|
||||
.map(|&account_keys_index| account_keys_index as usize)
|
||||
}
|
||||
pub fn key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
|
||||
self.key_index(instruction_index, accounts_index)
|
||||
.and_then(|account_keys_index| self.account_keys.get(account_keys_index))
|
||||
}
|
||||
pub fn signed_key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
|
||||
match self.key_index(instruction_index, accounts_index) {
|
||||
None => None,
|
||||
Some(signature_index) => {
|
||||
if signature_index >= self.signatures.len() {
|
||||
return None;
|
||||
}
|
||||
self.account_keys.get(signature_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn program_id(&self, instruction_index: usize) -> &Pubkey {
|
||||
let program_ids_index = self.instructions[instruction_index].program_ids_index;
|
||||
&self.program_ids[program_ids_index as usize]
|
||||
}
|
||||
/// Get the transaction data to sign.
|
||||
pub fn get_sign_data(&self) -> Vec<u8> {
|
||||
let mut data = serialize(&self.account_keys).expect("serialize account_keys");
|
||||
|
||||
let last_id_data = serialize(&self.last_id).expect("serialize last_id");
|
||||
data.extend_from_slice(&last_id_data);
|
||||
|
||||
let fee_data = serialize(&self.fee).expect("serialize fee");
|
||||
data.extend_from_slice(&fee_data);
|
||||
|
||||
let program_ids = serialize(&self.program_ids).expect("serialize program_ids");
|
||||
data.extend_from_slice(&program_ids);
|
||||
|
||||
let instructions = serialize(&self.instructions).expect("serialize instructions");
|
||||
data.extend_from_slice(&instructions);
|
||||
data
|
||||
}
|
||||
|
||||
/// Sign this transaction.
|
||||
pub fn sign(&mut self, keypairs: &[&Keypair], last_id: Hash) {
|
||||
self.last_id = last_id;
|
||||
let sign_data = self.get_sign_data();
|
||||
self.signatures = keypairs
|
||||
.iter()
|
||||
.map(|keypair| Signature::new(&keypair.sign(&sign_data).as_ref()))
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Verify only the transaction signature.
|
||||
pub fn verify_signature(&self) -> bool {
|
||||
warn!("transaction signature verification called");
|
||||
self.signatures
|
||||
.iter()
|
||||
.all(|s| s.verify(&self.from().as_ref(), &self.get_sign_data()))
|
||||
}
|
||||
|
||||
/// Verify that references in the instructions are valid
|
||||
pub fn verify_refs(&self) -> bool {
|
||||
for instruction in &self.instructions {
|
||||
if (instruction.program_ids_index as usize) >= self.program_ids.len() {
|
||||
return false;
|
||||
}
|
||||
for account_index in &instruction.accounts {
|
||||
if (*account_index as usize) >= self.account_keys.len() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn from(&self) -> &Pubkey {
|
||||
&self.account_keys[0]
|
||||
}
|
||||
|
||||
// a hash of a slice of transactions only needs to hash the signatures
|
||||
pub fn hash(transactions: &[Transaction]) -> Hash {
|
||||
let mut hasher = Hasher::default();
|
||||
transactions
|
||||
.iter()
|
||||
.for_each(|tx| hasher.hash(&tx.signatures[0].as_ref()));
|
||||
hasher.result()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
use signature::GenKeys;
|
||||
|
||||
#[test]
|
||||
fn test_refs() {
|
||||
let key = Keypair::new();
|
||||
let key1 = Keypair::new().pubkey();
|
||||
let key2 = Keypair::new().pubkey();
|
||||
let prog1 = Keypair::new().pubkey();
|
||||
let prog2 = Keypair::new().pubkey();
|
||||
let instructions = vec![
|
||||
Instruction::new(0, &(), vec![0, 1]),
|
||||
Instruction::new(1, &(), vec![0, 2]),
|
||||
];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[key1, key2],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![prog1, prog2],
|
||||
instructions,
|
||||
);
|
||||
assert!(tx.verify_refs());
|
||||
|
||||
assert_eq!(tx.key(0, 0), Some(&key.pubkey()));
|
||||
assert_eq!(tx.signed_key(0, 0), Some(&key.pubkey()));
|
||||
|
||||
assert_eq!(tx.key(1, 0), Some(&key.pubkey()));
|
||||
assert_eq!(tx.signed_key(1, 0), Some(&key.pubkey()));
|
||||
|
||||
assert_eq!(tx.key(0, 1), Some(&key1));
|
||||
assert_eq!(tx.signed_key(0, 1), None);
|
||||
|
||||
assert_eq!(tx.key(1, 1), Some(&key2));
|
||||
assert_eq!(tx.signed_key(1, 1), None);
|
||||
|
||||
assert_eq!(tx.key(2, 0), None);
|
||||
assert_eq!(tx.signed_key(2, 0), None);
|
||||
|
||||
assert_eq!(tx.key(0, 2), None);
|
||||
assert_eq!(tx.signed_key(0, 2), None);
|
||||
|
||||
assert_eq!(*tx.program_id(0), prog1);
|
||||
assert_eq!(*tx.program_id(1), prog2);
|
||||
}
|
||||
#[test]
|
||||
fn test_refs_invalid_program_id() {
|
||||
let key = Keypair::new();
|
||||
let instructions = vec![Instruction::new(1, &(), vec![])];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![],
|
||||
instructions,
|
||||
);
|
||||
assert!(!tx.verify_refs());
|
||||
}
|
||||
#[test]
|
||||
fn test_refs_invalid_account() {
|
||||
let key = Keypair::new();
|
||||
let instructions = vec![Instruction::new(0, &(), vec![1])];
|
||||
let tx = Transaction::new_with_instructions(
|
||||
&[&key],
|
||||
&[],
|
||||
Default::default(),
|
||||
0,
|
||||
vec![Default::default()],
|
||||
instructions,
|
||||
);
|
||||
assert_eq!(*tx.program_id(0), Default::default());
|
||||
assert!(!tx.verify_refs());
|
||||
}
|
||||
|
||||
/// Detect binary changes in the serialized contract userdata, which could have a downstream
|
||||
/// affect on SDKs and DApps
|
||||
#[test]
|
||||
fn test_sdk_serialize() {
|
||||
let keypair = &GenKeys::new([0u8; 32]).gen_n_keypairs(1)[0];
|
||||
let to = Pubkey::new(&[
|
||||
1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4,
|
||||
1, 1, 1,
|
||||
]);
|
||||
|
||||
let program_id = Pubkey::new(&[
|
||||
2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4,
|
||||
2, 2, 2,
|
||||
]);
|
||||
|
||||
let tx = Transaction::new(
|
||||
keypair,
|
||||
&[keypair.pubkey(), to],
|
||||
program_id,
|
||||
&(1u8, 2u8, 3u8),
|
||||
Hash::default(),
|
||||
99,
|
||||
);
|
||||
assert_eq!(
|
||||
serialize(&tx).unwrap(),
|
||||
vec![
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 234, 139, 34, 5, 120, 28, 107, 203, 69, 25, 236, 200, 164,
|
||||
1, 12, 47, 147, 53, 41, 143, 23, 116, 230, 203, 59, 228, 153, 14, 22, 241, 103,
|
||||
226, 186, 169, 181, 65, 49, 215, 44, 2, 61, 214, 113, 216, 184, 206, 147, 104, 140,
|
||||
225, 138, 21, 172, 135, 211, 80, 103, 80, 216, 106, 249, 86, 194, 1, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, 59, 206,
|
||||
105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, 68, 32,
|
||||
253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, 59, 206, 105, 231, 150,
|
||||
215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, 68, 1, 1, 1, 4, 5, 6,
|
||||
7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 5, 6, 7, 8, 9,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
pub use solana_sdk::transaction::*;
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
use bank::Bank;
|
||||
use blob_fetch_stage::BlobFetchStage;
|
||||
use cluster_info::ClusterInfo;
|
||||
use hash::Hash;
|
||||
use ledger_write_stage::LedgerWriteStage;
|
||||
use replicate_stage::{ReplicateStage, ReplicateStageReturnType};
|
||||
use retransmit_stage::RetransmitStage;
|
||||
use service::Service;
|
||||
use signature::Keypair;
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
@ -167,7 +167,6 @@ pub mod tests {
|
|||
use bincode::serialize;
|
||||
use cluster_info::{ClusterInfo, Node};
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use logger;
|
||||
use mint::Mint;
|
||||
|
@ -175,6 +174,7 @@ pub mod tests {
|
|||
use packet::SharedBlob;
|
||||
use service::Service;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::channel;
|
||||
|
|
|
@ -4,11 +4,11 @@ use bank::Bank;
|
|||
use bincode::serialize;
|
||||
use cluster_info::ClusterInfo;
|
||||
use counter::Counter;
|
||||
use hash::Hash;
|
||||
use log::Level;
|
||||
use packet::SharedBlob;
|
||||
use result::{Error, Result};
|
||||
use signature::Keypair;
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
#[cfg(test)]
|
||||
use bank::Bank;
|
||||
use bincode::deserialize;
|
||||
use hash::Hash;
|
||||
#[cfg(test)]
|
||||
use result::Result;
|
||||
use signature::Keypair;
|
||||
#[cfg(test)]
|
||||
use signature::KeypairUtil;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use system_transaction::SystemTransaction;
|
||||
use transaction::Transaction;
|
||||
|
|
|
@ -5,10 +5,8 @@ use budget_program::BudgetState;
|
|||
use budget_transaction::BudgetTransaction;
|
||||
use chrono::prelude::*;
|
||||
use clap::ArgMatches;
|
||||
use drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use elf;
|
||||
use fullnode::Config;
|
||||
use hash::Hash;
|
||||
use loader_transaction::LoaderTransaction;
|
||||
use ring::rand::SystemRandom;
|
||||
use ring::signature::Ed25519KeyPair;
|
||||
|
@ -16,6 +14,8 @@ use rpc::RpcSignatureStatus;
|
|||
use rpc_request::RpcRequest;
|
||||
use serde_json;
|
||||
use signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
|
@ -759,12 +759,12 @@ mod tests {
|
|||
use bank::Bank;
|
||||
use clap::{App, Arg, SubCommand};
|
||||
use cluster_info::Node;
|
||||
use drone::run_local_drone;
|
||||
use fullnode::Fullnode;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use ledger::create_tmp_genesis;
|
||||
use serde_json::Value;
|
||||
use signature::{read_keypair, read_pkcs8, Keypair, KeypairUtil};
|
||||
use solana_drone::drone::run_local_drone;
|
||||
use std::fs::remove_dir_all;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
|
|
@ -354,10 +354,10 @@ pub fn window_service(
|
|||
mod test {
|
||||
use cluster_info::{ClusterInfo, Node};
|
||||
use entry::Entry;
|
||||
use hash::Hash;
|
||||
use leader_scheduler::LeaderScheduler;
|
||||
use logger;
|
||||
use packet::{make_consecutive_blobs, SharedBlob, PACKET_DATA_SIZE};
|
||||
use solana_sdk::hash::Hash;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
|
|
|
@ -10,7 +10,6 @@ use solana::blob_fetch_stage::BlobFetchStage;
|
|||
use solana::cluster_info::{ClusterInfo, Node, NodeInfo};
|
||||
use solana::entry::{reconstruct_entries_from_blobs, Entry};
|
||||
use solana::fullnode::{Fullnode, FullnodeReturnType};
|
||||
use solana::hash::Hash;
|
||||
use solana::leader_scheduler::{make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig};
|
||||
use solana::ledger::{
|
||||
create_tmp_genesis, create_tmp_sample_ledger, get_tmp_ledger_path, read_ledger, LedgerWindow,
|
||||
|
@ -28,6 +27,7 @@ use solana::system_transaction::SystemTransaction;
|
|||
use solana::thin_client::{retry_get_balance, ThinClient};
|
||||
use solana::transaction::Transaction;
|
||||
use solana::window::default_window;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::timing::{duration_as_ms, duration_as_s};
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
|
|
Loading…
Reference in New Issue