mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Pass pubkey for coinbase (#159)
* store wallet output data in hashmap * cleanup up commented out code * pass pubkey/identifier and not derivation around to miner etc. * fix failing tests
This commit is contained in:
parent
c7f1ce965e
commit
3dd1dde00b
14 changed files with 249 additions and 69 deletions
|
@ -80,7 +80,7 @@ fn mine_empty_chain() {
|
|||
for n in 1..4 {
|
||||
let prev = chain.head_header().unwrap();
|
||||
let pk = keychain.derive_pubkey(n as u32).unwrap();
|
||||
let mut b = core::core::Block::new(&prev, vec![], &keychain, pk).unwrap();
|
||||
let mut b = core::core::Block::new(&prev, vec![], &keychain, &pk).unwrap();
|
||||
b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||
|
@ -251,7 +251,7 @@ fn prepare_block_nosum(prev: &BlockHeader, diff: u64) -> Block {
|
|||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let pubkey = keychain.derive_pubkey(1).unwrap();
|
||||
|
||||
let mut b = core::core::Block::new(prev, vec![], &keychain, pubkey).unwrap();
|
||||
let mut b = core::core::Block::new(prev, vec![], &keychain, &pubkey).unwrap();
|
||||
b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
b.header.total_difficulty = Difficulty::from_num(diff);
|
||||
b
|
||||
|
|
|
@ -39,7 +39,7 @@ fn test_various_store_indices() {
|
|||
|
||||
let chain_store = &chain::store::ChainKVStore::new(".grin".to_string()).unwrap() as &ChainStore;
|
||||
|
||||
let block = Block::new(&BlockHeader::default(), vec![], &keychain, pubkey).unwrap();
|
||||
let block = Block::new(&BlockHeader::default(), vec![], &keychain, &pubkey).unwrap();
|
||||
let commit = block.outputs[0].commitment();
|
||||
let block_hash = block.hash();
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ fn test_coinbase_maturity() {
|
|||
let pk3 = keychain.derive_pubkey(3).unwrap();
|
||||
let pk4 = keychain.derive_pubkey(4).unwrap();
|
||||
|
||||
let mut block = core::core::Block::new(&prev, vec![], &keychain, pk1.clone()).unwrap();
|
||||
let mut block = core::core::Block::new(&prev, vec![], &keychain, &pk1).unwrap();
|
||||
block.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||
|
@ -109,8 +109,7 @@ fn test_coinbase_maturity() {
|
|||
&keychain,
|
||||
).unwrap();
|
||||
|
||||
let mut block = core::core::Block::new(&prev, vec![&coinbase_txn], &keychain, pk3.clone())
|
||||
.unwrap();
|
||||
let mut block = core::core::Block::new(&prev, vec![&coinbase_txn], &keychain, &pk3).unwrap();
|
||||
block.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||
|
@ -138,7 +137,7 @@ fn test_coinbase_maturity() {
|
|||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let pk = keychain.derive_pubkey(1).unwrap();
|
||||
|
||||
let mut block = core::core::Block::new(&prev, vec![], &keychain, pk).unwrap();
|
||||
let mut block = core::core::Block::new(&prev, vec![], &keychain, &pk).unwrap();
|
||||
block.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||
|
@ -157,7 +156,7 @@ fn test_coinbase_maturity() {
|
|||
|
||||
let prev = chain.head_header().unwrap();
|
||||
|
||||
let mut block = core::core::Block::new(&prev, vec![&coinbase_txn], &keychain, pk4).unwrap();
|
||||
let mut block = core::core::Block::new(&prev, vec![&coinbase_txn], &keychain, &pk4).unwrap();
|
||||
|
||||
block.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ impl Block {
|
|||
prev: &BlockHeader,
|
||||
txs: Vec<&Transaction>,
|
||||
keychain: &keychain::Keychain,
|
||||
pubkey: keychain::Identifier,
|
||||
pubkey: &keychain::Identifier,
|
||||
) -> Result<Block, keychain::Error> {
|
||||
|
||||
let fees = txs.iter().map(|tx| tx.fee).sum();
|
||||
|
@ -469,11 +469,18 @@ impl Block {
|
|||
// * That the sum of blinding factors for all coinbase-marked outputs match
|
||||
// the coinbase-marked kernels.
|
||||
fn verify_coinbase(&self, secp: &Secp256k1) -> Result<(), Error> {
|
||||
let cb_outs = filter_map_vec!(self.outputs, |out| {
|
||||
if out.features.contains(COINBASE_OUTPUT) { Some(out.commitment()) } else { None }
|
||||
let cb_outs = filter_map_vec!(self.outputs, |out| if out.features.contains(
|
||||
COINBASE_OUTPUT,
|
||||
)
|
||||
{
|
||||
Some(out.commitment())
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let cb_kerns = filter_map_vec!(self.kernels, |k| {
|
||||
if k.features.contains(COINBASE_KERNEL) { Some(k.excess) } else { None }
|
||||
let cb_kerns = filter_map_vec!(self.kernels, |k| if k.features.contains(COINBASE_KERNEL) {
|
||||
Some(k.excess)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
|
||||
let over_commit = secp.commit_value(reward(self.total_fees()))?;
|
||||
|
@ -490,16 +497,15 @@ impl Block {
|
|||
/// reward.
|
||||
pub fn reward_output(
|
||||
keychain: &keychain::Keychain,
|
||||
pubkey: keychain::Identifier,
|
||||
pubkey: &keychain::Identifier,
|
||||
fees: u64,
|
||||
) -> Result<(Output, TxKernel), keychain::Error> {
|
||||
|
||||
let secp = keychain.secp();
|
||||
|
||||
let commit = keychain.commit(reward(fees), &pubkey)?;
|
||||
let commit = keychain.commit(reward(fees), pubkey)?;
|
||||
// let switch_commit = keychain.switch_commit(pubkey)?;
|
||||
let msg = secp::pedersen::ProofMessage::empty();
|
||||
let rproof = keychain.range_proof(reward(fees), &pubkey, commit, msg)?;
|
||||
let rproof = keychain.range_proof(reward(fees), pubkey, commit, msg)?;
|
||||
|
||||
let output = Output {
|
||||
features: COINBASE_OUTPUT,
|
||||
|
@ -540,7 +546,7 @@ mod test {
|
|||
// header
|
||||
fn new_block(txs: Vec<&Transaction>, keychain: &Keychain) -> Block {
|
||||
let pubkey = keychain.derive_pubkey(1).unwrap();
|
||||
Block::new(&BlockHeader::default(), txs, keychain, pubkey).unwrap()
|
||||
Block::new(&BlockHeader::default(), txs, keychain, &pubkey).unwrap()
|
||||
}
|
||||
|
||||
// utility producing a transaction that spends an output with the provided
|
||||
|
|
|
@ -329,7 +329,7 @@ mod test {
|
|||
let keychain = new_keychain();
|
||||
let pubkey = keychain.derive_pubkey(1).unwrap();
|
||||
|
||||
let b = Block::new(&BlockHeader::default(), vec![], &keychain, pubkey).unwrap();
|
||||
let b = Block::new(&BlockHeader::default(), vec![], &keychain, &pubkey).unwrap();
|
||||
b.compact().validate(&keychain.secp()).unwrap();
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ mod test {
|
|||
let mut tx1 = tx2i1o();
|
||||
tx1.verify_sig(keychain.secp()).unwrap();
|
||||
|
||||
let b = Block::new(&BlockHeader::default(), vec![&mut tx1], &keychain, pubkey).unwrap();
|
||||
let b = Block::new(&BlockHeader::default(), vec![&mut tx1], &keychain, &pubkey).unwrap();
|
||||
b.compact().validate(keychain.secp()).unwrap();
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ mod test {
|
|||
let mut tx2 = tx1i1o();
|
||||
tx2.verify_sig(keychain.secp()).unwrap();
|
||||
|
||||
let b = Block::new(&BlockHeader::default(), vec![&mut tx1, &mut tx2], &keychain, pubkey).unwrap();
|
||||
let b = Block::new(&BlockHeader::default(), vec![&mut tx1, &mut tx2], &keychain, &pubkey).unwrap();
|
||||
b.validate(keychain.secp()).unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
use std::{error, fmt, cmp};
|
||||
use std::io::{self, Write, Read};
|
||||
use byteorder::{ByteOrder, ReadBytesExt, BigEndian};
|
||||
use keychain::Identifier;
|
||||
use secp::pedersen::Commitment;
|
||||
use secp::pedersen::RangeProof;
|
||||
use secp::constants::PEDERSEN_COMMITMENT_SIZE;
|
||||
|
@ -285,6 +286,19 @@ impl Writeable for Commitment {
|
|||
}
|
||||
}
|
||||
|
||||
impl Writeable for Identifier {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_fixed_bytes(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Readable for Identifier {
|
||||
fn read(reader: &mut Reader) -> Result<Identifier, Error> {
|
||||
let bytes = reader.read_fixed_bytes(20)?;
|
||||
Ok(Identifier::from_bytes(&bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl Writeable for RangeProof {
|
||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_fixed_bytes(self)
|
||||
|
@ -511,3 +525,8 @@ impl AsFixedBytes for ::secp::pedersen::Commitment {
|
|||
return PEDERSEN_COMMITMENT_SIZE;
|
||||
}
|
||||
}
|
||||
impl AsFixedBytes for ::keychain::Identifier {
|
||||
fn len(&self) -> usize {
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ use chain;
|
|||
use secp;
|
||||
use pool;
|
||||
use util;
|
||||
use keychain::Keychain;
|
||||
use keychain::{Identifier, Keychain};
|
||||
use wallet::{BlockFees, WalletReceiveRequest, CbData};
|
||||
|
||||
use pow::plugin::PluginMiner;
|
||||
|
@ -431,13 +431,15 @@ impl Miner {
|
|||
// to prevent the wallet from generating a new HD key derivation for each
|
||||
// iteration, we keep the returned derivation to provide it back when
|
||||
// nothing has changed
|
||||
let mut derivation = 0;
|
||||
let mut pubkey = None;
|
||||
|
||||
loop {
|
||||
debug!("in miner loop...");
|
||||
|
||||
// get the latest chain state and build a block on top of it
|
||||
let head = self.chain.head_header().unwrap();
|
||||
let mut latest_hash = self.chain.head().unwrap().last_block_h;
|
||||
let (mut b, deriv) = self.build_block(&head, derivation);
|
||||
let (mut b, block_fees) = self.build_block(&head, pubkey);
|
||||
|
||||
let mut sol = None;
|
||||
let mut use_async = false;
|
||||
|
@ -500,16 +502,22 @@ impl Miner {
|
|||
e
|
||||
);
|
||||
}
|
||||
derivation = 0;
|
||||
debug!("resetting pubkey in miner to None");
|
||||
pubkey = None;
|
||||
} else {
|
||||
derivation = deriv;
|
||||
debug!("setting pubkey in miner to pubkey from block_fees - {:?}", block_fees);
|
||||
pubkey = block_fees.pubkey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a new block with the chain head as previous and eligible
|
||||
/// transactions from the pool.
|
||||
fn build_block(&self, head: &core::BlockHeader, deriv: u32) -> (core::Block, u32) {
|
||||
fn build_block(
|
||||
&self,
|
||||
head: &core::BlockHeader,
|
||||
pubkey: Option<Identifier>,
|
||||
) -> (core::Block, BlockFees) {
|
||||
// prepare the block header timestamp
|
||||
let mut now_sec = time::get_time().sec;
|
||||
let head_sec = head.timestamp.to_timespec().sec;
|
||||
|
@ -529,7 +537,12 @@ impl Miner {
|
|||
|
||||
// build the coinbase and the block itself
|
||||
let fees = txs.iter().map(|tx| tx.fee).sum();
|
||||
let (output, kernel, deriv) = self.get_coinbase(fees, deriv);
|
||||
let block_fees = BlockFees {
|
||||
fees: fees,
|
||||
pubkey: pubkey,
|
||||
};
|
||||
|
||||
let (output, kernel, block_fees) = self.get_coinbase(block_fees);
|
||||
let mut b = core::Block::with_reward(head, txs, output, kernel).unwrap();
|
||||
debug!(
|
||||
"(Server ID: {}) Built new block with {} inputs and {} outputs, difficulty: {}",
|
||||
|
@ -550,21 +563,28 @@ impl Miner {
|
|||
self.chain.set_sumtree_roots(&mut b).expect(
|
||||
"Error setting sum tree roots",
|
||||
);
|
||||
(b, deriv)
|
||||
(b, block_fees)
|
||||
}
|
||||
|
||||
fn get_coinbase(&self, fees: u64, derivation: u32) -> (core::Output, core::TxKernel, u32) {
|
||||
fn get_coinbase(
|
||||
&self,
|
||||
block_fees: BlockFees,
|
||||
) -> (core::Output, core::TxKernel, BlockFees) {
|
||||
if self.config.burn_reward {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let pubkey = keychain.derive_pubkey(1).unwrap();
|
||||
let (out, kern) = core::Block::reward_output(&keychain, pubkey, fees).unwrap();
|
||||
(out, kern, 0)
|
||||
let (out, kern) = core::Block::reward_output(
|
||||
&keychain,
|
||||
&pubkey,
|
||||
block_fees.fees
|
||||
).unwrap();
|
||||
(out, kern, block_fees)
|
||||
} else {
|
||||
let url = format!(
|
||||
"{}/v1/receive/coinbase",
|
||||
self.config.wallet_receiver_url.as_str()
|
||||
);
|
||||
let request = WalletReceiveRequest::Coinbase(BlockFees { fees: fees, derivation: derivation });
|
||||
let request = WalletReceiveRequest::Coinbase(block_fees.clone());
|
||||
let res: CbData = api::client::post(url.as_str(), &request).expect(
|
||||
format!(
|
||||
"(Server ID: {}) Wallet receiver unreachable, could not claim reward. Is it running?",
|
||||
|
@ -574,10 +594,18 @@ impl Miner {
|
|||
);
|
||||
let out_bin = util::from_hex(res.output).unwrap();
|
||||
let kern_bin = util::from_hex(res.kernel).unwrap();
|
||||
let pubkey_bin = util::from_hex(res.pubkey).unwrap();
|
||||
let output = ser::deserialize(&mut &out_bin[..]).unwrap();
|
||||
let kernel = ser::deserialize(&mut &kern_bin[..]).unwrap();
|
||||
let pubkey = ser::deserialize(&mut &pubkey_bin[..]).unwrap();
|
||||
let block_fees = BlockFees {
|
||||
pubkey: Some(pubkey),
|
||||
.. block_fees
|
||||
};
|
||||
|
||||
(output, kernel, res.derivation)
|
||||
debug!("block_fees here: {:?}", block_fees);
|
||||
|
||||
(output, kernel, block_fees)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@ version = "0.1.0"
|
|||
authors = ["Antioch Peverell"]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1"
|
||||
byteorder = "~1"
|
||||
blake2-rfc = "~0.2.17"
|
||||
rand = "~0.3"
|
||||
serde = "~1.0.8"
|
||||
serde_derive = "~1.0.8"
|
||||
serde_json = "~1.0.3"
|
||||
grin_util = { path = "../util" }
|
||||
secp256k1zkp = { git = "https://github.com/mimblewimble/rust-secp256k1-zkp" }
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
use std::{error, fmt};
|
||||
use std::cmp::min;
|
||||
|
||||
use serde::{de, ser};
|
||||
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use blake2::blake2b::blake2b;
|
||||
use secp::Secp256k1;
|
||||
|
@ -75,25 +77,83 @@ impl fmt::Display for Fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Identifier(String);
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Identifier([u8; 20]);
|
||||
|
||||
impl ser::Serialize for Identifier {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for Identifier {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Identifier, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_u64(IdentifierVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct IdentifierVisitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for IdentifierVisitor {
|
||||
type Value = Identifier;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("an identifier")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
// TODO - error handling here
|
||||
let identifier = Identifier::from_hex(s).unwrap();
|
||||
Ok(identifier)
|
||||
}
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
fn from_bytes(bytes: &[u8]) -> Identifier {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Identifier {
|
||||
let mut identifier = [0; 20];
|
||||
for i in 0..min(20, bytes.len()) {
|
||||
identifier[i] = bytes[i];
|
||||
}
|
||||
Identifier(util::to_hex(identifier.to_vec()))
|
||||
Identifier(identifier)
|
||||
}
|
||||
|
||||
fn from_hex(hex: &str) -> Result<Identifier, Error> {
|
||||
// TODO - error handling, don't unwrap here
|
||||
let bytes = util::from_hex(hex.to_string()).unwrap();
|
||||
Ok(Identifier::from_bytes(&bytes))
|
||||
}
|
||||
|
||||
pub fn to_hex(&self) -> String {
|
||||
self.0.clone()
|
||||
util::to_hex(self.0.to_vec())
|
||||
}
|
||||
|
||||
pub fn fingerprint(&self) -> Fingerprint {
|
||||
let hex = &self.0[0..8];
|
||||
Fingerprint(String::from(hex))
|
||||
Fingerprint::from_bytes(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Identifier {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for Identifier {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
try!(write!(f, "{}(", stringify!(Identifier)));
|
||||
for i in self.0.iter().cloned() {
|
||||
try!(write!(f, "{:02x}", i));
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,6 +268,8 @@ impl ExtendedKey {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use serde_json;
|
||||
|
||||
use secp::Secp256k1;
|
||||
use secp::key::SecretKey;
|
||||
use super::{ExtendedKey, Fingerprint, Identifier};
|
||||
|
@ -217,6 +279,29 @@ mod test {
|
|||
util::from_hex(hex_str.to_string()).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_identifier_json_ser_deser() {
|
||||
let hex = "942b6c0bd43bdcb24f3edfe7fadbc77054ecc4f2";
|
||||
let identifier = Identifier::from_hex(hex).unwrap();
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
struct HasAnIdentifier {
|
||||
identifier: Identifier,
|
||||
}
|
||||
|
||||
let has_an_identifier = HasAnIdentifier { identifier };
|
||||
|
||||
let json = serde_json::to_string(&has_an_identifier).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
json,
|
||||
"{\"identifier\":\"942b6c0bd43bdcb24f3edfe7fadbc77054ecc4f2\"}"
|
||||
);
|
||||
|
||||
let deserialized: HasAnIdentifier = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, has_an_identifier);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extkey_from_seed() {
|
||||
// TODO More test vectors
|
||||
|
|
|
@ -51,7 +51,7 @@ pub struct Keychain {
|
|||
}
|
||||
|
||||
impl Keychain {
|
||||
pub fn fingerprint(self) -> Fingerprint {
|
||||
pub fn fingerprint(&self) -> Fingerprint {
|
||||
self.extkey.fingerprint.clone()
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,19 @@ impl Keychain {
|
|||
return Ok(extkey.key);
|
||||
}
|
||||
}
|
||||
Err(Error::KeyDerivation("cannot find one...".to_string()))
|
||||
Err(Error::KeyDerivation(format!("cannot find extkey for {}", pubkey.fingerprint())))
|
||||
}
|
||||
|
||||
// TODO - clean this and derived_key up, rename them?
|
||||
// TODO - maybe wallet deals exclusively with pubkeys and not derivations - this leaks?
|
||||
pub fn derivation_from_pubkey(&self, pubkey: &Identifier) -> Result<u32, Error> {
|
||||
for i in 1..10000 {
|
||||
let extkey = self.extkey.derive(&self.secp, i)?;
|
||||
if extkey.identifier() == *pubkey {
|
||||
return Ok(extkey.n_child);
|
||||
}
|
||||
}
|
||||
Err(Error::KeyDerivation(format!("cannot find extkey for {}", pubkey.fingerprint())))
|
||||
}
|
||||
|
||||
pub fn commit(&self, amount: u64, pubkey: &Identifier) -> Result<Commitment, Error> {
|
||||
|
|
|
@ -22,6 +22,7 @@ extern crate grin_util as util;
|
|||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
|
||||
mod blind;
|
||||
mod extkey;
|
||||
|
|
|
@ -908,7 +908,7 @@ mod tests {
|
|||
&block::BlockHeader::default(),
|
||||
block_transactions,
|
||||
&keychain,
|
||||
pubkey,
|
||||
&pubkey,
|
||||
).unwrap();
|
||||
|
||||
chain_ref.apply_block(&block);
|
||||
|
@ -1007,7 +1007,7 @@ mod tests {
|
|||
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let pubkey = keychain.derive_pubkey(1).unwrap();
|
||||
block = block::Block::new(&block::BlockHeader::default(), tx_refs, &keychain, pubkey)
|
||||
block = block::Block::new(&block::BlockHeader::default(), tx_refs, &keychain, &pubkey)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -108,27 +108,35 @@ impl ApiEndpoint for WalletReceiver {
|
|||
match input {
|
||||
WalletReceiveRequest::Coinbase(cb_fees) => {
|
||||
debug!("Operation {} with fees {:?}", op, cb_fees);
|
||||
let (out, kern, derivation) =
|
||||
let (out, kern, block_fees) =
|
||||
receive_coinbase(
|
||||
&self.config,
|
||||
&self.keychain,
|
||||
cb_fees.fees,
|
||||
cb_fees.derivation,
|
||||
&cb_fees,
|
||||
).map_err(|e| {
|
||||
api::Error::Internal(format!("Error building coinbase: {:?}", e))
|
||||
})?;
|
||||
let out_bin =
|
||||
ser::ser_vec(&out).map_err(|e| {
|
||||
api::Error::Internal(format!("Error serializing output: {:?}", e))
|
||||
})?;
|
||||
api::Error::Internal(format!("Error serializing output: {:?}", e))
|
||||
})?;
|
||||
let kern_bin =
|
||||
ser::ser_vec(&kern).map_err(|e| {
|
||||
api::Error::Internal(format!("Error serializing kernel: {:?}", e))
|
||||
})?;
|
||||
let pubkey_bin = match block_fees.pubkey {
|
||||
Some(pubkey) => {
|
||||
ser::ser_vec(&pubkey).map_err(|e| {
|
||||
api::Error::Internal(format!("Error serializing kernel: {:?}", e))
|
||||
})?;
|
||||
})?
|
||||
},
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
Ok(CbData {
|
||||
output: util::to_hex(out_bin),
|
||||
kernel: util::to_hex(kern_bin),
|
||||
derivation: derivation,
|
||||
pubkey: util::to_hex(pubkey_bin),
|
||||
})
|
||||
}
|
||||
_ => Err(api::Error::Argument(
|
||||
|
@ -148,7 +156,7 @@ impl ApiEndpoint for WalletReceiver {
|
|||
Ok(CbData {
|
||||
output: String::from(""),
|
||||
kernel: String::from(""),
|
||||
derivation: 0,
|
||||
pubkey: String::from(""),
|
||||
})
|
||||
}
|
||||
_ => Err(api::Error::Argument(
|
||||
|
@ -165,33 +173,48 @@ impl ApiEndpoint for WalletReceiver {
|
|||
fn receive_coinbase(
|
||||
config: &WalletConfig,
|
||||
keychain: &Keychain,
|
||||
fees: u64,
|
||||
mut derivation: u32,
|
||||
) -> Result<(Output, TxKernel, u32), Error> {
|
||||
let fingerprint = keychain.clone().fingerprint();
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<(Output, TxKernel, BlockFees), Error> {
|
||||
let fingerprint = keychain.fingerprint();
|
||||
|
||||
// operate within a lock on wallet data
|
||||
WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
|
||||
if derivation == 0 {
|
||||
derivation = wallet_data.next_child(fingerprint.clone());
|
||||
}
|
||||
let pubkey = keychain.derive_pubkey(derivation)?;
|
||||
let pubkey = block_fees.pubkey();
|
||||
let (pubkey, derivation) = match pubkey {
|
||||
Some(pubkey) => {
|
||||
let derivation = keychain.derivation_from_pubkey(&pubkey)?;
|
||||
(pubkey.clone(), derivation)
|
||||
},
|
||||
None => {
|
||||
let derivation = wallet_data.next_child(fingerprint.clone());
|
||||
let pubkey = keychain.derive_pubkey(derivation)?;
|
||||
(pubkey, derivation)
|
||||
}
|
||||
};
|
||||
|
||||
// track the new output and return the stuff needed for reward
|
||||
wallet_data.add_output(OutputData {
|
||||
fingerprint: fingerprint.clone(),
|
||||
identifier: pubkey.clone(),
|
||||
n_child: derivation,
|
||||
value: reward(fees),
|
||||
value: reward(block_fees.fees),
|
||||
status: OutputStatus::Unconfirmed,
|
||||
height: 0,
|
||||
lock_height: 0,
|
||||
});
|
||||
debug!("Received coinbase and built output - {}, {}, {}",
|
||||
|
||||
debug!("Received coinbase and built candidate output - {}, {}, {}",
|
||||
fingerprint.clone(), pubkey.fingerprint(), derivation);
|
||||
|
||||
let (out, kern) = Block::reward_output(&keychain, pubkey, fees)?;
|
||||
Ok((out, kern, derivation))
|
||||
debug!("block_fees - {:?}", block_fees);
|
||||
|
||||
let mut block_fees = block_fees.clone();
|
||||
block_fees.pubkey = Some(pubkey.clone());
|
||||
|
||||
debug!("block_fees updated - {:?}", block_fees);
|
||||
|
||||
let (out, kern) = Block::reward_output(&keychain, &pubkey, block_fees.fees)?;
|
||||
Ok((out, kern, block_fees))
|
||||
})?
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ impl WalletData {
|
|||
Error::WalletData(format!("Could not create {}: {}", data_file_path, e))
|
||||
})?;
|
||||
let res_json = serde_json::to_vec_pretty(self).map_err(|e| {
|
||||
Error::WalletData(format!("Error serializing wallet data."))
|
||||
Error::WalletData(format!("Error serializing wallet data: {}", e))
|
||||
})?;
|
||||
data_file.write_all(res_json.as_slice()).map_err(|e| {
|
||||
Error::WalletData(format!("Error writing {}: {}", data_file_path, e))
|
||||
|
@ -385,7 +385,13 @@ pub enum WalletReceiveRequest {
|
|||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct BlockFees {
|
||||
pub fees: u64,
|
||||
pub derivation: u32,
|
||||
pub pubkey: Option<keychain::Identifier>,
|
||||
}
|
||||
|
||||
impl BlockFees {
|
||||
pub fn pubkey(&self) -> Option<keychain::Identifier> {
|
||||
self.pubkey.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Response to build a coinbase output.
|
||||
|
@ -393,5 +399,5 @@ pub struct BlockFees {
|
|||
pub struct CbData {
|
||||
pub output: String,
|
||||
pub kernel: String,
|
||||
pub derivation: u32,
|
||||
pub pubkey: String,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue