mirror of
https://github.com/mimblewimble/grin.git
synced 2025-05-09 10:41:17 +03:00
Formatting.
This commit is contained in:
parent
f79fb8ef95
commit
996eab72ae
13 changed files with 221 additions and 207 deletions
|
@ -28,7 +28,7 @@ use rest::Error;
|
|||
pub fn get<'a, T>(url: &'a str) -> Result<T, Error>
|
||||
where for<'de> T: Deserialize<'de>
|
||||
{
|
||||
println!("get {}", url);
|
||||
println!("get {}", url);
|
||||
let client = hyper::Client::new();
|
||||
let res = check_error(client.get(url).send())?;
|
||||
serde_json::from_reader(res)
|
||||
|
|
|
@ -72,9 +72,11 @@ impl ApiEndpoint for OutputApi {
|
|||
}
|
||||
|
||||
fn get(&self, id: String) -> ApiResult<Output> {
|
||||
debug!("GET output {}", id);
|
||||
let c = util::from_hex(id.clone()).map_err(|e| Error::Argument(format!("Not a valid commitment: {}", id)))?;
|
||||
self.chain_store.get_output_by_commit(&Commitment::from_vec(c)).map_err(|e| Error::Internal(e.to_string()))
|
||||
debug!("GET output {}", id);
|
||||
let c = util::from_hex(id.clone()).map_err(|e| Error::Argument(format!("Not a valid commitment: {}", id)))?;
|
||||
self.chain_store
|
||||
.get_output_by_commit(&Commitment::from_vec(c))
|
||||
.map_err(|e| Error::Internal(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,8 +86,10 @@ pub fn start_rest_apis(addr: String, chain_store: Arc<chain::ChainStore>) {
|
|||
|
||||
thread::spawn(move || {
|
||||
let mut apis = ApiServer::new("/v1".to_string());
|
||||
apis.register_endpoint("/chain".to_string(), ChainApi { chain_store: chain_store.clone() });
|
||||
apis.register_endpoint("/chain/output".to_string(), OutputApi { chain_store: chain_store.clone() });
|
||||
apis.register_endpoint("/chain".to_string(),
|
||||
ChainApi { chain_store: chain_store.clone() });
|
||||
apis.register_endpoint("/chain/output".to_string(),
|
||||
OutputApi { chain_store: chain_store.clone() });
|
||||
apis.start(&addr[..]).unwrap_or_else(|e| {
|
||||
error!("Failed to start API HTTP server: {}.", e);
|
||||
});
|
||||
|
|
|
@ -181,4 +181,4 @@ mod tests {
|
|||
assert_eq!(tip.prev_block_h, d_tip.prev_block_h);
|
||||
assert_eq!(tip.total_difficulty, d_tip.total_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,8 +103,8 @@ impl ChainStore for ChainKVStore {
|
|||
|
||||
// saving the full output under its hash, as well as a commitment to hash index
|
||||
for out in &b.outputs {
|
||||
let mut out_bytes = out.commit.as_ref().to_vec();
|
||||
println!("OUTSAVE: {:?}", out_bytes);
|
||||
let mut out_bytes = out.commit.as_ref().to_vec();
|
||||
println!("OUTSAVE: {:?}", out_bytes);
|
||||
batch = batch.put_enc(&mut BlockCodec::default(),
|
||||
&to_key(OUTPUT_COMMIT_PREFIX, &mut out_bytes)[..],
|
||||
out.hash().clone())?;
|
||||
|
@ -125,7 +125,8 @@ impl ChainStore for ChainKVStore {
|
|||
|
||||
fn get_output_by_commit(&self, commit: &Commitment) -> Result<Output, Error> {
|
||||
option_to_not_found(self.db.get_dec(&mut BlockCodec::default(),
|
||||
&to_key(OUTPUT_COMMIT_PREFIX, &mut commit.as_ref().to_vec())))
|
||||
&to_key(OUTPUT_COMMIT_PREFIX,
|
||||
&mut commit.as_ref().to_vec())))
|
||||
}
|
||||
|
||||
fn has_output_commit(&self, commit: &Commitment) -> Result<Hash, Error> {
|
||||
|
|
|
@ -46,7 +46,7 @@ pub struct BlockHeader {
|
|||
pub timestamp: time::Tm,
|
||||
/// Length of the cuckoo cycle used to mine this block.
|
||||
pub cuckoo_len: u8,
|
||||
/// Merkle root of the UTXO set
|
||||
/// Merkle root of the UTXO set
|
||||
pub utxo_merkle: Hash,
|
||||
/// Merkle tree of hashes for all inputs, outputs and kernels in the block
|
||||
pub tx_merkle: Hash,
|
||||
|
@ -90,7 +90,7 @@ impl Writeable for BlockHeader {
|
|||
[write_u8, self.cuckoo_len],
|
||||
[write_fixed_bytes, &self.utxo_merkle],
|
||||
[write_fixed_bytes, &self.tx_merkle],
|
||||
[write_u8, self.features.bits()]);
|
||||
[write_u8, self.features.bits()]);
|
||||
|
||||
try!(writer.write_u64(self.nonce));
|
||||
try!(self.difficulty.write(writer));
|
||||
|
@ -141,13 +141,13 @@ impl Readable for BlockHeader {
|
|||
/// additive to the total of fees ever collected.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Block {
|
||||
/// The header with metadata and commitments to the rest of the data
|
||||
/// The header with metadata and commitments to the rest of the data
|
||||
pub header: BlockHeader,
|
||||
/// List of transaction inputs
|
||||
/// List of transaction inputs
|
||||
pub inputs: Vec<Input>,
|
||||
/// List of transaction outputs
|
||||
/// List of transaction outputs
|
||||
pub outputs: Vec<Output>,
|
||||
/// List of transaction kernels and associated proofs
|
||||
/// List of transaction kernels and associated proofs
|
||||
pub kernels: Vec<TxKernel>,
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,6 @@ impl Default for Block {
|
|||
}
|
||||
|
||||
impl Block {
|
||||
|
||||
/// Builds a new block from the header of the previous block, a vector of
|
||||
/// transactions and the private key that will receive the reward. Checks
|
||||
/// that all transactions are valid and calculates the Merkle tree.
|
||||
|
@ -240,17 +239,17 @@ impl Block {
|
|||
let secp = Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
let (reward_out, reward_proof) = try!(Block::reward_output(reward_key, &secp));
|
||||
|
||||
Block::with_reward(prev, txs, reward_out, reward_proof)
|
||||
Block::with_reward(prev, txs, reward_out, reward_proof)
|
||||
}
|
||||
|
||||
/// Builds a new block ready to mine from the header of the previous block,
|
||||
/// a vector of transactions and the reward information. Checks
|
||||
/// a vector of transactions and the reward information. Checks
|
||||
/// that all transactions are valid and calculates the Merkle tree.
|
||||
pub fn with_reward(prev: &BlockHeader,
|
||||
txs: Vec<&mut Transaction>,
|
||||
reward_out: Output,
|
||||
reward_kern: TxKernel)
|
||||
-> Result<Block, secp::Error> {
|
||||
txs: Vec<&mut Transaction>,
|
||||
reward_out: Output,
|
||||
reward_kern: TxKernel)
|
||||
-> Result<Block, secp::Error> {
|
||||
// note: the following reads easily but may not be the most efficient due to
|
||||
// repeated iterations, revisit if a problem
|
||||
let secp = Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
|
@ -295,15 +294,15 @@ impl Block {
|
|||
kernels: kernels,
|
||||
}
|
||||
.compact())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Blockhash, computed using only the header
|
||||
/// Blockhash, computed using only the header
|
||||
pub fn hash(&self) -> Hash {
|
||||
self.header.hash()
|
||||
}
|
||||
|
||||
/// Sum of all fees (inputs less outputs) in the block
|
||||
/// Sum of all fees (inputs less outputs) in the block
|
||||
pub fn total_fees(&self) -> u64 {
|
||||
self.kernels.iter().map(|p| p.fee).sum()
|
||||
}
|
||||
|
@ -350,7 +349,8 @@ impl Block {
|
|||
}
|
||||
}
|
||||
|
||||
/// Merges the 2 blocks, essentially appending the inputs, outputs and kernels.
|
||||
/// Merges the 2 blocks, essentially appending the inputs, outputs and
|
||||
/// kernels.
|
||||
/// Also performs a compaction on the result.
|
||||
pub fn merge(&self, other: Block) -> Block {
|
||||
let mut all_inputs = self.inputs.clone();
|
||||
|
@ -448,10 +448,11 @@ impl Block {
|
|||
.verify_kernels(secp)
|
||||
}
|
||||
|
||||
/// Builds the blinded output and related signature proof for the block reward.
|
||||
/// Builds the blinded output and related signature proof for the block
|
||||
/// reward.
|
||||
pub fn reward_output(skey: secp::key::SecretKey,
|
||||
secp: &Secp256k1)
|
||||
-> Result<(Output, TxKernel), secp::Error> {
|
||||
secp: &Secp256k1)
|
||||
-> Result<(Output, TxKernel), secp::Error> {
|
||||
let msg = try!(secp::Message::from_slice(&[0; secp::constants::MESSAGE_SIZE]));
|
||||
let sig = try!(secp.sign(&msg, &skey));
|
||||
let commit = secp.commit(REWARD, skey).unwrap();
|
||||
|
|
|
@ -205,9 +205,8 @@ mod test {
|
|||
#[test]
|
||||
fn blind_simpler_tx() {
|
||||
let secp = Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
let (tx, _) =
|
||||
transaction(vec![input_rand(6), output(2, key::ONE_KEY), with_fee(4)])
|
||||
.unwrap();
|
||||
let (tx, _) = transaction(vec![input_rand(6), output(2, key::ONE_KEY), with_fee(4)])
|
||||
.unwrap();
|
||||
tx.verify_sig(&secp).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,15 +48,15 @@ impl fmt::Display for Hash {
|
|||
}
|
||||
|
||||
impl Hash {
|
||||
/// Builds a Hash from a byte vector. If the vector is too short, it will be
|
||||
/// completed by zeroes. If it's too long, it will be truncated.
|
||||
pub fn from_vec(v: Vec<u8>) -> Hash {
|
||||
let mut h = [0; 32];
|
||||
for i in 0..min(v.len(), 32) {
|
||||
h[i] = v[i];
|
||||
}
|
||||
Hash(h)
|
||||
}
|
||||
/// Builds a Hash from a byte vector. If the vector is too short, it will be
|
||||
/// completed by zeroes. If it's too long, it will be truncated.
|
||||
pub fn from_vec(v: Vec<u8>) -> Hash {
|
||||
let mut h = [0; 32];
|
||||
for i in 0..min(v.len(), 32) {
|
||||
h[i] = v[i];
|
||||
}
|
||||
Hash(h)
|
||||
}
|
||||
|
||||
/// Converts the hash to a byte vector
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
|
@ -65,49 +65,49 @@ impl Hash {
|
|||
}
|
||||
|
||||
impl ops::Index<usize> for Hash {
|
||||
type Output = u8;
|
||||
type Output = u8;
|
||||
|
||||
fn index(&self, idx: usize) -> &u8 {
|
||||
&self.0[idx]
|
||||
}
|
||||
fn index(&self, idx: usize) -> &u8 {
|
||||
&self.0[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::Range<usize>> for Hash {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
fn index(&self, idx: ops::Range<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
fn index(&self, idx: ops::Range<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::RangeTo<usize>> for Hash {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
fn index(&self, idx: ops::RangeTo<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
fn index(&self, idx: ops::RangeTo<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::RangeFrom<usize>> for Hash {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
fn index(&self, idx: ops::RangeFrom<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
fn index(&self, idx: ops::RangeFrom<usize>) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::RangeFull> for Hash {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
fn index(&self, idx: ops::RangeFull) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
fn index(&self, idx: ops::RangeFull) -> &[u8] {
|
||||
&self.0[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Hash {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Readable for Hash {
|
||||
|
@ -133,17 +133,19 @@ pub struct HashWriter {
|
|||
}
|
||||
|
||||
impl HashWriter {
|
||||
/// Consume the `HashWriter`, outputting its current hash into a 32-byte array
|
||||
/// Consume the `HashWriter`, outputting its current hash into a 32-byte
|
||||
/// array
|
||||
pub fn finalize(self, output: &mut [u8]) {
|
||||
self.state.finalize(output);
|
||||
}
|
||||
|
||||
/// Consume the `HashWriter`, outputting a `Hash` corresponding to its current state
|
||||
pub fn into_hash(self) -> Hash {
|
||||
let mut new_hash = ZERO_HASH;
|
||||
/// Consume the `HashWriter`, outputting a `Hash` corresponding to its
|
||||
/// current state
|
||||
pub fn into_hash(self) -> Hash {
|
||||
let mut new_hash = ZERO_HASH;
|
||||
self.state.finalize(&mut new_hash.0[..]);
|
||||
new_hash
|
||||
}
|
||||
new_hash
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HashWriter {
|
||||
|
@ -165,7 +167,7 @@ impl ser::Writer for HashWriter {
|
|||
|
||||
/// A trait for types that have a canonical hash
|
||||
pub trait Hashed {
|
||||
/// Obtain the hash of the object
|
||||
/// Obtain the hash of the object
|
||||
fn hash(&self) -> Hash;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ pub const MAX_TARGET: [u8; 32] = [0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|||
/// The difficulty is defined as the maximum target divided by the block hash.
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub struct Difficulty {
|
||||
num: BigUint
|
||||
num: BigUint,
|
||||
}
|
||||
|
||||
impl Difficulty {
|
||||
|
@ -44,15 +44,15 @@ impl Difficulty {
|
|||
Difficulty { num: BigUint::new(vec![1]) }
|
||||
}
|
||||
|
||||
/// Convert a `u32` into a `Difficulty`
|
||||
/// Convert a `u32` into a `Difficulty`
|
||||
pub fn from_num(num: u32) -> Difficulty {
|
||||
Difficulty { num: BigUint::new(vec![num]) }
|
||||
}
|
||||
|
||||
/// Convert a `BigUint` into a `Difficulty`
|
||||
pub fn from_biguint(num: BigUint) -> Difficulty {
|
||||
Difficulty { num: num }
|
||||
}
|
||||
/// Convert a `BigUint` into a `Difficulty`
|
||||
pub fn from_biguint(num: BigUint) -> Difficulty {
|
||||
Difficulty { num: num }
|
||||
}
|
||||
|
||||
/// Computes the difficulty from a hash. Divides the maximum target by the
|
||||
/// provided hash.
|
||||
|
@ -62,16 +62,16 @@ impl Difficulty {
|
|||
Difficulty { num: max_target / h_num }
|
||||
}
|
||||
|
||||
/// Converts the difficulty into a bignum
|
||||
pub fn into_biguint(self) -> BigUint {
|
||||
self.num
|
||||
}
|
||||
/// Converts the difficulty into a bignum
|
||||
pub fn into_biguint(self) -> BigUint {
|
||||
self.num
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Difficulty {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.num)
|
||||
}
|
||||
write!(f, "{}", self.num)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Difficulty> for Difficulty {
|
||||
|
|
|
@ -55,10 +55,10 @@ pub struct TxKernel {
|
|||
impl Writeable for TxKernel {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||
ser_multiwrite!(writer,
|
||||
[write_u8, self.features.bits()],
|
||||
[write_fixed_bytes, &self.excess],
|
||||
[write_bytes, &self.excess_sig],
|
||||
[write_u64, self.fee]);
|
||||
[write_u8, self.features.bits()],
|
||||
[write_fixed_bytes, &self.excess],
|
||||
[write_bytes, &self.excess_sig],
|
||||
[write_u64, self.fee]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ impl Readable for Input {
|
|||
/// The input for a transaction, which spends a pre-existing output. The input
|
||||
/// commitment is a reproduction of the commitment of the output it's spending.
|
||||
impl Input {
|
||||
/// Extracts the referenced commitment from a transaction output
|
||||
/// Extracts the referenced commitment from a transaction output
|
||||
pub fn commitment(&self) -> Commitment {
|
||||
self.0
|
||||
}
|
||||
|
@ -286,9 +286,9 @@ bitflags! {
|
|||
pub struct Output {
|
||||
/// Options for an output's structure or use
|
||||
pub features: OutputFeatures,
|
||||
/// The homomorphic commitment representing the output's amount
|
||||
/// The homomorphic commitment representing the output's amount
|
||||
pub commit: Commitment,
|
||||
/// A proof that the commitment is in the right range
|
||||
/// A proof that the commitment is in the right range
|
||||
pub proof: RangeProof,
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,9 @@ pub struct Output {
|
|||
/// an Output as binary.
|
||||
impl Writeable for Output {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||
ser_multiwrite!(writer, [write_u8, self.features.bits()], [write_fixed_bytes, &self.commit]);
|
||||
ser_multiwrite!(writer,
|
||||
[write_u8, self.features.bits()],
|
||||
[write_fixed_bytes, &self.commit]);
|
||||
// The hash of an output doesn't include the range proof
|
||||
if writer.serialization_mode() == ser::SerializationMode::Full {
|
||||
writer.write_bytes(&self.proof)?
|
||||
|
|
|
@ -32,9 +32,9 @@ const MAXPATHLEN: usize = 8192;
|
|||
/// A cuckoo-cycle related error
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Unable to find a short enough path
|
||||
/// Unable to find a short enough path
|
||||
Path,
|
||||
/// Unable to find a solution
|
||||
/// Unable to find a solution
|
||||
NoSolution,
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ enum CycleSol {
|
|||
}
|
||||
|
||||
impl Miner {
|
||||
/// Creates a new miner
|
||||
/// Creates a new miner
|
||||
pub fn new(header: &[u8], ease: u32, sizeshift: u32) -> Miner {
|
||||
let cuckoo = Cuckoo::new(header, sizeshift);
|
||||
let size = 1 << sizeshift;
|
||||
|
@ -181,7 +181,7 @@ impl Miner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Searches for a solution
|
||||
/// Searches for a solution
|
||||
pub fn mine(&mut self) -> Result<Proof, Error> {
|
||||
let mut us = [0; MAXPATHLEN];
|
||||
let mut vs = [0; MAXPATHLEN];
|
||||
|
|
|
@ -34,9 +34,9 @@ pub enum Error {
|
|||
IOErr(io::Error),
|
||||
/// Expected a given value that wasn't found
|
||||
UnexpectedData {
|
||||
/// What we wanted
|
||||
/// What we wanted
|
||||
expected: Vec<u8>,
|
||||
/// What we got
|
||||
/// What we got
|
||||
received: Vec<u8>,
|
||||
},
|
||||
/// Data wasn't in a consumable format
|
||||
|
@ -179,7 +179,9 @@ pub trait Writeable {
|
|||
/// Trait that every type that can be deserialized from binary must implement.
|
||||
/// Reads directly to a Reader, a utility type thinly wrapping an
|
||||
/// underlying Read implementation.
|
||||
pub trait Readable where Self: Sized {
|
||||
pub trait Readable
|
||||
where Self: Sized
|
||||
{
|
||||
/// Reads the data necessary to this Readable from the provided reader
|
||||
fn read(reader: &mut Reader) -> Result<Self, Error>;
|
||||
}
|
||||
|
@ -326,36 +328,35 @@ impl_int!(u64, write_u64, read_u64);
|
|||
impl_int!(i64, write_i64, read_i64);
|
||||
|
||||
impl<A: Writeable, B: Writeable> Writeable for (A, B) {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
try!(Writeable::write(&self.0, writer));
|
||||
Writeable::write(&self.1, writer)
|
||||
}
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
try!(Writeable::write(&self.0, writer));
|
||||
Writeable::write(&self.1, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Readable, B: Readable> Readable for (A, B) {
|
||||
fn read(reader: &mut Reader) -> Result<(A, B), Error> {
|
||||
Ok((try!(Readable::read(reader)),
|
||||
try!(Readable::read(reader))))
|
||||
}
|
||||
fn read(reader: &mut Reader) -> Result<(A, B), Error> {
|
||||
Ok((try!(Readable::read(reader)), try!(Readable::read(reader))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Writeable, B: Writeable, C: Writeable> Writeable for (A, B, C) {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
try!(Writeable::write(&self.0, writer));
|
||||
try!(Writeable::write(&self.1, writer));
|
||||
Writeable::write(&self.2, writer)
|
||||
}
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
try!(Writeable::write(&self.0, writer));
|
||||
try!(Writeable::write(&self.1, writer));
|
||||
Writeable::write(&self.2, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Readable, B: Readable, C: Readable> Readable for (A, B, C) {
|
||||
fn read(reader: &mut Reader) -> Result<(A, B, C), Error> {
|
||||
Ok((try!(Readable::read(reader)),
|
||||
try!(Readable::read(reader)),
|
||||
try!(Readable::read(reader))))
|
||||
}
|
||||
fn read(reader: &mut Reader) -> Result<(A, B, C), Error> {
|
||||
Ok((try!(Readable::read(reader)),
|
||||
try!(Readable::read(reader)),
|
||||
try!(Readable::read(reader))))
|
||||
}
|
||||
}
|
||||
|
||||
/// Useful marker trait on types that can be sized byte slices
|
||||
/// Useful marker trait on types that can be sized byte slices
|
||||
pub trait AsFixedBytes: Sized + AsRef<[u8]> {}
|
||||
|
||||
impl<'a> AsFixedBytes for &'a [u8] {}
|
||||
|
|
180
src/bin/grin.rs
180
src/bin/grin.rs
|
@ -45,7 +45,7 @@ use secp::Secp256k1;
|
|||
fn main() {
|
||||
env_logger::init().unwrap();
|
||||
|
||||
let args = App::new("Grin")
|
||||
let args = App::new("Grin")
|
||||
.version("0.1")
|
||||
.author("The Grin Team")
|
||||
.about("Lightweight implementation of the MimbleWimble protocol.")
|
||||
|
@ -109,110 +109,114 @@ fn main() {
|
|||
.takes_value(true))))
|
||||
.get_matches();
|
||||
|
||||
match args.subcommand() {
|
||||
// server commands and options
|
||||
("server", Some(server_args)) => {
|
||||
server_command(server_args);
|
||||
}
|
||||
match args.subcommand() {
|
||||
// server commands and options
|
||||
("server", Some(server_args)) => {
|
||||
server_command(server_args);
|
||||
}
|
||||
|
||||
// client commands and options
|
||||
("client", Some(client_args)) => {
|
||||
match client_args.subcommand() {
|
||||
("status", _) => {
|
||||
println!("status info...");
|
||||
},
|
||||
_ => panic!("Unknown client command, use 'grin help client' for details"),
|
||||
}
|
||||
}
|
||||
// client commands and options
|
||||
("client", Some(client_args)) => {
|
||||
match client_args.subcommand() {
|
||||
("status", _) => {
|
||||
println!("status info...");
|
||||
}
|
||||
_ => panic!("Unknown client command, use 'grin help client' for details"),
|
||||
}
|
||||
}
|
||||
|
||||
// client commands and options
|
||||
("wallet", Some(wallet_args)) => {
|
||||
wallet_command(wallet_args);
|
||||
}
|
||||
// client commands and options
|
||||
("wallet", Some(wallet_args)) => {
|
||||
wallet_command(wallet_args);
|
||||
}
|
||||
|
||||
_ => println!("Unknown command, use 'grin help' for a list of all commands"),
|
||||
}
|
||||
_ => println!("Unknown command, use 'grin help' for a list of all commands"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the server part of the command line, mostly running, starting and
|
||||
/// stopping the Grin blockchain server. Processes all the command line arguments
|
||||
/// stopping the Grin blockchain server. Processes all the command line
|
||||
/// arguments
|
||||
/// to build a proper configuration and runs Grin with that configuration.
|
||||
fn server_command(server_args: &ArgMatches) {
|
||||
info!("Starting the Grin server...");
|
||||
info!("Starting the Grin server...");
|
||||
|
||||
// configuration wrangling
|
||||
let mut server_config = read_config();
|
||||
if let Some(port) = server_args.value_of("port") {
|
||||
server_config.p2p_config.port = port.parse().unwrap();
|
||||
}
|
||||
if server_args.is_present("mine") {
|
||||
server_config.mining_config.enable_mining = true;
|
||||
}
|
||||
if let Some(seeds) = server_args.values_of("seed") {
|
||||
server_config.seeding_type = grin::Seeding::List(seeds.map(|s| s.to_string()).collect());
|
||||
}
|
||||
// configuration wrangling
|
||||
let mut server_config = read_config();
|
||||
if let Some(port) = server_args.value_of("port") {
|
||||
server_config.p2p_config.port = port.parse().unwrap();
|
||||
}
|
||||
if server_args.is_present("mine") {
|
||||
server_config.mining_config.enable_mining = true;
|
||||
}
|
||||
if let Some(seeds) = server_args.values_of("seed") {
|
||||
server_config.seeding_type = grin::Seeding::List(seeds.map(|s| s.to_string()).collect());
|
||||
}
|
||||
|
||||
// start the server in the different run modes (interactive or daemon)
|
||||
match server_args.subcommand() {
|
||||
("run", _) => {
|
||||
grin::Server::start(server_config).unwrap();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
},
|
||||
("start", _) => {
|
||||
let daemonize = Daemonize::new()
|
||||
.pid_file("/tmp/grin.pid")
|
||||
.chown_pid_file(true)
|
||||
.privileged_action(move || {
|
||||
grin::Server::start(server_config.clone()).unwrap();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
});
|
||||
match daemonize.start() {
|
||||
Ok(_) => info!("Grin server succesfully started."),
|
||||
Err(e) => error!("Error starting: {}", e),
|
||||
}
|
||||
}
|
||||
("stop", _) => {
|
||||
println!("TODO, just 'kill $pid' for now.")
|
||||
}
|
||||
_ => panic!("Unknown server command, use 'grin help server' for details"),
|
||||
}
|
||||
// start the server in the different run modes (interactive or daemon)
|
||||
match server_args.subcommand() {
|
||||
("run", _) => {
|
||||
grin::Server::start(server_config).unwrap();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
}
|
||||
("start", _) => {
|
||||
let daemonize = Daemonize::new()
|
||||
.pid_file("/tmp/grin.pid")
|
||||
.chown_pid_file(true)
|
||||
.privileged_action(move || {
|
||||
grin::Server::start(server_config.clone()).unwrap();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
});
|
||||
match daemonize.start() {
|
||||
Ok(_) => info!("Grin server succesfully started."),
|
||||
Err(e) => error!("Error starting: {}", e),
|
||||
}
|
||||
}
|
||||
("stop", _) => println!("TODO, just 'kill $pid' for now."),
|
||||
_ => panic!("Unknown server command, use 'grin help server' for details"),
|
||||
}
|
||||
}
|
||||
|
||||
fn wallet_command(wallet_args: &ArgMatches) {
|
||||
let hd_seed = wallet_args.value_of("pass").expect("Wallet passphrase required.");
|
||||
let hd_seed = wallet_args.value_of("pass").expect("Wallet passphrase required.");
|
||||
|
||||
// TODO do something closer to BIP39, eazy solution right now
|
||||
let mut sha3 = Keccak::new_sha3_256();
|
||||
sha3.update(hd_seed.as_bytes());
|
||||
let mut seed = [0; 32];
|
||||
sha3.finalize(&mut seed);
|
||||
// TODO do something closer to BIP39, eazy solution right now
|
||||
let mut sha3 = Keccak::new_sha3_256();
|
||||
sha3.update(hd_seed.as_bytes());
|
||||
let mut seed = [0; 32];
|
||||
sha3.finalize(&mut seed);
|
||||
|
||||
let s = Secp256k1::new();
|
||||
let key = wallet::ExtendedKey::from_seed(&s, &seed[..]).expect("Error deriving extended key from seed.");
|
||||
let key = wallet::ExtendedKey::from_seed(&s, &seed[..])
|
||||
.expect("Error deriving extended key from seed.");
|
||||
|
||||
match wallet_args.subcommand() {
|
||||
("receive", _) => {
|
||||
info!("Starting the Grin wallet receiving daemon...");
|
||||
let mut apis = api::ApiServer::new("/v1".to_string());
|
||||
apis.register_endpoint("/receive_coinbase".to_string(), wallet::WalletReceiver { key: key });
|
||||
apis.start("127.0.0.1:13416").unwrap_or_else(|e| {
|
||||
error!("Failed to start Grin wallet receiver: {}.", e);
|
||||
});
|
||||
}
|
||||
("send", Some(send_args)) => {
|
||||
let amount = send_args.value_of("amount").expect("Amount to send required").parse().expect("Could not parse amount as a whole number.");
|
||||
let mut dest = "stdout";
|
||||
if let Some(d) = send_args.value_of("dest") {
|
||||
dest = d;
|
||||
}
|
||||
wallet::issue_send_tx(&key, amount, dest.to_string()).unwrap();
|
||||
}
|
||||
_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
|
||||
}
|
||||
match wallet_args.subcommand() {
|
||||
("receive", _) => {
|
||||
info!("Starting the Grin wallet receiving daemon...");
|
||||
let mut apis = api::ApiServer::new("/v1".to_string());
|
||||
apis.register_endpoint("/receive_coinbase".to_string(),
|
||||
wallet::WalletReceiver { key: key });
|
||||
apis.start("127.0.0.1:13416").unwrap_or_else(|e| {
|
||||
error!("Failed to start Grin wallet receiver: {}.", e);
|
||||
});
|
||||
}
|
||||
("send", Some(send_args)) => {
|
||||
let amount = send_args.value_of("amount")
|
||||
.expect("Amount to send required")
|
||||
.parse()
|
||||
.expect("Could not parse amount as a whole number.");
|
||||
let mut dest = "stdout";
|
||||
if let Some(d) = send_args.value_of("dest") {
|
||||
dest = d;
|
||||
}
|
||||
wallet::issue_send_tx(&key, amount, dest.to_string()).unwrap();
|
||||
}
|
||||
_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_config() -> grin::ServerConfig {
|
||||
|
|
|
@ -22,7 +22,7 @@ use extkey::ExtendedKey;
|
|||
use types::*;
|
||||
|
||||
pub fn issue_send_tx(ext_key: &ExtendedKey, amount: u64, dest: String) -> Result<(), Error> {
|
||||
checker::refresh_outputs(&WalletConfig::default(), ext_key);
|
||||
checker::refresh_outputs(&WalletConfig::default(), ext_key);
|
||||
|
||||
let (tx, blind_sum) = build_send_tx(ext_key, amount)?;
|
||||
let json_tx = partial_tx_to_json(amount, blind_sum, tx);
|
||||
|
|
Loading…
Add table
Reference in a new issue