updates.set_utxo(&UTXO {
outpoint: OutPoint::new(tx.txid(), i as u32),
txout: output.clone(),
- is_internal: script_type.is_internal(),
+ script_type,
})?;
incoming += output.value;
updates.set_utxo(&UTXO {
outpoint: OutPoint::new(tx.txid(), i as u32),
txout: output.clone(),
- is_internal: script_type.is_internal(),
+ script_type,
})?;
incoming += output.value;
let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
let value = json!({
"t": utxo.txout,
- "i": utxo.is_internal,
+ "i": utxo.script_type,
});
self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
Some(b) => {
let mut val: serde_json::Value = serde_json::from_slice(&b)?;
let txout = serde_json::from_value(val["t"].take())?;
- let is_internal = serde_json::from_value(val["i"].take())?;
+ let script_type = serde_json::from_value(val["i"].take())?;
- Ok(Some(UTXO { outpoint: outpoint.clone(), txout, is_internal }))
+ Ok(Some(UTXO { outpoint: outpoint.clone(), txout, script_type }))
}
}
}
let mut val: serde_json::Value = serde_json::from_slice(&v)?;
let txout = serde_json::from_value(val["t"].take())?;
- let is_internal = serde_json::from_value(val["i"].take())?;
+ let script_type = serde_json::from_value(val["i"].take())?;
Ok(UTXO {
outpoint,
txout,
- is_internal,
+ script_type,
})
})
.collect()
.map(|b| -> Result<_, Error> {
let mut val: serde_json::Value = serde_json::from_slice(&b)?;
let txout = serde_json::from_value(val["t"].take())?;
- let is_internal = serde_json::from_value(val["i"].take())?;
+ let script_type = serde_json::from_value(val["i"].take())?;
Ok(UTXO {
outpoint: *outpoint,
txout,
- is_internal,
+ script_type,
})
})
.transpose()
fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
self.map
- .insert(key, Box::new((utxo.txout.clone(), utxo.is_internal)));
+ .insert(key, Box::new((utxo.txout.clone(), utxo.script_type)));
Ok(())
}
match res {
None => Ok(None),
Some(b) => {
- let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+ let (txout, script_type) = b.downcast_ref().cloned().unwrap();
Ok(Some(UTXO {
outpoint: *outpoint,
txout,
- is_internal,
+ script_type,
}))
}
}
.range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
.map(|(k, v)| {
let outpoint = deserialize(&k[1..]).unwrap();
- let (txout, is_internal) = v.downcast_ref().cloned().unwrap();
+ let (txout, script_type) = v.downcast_ref().cloned().unwrap();
Ok(UTXO {
outpoint,
txout,
- is_internal,
+ script_type,
})
})
.collect()
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
let key = MapKey::UTXO(Some(outpoint)).as_map_key();
Ok(self.map.get(&key).map(|b| {
- let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+ let (txout, script_type) = b.downcast_ref().cloned().unwrap();
UTXO {
outpoint: *outpoint,
txout,
- is_internal,
+ script_type,
}
}))
}
txid,
vout: vout as u32,
},
- is_internal: false,
+ script_type: ScriptType::External,
})
.unwrap();
}
let utxo = UTXO {
txout,
outpoint,
- is_internal: false,
+ script_type: ScriptType::External,
};
tree.set_utxo(&utxo).unwrap();
ScriptType::Internal => b'i',
}
}
-
- pub fn is_internal(&self) -> bool {
- self == &ScriptType::Internal
- }
}
impl AsRef<[u8]> for ScriptType {
pub struct UTXO {
pub outpoint: OutPoint,
pub txout: TxOut,
- pub is_internal: bool,
+ pub script_type: ScriptType,
}
/// A wallet transaction
value: 100_000,
script_pubkey: Script::new(),
},
- is_internal: false,
+ script_type: ScriptType::External,
},
P2WPKH_WITNESS_SIZE,
),
value: 200_000,
script_pubkey: Script::new(),
},
- is_internal: true,
+ script_type: ScriptType::Internal,
},
P2WPKH_WITNESS_SIZE,
),
value: rng.gen_range(0, 200000000),
script_pubkey: Script::new(),
},
- is_internal: false,
+ script_type: ScriptType::External,
},
P2WPKH_WITNESS_SIZE,
));
value: utxos_value,
script_pubkey: Script::new(),
},
- is_internal: false,
+ script_type: ScriptType::External,
},
P2WPKH_WITNESS_SIZE,
);
}
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
-
- let external_weight = self
- .get_descriptor_for_script_type(ScriptType::External)
- .0
- .max_satisfaction_weight(deriv_ctx)
- .unwrap();
- let internal_weight = self
- .get_descriptor_for_script_type(ScriptType::Internal)
- .0
- .max_satisfaction_weight(deriv_ctx)
- .unwrap();
-
let original_sequence = tx.input[0].sequence;
// remove the inputs from the tx and process them
.get_previous_output(&txin.previous_output)?
.ok_or(Error::UnknownUTXO)?;
- let (weight, is_internal) = match self
+ let (weight, script_type) = match self
.database
.borrow()
.get_path_from_script_pubkey(&txout.script_pubkey)?
{
- Some((ScriptType::Internal, _)) => (internal_weight, true),
- Some((ScriptType::External, _)) => (external_weight, false),
+ Some((script_type, _)) => (
+ self.get_descriptor_for_script_type(script_type)
+ .0
+ .max_satisfaction_weight(deriv_ctx)
+ .unwrap(),
+ script_type,
+ ),
None => {
// estimate the weight based on the scriptsig/witness size present in the
// original transaction
let weight =
serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
- (weight, false)
+ (weight, ScriptType::External)
}
};
let utxo = UTXO {
outpoint: txin.previous_output,
txout,
- is_internal,
+ script_type,
};
Ok((utxo, weight))
fn get_available_utxos(&self) -> Result<Vec<(UTXO, usize)>, Error> {
let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
-
- let external_weight = self
- .get_descriptor_for_script_type(ScriptType::External)
- .0
- .max_satisfaction_weight(deriv_ctx)
- .unwrap();
- let internal_weight = self
- .get_descriptor_for_script_type(ScriptType::Internal)
- .0
- .max_satisfaction_weight(deriv_ctx)
- .unwrap();
-
- let add_weight = |utxo: UTXO| {
- let weight = match utxo.is_internal {
- true => internal_weight,
- false => external_weight,
- };
-
- (utxo, weight)
- };
-
- let utxos = self.list_unspent()?.into_iter().map(add_weight).collect();
-
- Ok(utxos)
+ Ok(self
+ .list_unspent()?
+ .into_iter()
+ .map(|utxo| {
+ let script_type = utxo.script_type;
+ (
+ utxo,
+ self.get_descriptor_for_script_type(script_type)
+ .0
+ .max_satisfaction_weight(deriv_ctx)
+ .unwrap(),
+ )
+ })
+ .collect())
}
/// Given the options returns the list of utxos that must be used to form the
pub(crate) fn is_satisfied_by(&self, utxo: &UTXO) -> bool {
match self {
ChangeSpendPolicy::ChangeAllowed => true,
- ChangeSpendPolicy::OnlyChange => utxo.is_internal,
- ChangeSpendPolicy::ChangeForbidden => !utxo.is_internal,
+ ChangeSpendPolicy::OnlyChange => utxo.script_type == ScriptType::Internal,
+ ChangeSpendPolicy::ChangeForbidden => utxo.script_type == ScriptType::External,
}
}
}
vout: 0,
},
txout: Default::default(),
- is_internal: false,
+ script_type: ScriptType::External,
},
UTXO {
outpoint: OutPoint {
vout: 1,
},
txout: Default::default(),
- is_internal: true,
+ script_type: ScriptType::Internal,
},
]
}
.collect::<Vec<_>>();
assert_eq!(filtered.len(), 1);
- assert_eq!(filtered[0].is_internal, false);
+ assert_eq!(filtered[0].script_type, ScriptType::External);
}
#[test]
.collect::<Vec<_>>();
assert_eq!(filtered.len(), 1);
- assert_eq!(filtered[0].is_internal, true);
+ assert_eq!(filtered[0].script_type, ScriptType::Internal);
}
#[test]
wallet.sync(noop_progress(), None).unwrap();
assert_eq!(wallet.get_balance().unwrap(), 50_000);
- assert_eq!(wallet.list_unspent().unwrap()[0].is_internal, false);
+ assert_eq!(wallet.list_unspent().unwrap()[0].script_type, ScriptType::External);
let list_tx_item = &wallet.list_transactions(false).unwrap()[0];
assert_eq!(list_tx_item.txid, txid);