hash (features|commitment) in output mmr (#615)

* experiment with lock_heights on outputs

* playing around with lock_height as part of the switch commitment hash

* cleanup

* include features in the switch commit hash key

* commit

* rebase off master

* commit

* cleanup

* missing docs

* rework coinbase maturity test to build valid tx

* pool and chain tests passing (inputs have switch commitments)

* commit

* cleanup

* check inputs spending coinbase outputs have valid lock_heights

* wip - got it building (tests still failing)

* use zero key for non coinbase switch commit hash

* fees and height wrong order...

* send output lock_height over to wallet via api

* no more header by height index
workaround this for wallet refresh and wallet restore

* refresh heights for unspent wallet outputs where missing

* TODO - might be slow?

* simplify - do not pass around lock_height for non coinbase outputs

* commit

* fix tests after merge

* build input vs coinbase_input
switch commit hash key encodes lock_height
cleanup output by commit index (currently broken...)

* is_unspent and get_unspent cleanup - we have no outputs, only switch_commit_hashes

* separate concept of utxo vs output in the api
utxos come from the sumtrees (and only the sumtrees, limited info)
outputs come from blocks (and we need to look them up via block height)

* cleanup

* better api support for block outputs with range proofs

* basic wallet operations appear to work
restore is not working fully
refresh refreshes heights correctly (at least appears to)

* wallet refresh and wallet restore appear to be working now

* fix core tests

* fix some mine_simple_chain tests

* fixup chain tests

* rework so pool tests pass

* wallet restore now safely habndles duplicate commitments (reused wallet keys)
for coinbase outputs where lock_height is _very_ important

* wip

* validate_coinbase_maturity
got things building
tests are failing

* lite vs full versions of is_unspent

* builds and working locally
zero-conf - what to do here?

* handle zero-conf edge case (use latest block)

* introduce OutputIdentifier, avoid leaking SumCommit everywhere

* fix the bad merge

* pool verifies coinbase maturity via is_matured
this uses sumtree in a consistent way

* cleanup

* add docs, cleanup build warnings

* fix core tests

* fix chain tests

* fix pool tests

* cleanup debug logging that we no longer need

* make out_block optional on an input (only care about it for spending coinbase outputs)

* cleanup

* bump the build
This commit is contained in:
AntiochP
2018-01-16 22:03:40 -05:00
committed by GitHub
parent 7e7c8e157e
commit cbd3b2ff87
31 changed files with 1345 additions and 901 deletions
+18 -20
View File
@@ -25,9 +25,8 @@ use util::secp::pedersen::Commitment;
pub use graph;
use core::consensus;
use core::core::block;
use core::core::transaction;
use core::core::hash;
use core::core::{block, hash, transaction};
use core::core::transaction::{Input, OutputIdentifier};
/// Tranasction pool configuration
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -78,7 +77,7 @@ pub struct TxSource {
#[derive(Clone)]
pub enum Parent {
Unknown,
BlockTransaction { output: transaction::Output },
BlockTransaction,
PoolTransaction { tx_ref: hash::Hash },
AlreadySpent { other_tx: hash::Hash },
}
@@ -87,11 +86,15 @@ impl fmt::Debug for Parent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Parent::Unknown => write!(f, "Parent: Unknown"),
&Parent::BlockTransaction { output: _ } => write!(f, "Parent: Block Transaction"),
&Parent::BlockTransaction => {
write!(f, "Parent: Block Transaction")
}
&Parent::PoolTransaction { tx_ref: x } => {
write!(f, "Parent: Pool Transaction ({:?})", x)
}
&Parent::AlreadySpent { other_tx: x } => write!(f, "Parent: Already Spent By {:?}", x),
&Parent::AlreadySpent { other_tx: x } => {
write!(f, "Parent: Already Spent By {:?}", x)
}
}
}
}
@@ -122,12 +125,7 @@ pub enum PoolError {
},
/// Attempt to spend an output before it matures
/// lock_height must not exceed current block height
ImmatureCoinbase {
/// The block header of the block containing the output
header: block::BlockHeader,
/// The unspent output
output: Commitment,
},
ImmatureCoinbase,
/// Attempt to add a transaction to the pool with lock_height
/// greater than height of current block
ImmatureTransaction {
@@ -151,18 +149,18 @@ pub enum PoolError {
/// Interface that the pool requires from a blockchain implementation.
pub trait BlockChain {
/// Get an unspent output by its commitment. Will return None if the output
/// Get an unspent output by its commitment. Will return an error if the output
/// is spent or if it doesn't exist. The blockchain is expected to produce
/// a result with its current view of the most worked chain, ignoring
/// orphans, etc.
fn get_unspent(&self, output_ref: &Commitment) -> Result<transaction::Output, PoolError>;
/// We do not maintain outputs themselves. The only information we have is the
/// hash from the output MMR.
fn is_unspent(&self, output_ref: &OutputIdentifier) -> Result<(), PoolError>;
/// Get the block header by output commitment (needed for spending coinbase
/// after n blocks)
fn get_block_header_by_output_commit(
&self,
commit: &Commitment,
) -> Result<block::BlockHeader, PoolError>;
/// Check if an output being spent by the input has sufficiently matured.
/// This is only applicable for coinbase outputs (1,000 blocks).
/// Non-coinbase outputs will always pass this check.
fn is_matured(&self, input: &Input, height: u64) -> Result<(), PoolError>;
/// Get the block header at the head
fn head_header(&self) -> Result<block::BlockHeader, PoolError>;