Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions api-server/scanner-lib/src/blockchain_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ async fn update_tables_from_block_reward<T: ApiServerStorageWrite>(
| TxOutput::DataDeposit(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::IssueNft(_, _, _) => {}
| TxOutput::IssueNft(_, _, _)
| TxOutput::Htlc(_, _) => {}
TxOutput::ProduceBlockFromStake(_, _) => {
set_utxo(
outpoint,
Expand Down Expand Up @@ -569,7 +570,8 @@ async fn calculate_fees<T: ApiServerStorageWrite>(
| TxOutput::DataDeposit(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::ProduceBlockFromStake(_, _) => None,
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::Htlc(_, _) => None,
})
})
.collect();
Expand Down Expand Up @@ -601,7 +603,8 @@ async fn calculate_fees<T: ApiServerStorageWrite>(
| TxOutput::DelegateStaking(_, _)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::ProduceBlockFromStake(_, _) => None,
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::Htlc(_, _) => None,
},
TxInput::Account(_) => None,
TxInput::AccountCommand(_, cmd) => match cmd {
Expand Down Expand Up @@ -726,7 +729,8 @@ async fn prefetch_pool_amounts<T: ApiServerStorageWrite>(
| TxOutput::CreateDelegationId(_, _)
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueNft(_, _, _)
| TxOutput::IssueFungibleToken(_),
| TxOutput::IssueFungibleToken(_)
| TxOutput::Htlc(_, _),
) => {}
None => {}
}
Expand Down Expand Up @@ -1103,7 +1107,8 @@ async fn update_tables_from_transaction_inputs<T: ApiServerStorageWrite>(
| TxOutput::DataDeposit(_)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_) => {}
| TxOutput::IssueFungibleToken(_)
| TxOutput::Htlc(_, _) => {}
TxOutput::CreateStakePool(pool_id, _)
| TxOutput::ProduceBlockFromStake(_, pool_id) => {
let pool_data = db_tx
Expand Down Expand Up @@ -1196,6 +1201,7 @@ async fn update_tables_from_transaction_inputs<T: ApiServerStorageWrite>(
)
.await;
}
TxOutput::Htlc(_, _) => {} // TODO(HTLC)
TxOutput::LockThenTransfer(output_value, destination, _)
| TxOutput::Transfer(output_value, destination) => {
let address = Address::<Destination>::new(&chain_config, destination)
Expand Down Expand Up @@ -1610,6 +1616,7 @@ async fn update_tables_from_transaction_outputs<T: ApiServerStorageWrite>(
.expect("Unable to set locked utxo");
}
}
TxOutput::Htlc(_, _) => {} // TODO(HTLC)
}
}

Expand Down Expand Up @@ -1809,5 +1816,6 @@ fn get_tx_output_destination(txo: &TxOutput) -> Option<&Destination> {
| TxOutput::Burn(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::DataDeposit(_) => None,
TxOutput::Htlc(_, _) => None, // TODO(HTLC)
}
}
14 changes: 9 additions & 5 deletions api-server/scanner-lib/src/sync/tests/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ async fn simulation(
let mut block_builder = tf.make_pos_block_builder().with_random_staking_pool(&mut rng);

for _ in 0..rng.gen_range(10..max_tx_per_block) {
block_builder = block_builder.add_test_transaction(&mut rng);
block_builder = block_builder.add_test_transaction(&mut rng, false);
}

let block = block_builder.build(&mut rng);
Expand All @@ -259,7 +259,8 @@ async fn simulation(
| TxOutput::CreateDelegationId(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::IssueNft(_, _, _) => None,
| TxOutput::IssueNft(_, _, _)
| TxOutput::Htlc(_, _) => None,
});
staking_pools.extend(new_pools);

Expand All @@ -277,7 +278,8 @@ async fn simulation(
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::IssueNft(_, _, _) => None,
| TxOutput::IssueNft(_, _, _)
| TxOutput::Htlc(_, _) => None,
});
delegations.extend(new_delegations);

Expand All @@ -292,7 +294,8 @@ async fn simulation(
| TxOutput::DataDeposit(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::ProduceBlockFromStake(_, _) => None,
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::Htlc(_, _) => None,
});
token_ids.extend(new_tokens);

Expand Down Expand Up @@ -335,7 +338,8 @@ async fn simulation(
| TxOutput::CreateDelegationId(_, _)
| TxOutput::Transfer(_, _)
| TxOutput::LockThenTransfer(_, _, _)
| TxOutput::ProduceBlockFromStake(_, _) => {}
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::Htlc(_, _) => {}
});

tx.inputs().iter().for_each(|inp| match inp {
Expand Down
12 changes: 12 additions & 0 deletions api-server/web-server/src/api/json_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ pub fn txoutput_to_json(
"destination": Address::new(chain_config, dest.clone()).expect("no error").as_str(),
})
}
TxOutput::Htlc(value, htlc) => {
json!({
"type": "Htlc",
"value": outputvalue_to_json(value, chain_config, token_decimals),
"htlc": {
"secret_hash": to_json_string(htlc.secret_hash.as_bytes()),
"spend_key": Address::new(chain_config, htlc.spend_key.clone()).expect("no error").as_str(),
"refund_timelock": htlc.refund_timelock,
"refund_key": Address::new(chain_config, htlc.refund_key.clone()).expect("no error").as_str(),
},
})
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ impl ConstrainedValueAccumulator {
StakerBalanceGetterFn: Fn(PoolId) -> Result<Option<Amount>, Error>,
{
match input_utxo {
TxOutput::Transfer(value, _) | TxOutput::LockThenTransfer(value, _, _) => {
TxOutput::Transfer(value, _)
| TxOutput::LockThenTransfer(value, _, _)
| TxOutput::Htlc(value, _) => {
match value {
OutputValue::Coin(amount) => insert_or_increase(
&mut self.unconstrained_value,
Expand Down Expand Up @@ -269,19 +271,21 @@ impl ConstrainedValueAccumulator {

for output in outputs {
match output {
TxOutput::Transfer(value, _) | TxOutput::Burn(value) => match value {
OutputValue::Coin(amount) => insert_or_increase(
&mut accumulator.unconstrained_value,
CoinOrTokenId::Coin,
*amount,
)?,
OutputValue::TokenV0(_) => { /* ignore */ }
OutputValue::TokenV1(token_id, amount) => insert_or_increase(
&mut accumulator.unconstrained_value,
CoinOrTokenId::TokenId(*token_id),
*amount,
)?,
},
TxOutput::Transfer(value, _) | TxOutput::Burn(value) | TxOutput::Htlc(value, _) => {
match value {
OutputValue::Coin(amount) => insert_or_increase(
&mut accumulator.unconstrained_value,
CoinOrTokenId::Coin,
*amount,
)?,
OutputValue::TokenV0(_) => { /* ignore */ }
OutputValue::TokenV1(token_id, amount) => insert_or_increase(
&mut accumulator.unconstrained_value,
CoinOrTokenId::TokenId(*token_id),
*amount,
)?,
}
}
TxOutput::DelegateStaking(coins, _) => insert_or_increase(
&mut accumulator.unconstrained_value,
CoinOrTokenId::Coin,
Expand Down
2 changes: 2 additions & 0 deletions chainstate/src/detail/ban_score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl BanScore for mintscript::translate::TranslationError {
| Self::DelegationNotFound(_)
| Self::TokenNotFound(_) => 100,

Self::SignatureError(_) => 100,
Self::PoSAccounting(e) => e.ban_score(),
Self::TokensAccounting(e) => e.ban_score(),
}
Expand Down Expand Up @@ -351,6 +352,7 @@ impl BanScore for CheckTransactionError {
CheckTransactionError::DataDepositMaxSizeExceeded(_, _, _) => 100,
CheckTransactionError::TxSizeTooLarge(_, _, _) => 100,
CheckTransactionError::DeprecatedTokenOperationVersion(_, _) => 100,
CheckTransactionError::HtlcsAreNotActivated => 100,
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion chainstate/src/detail/chainstateref/epoch_seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ where
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::IssueNft(_, _, _)
| TxOutput::DataDeposit(_) => {
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _) => {
return Err(EpochSealError::SpendStakeError(
SpendStakeError::InvalidBlockRewardOutputType,
));
Expand Down
6 changes: 4 additions & 2 deletions chainstate/src/detail/chainstateref/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,8 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::IssueNft(_, _, _)
| TxOutput::DataDeposit(_) => Err(
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _) => Err(
CheckBlockError::InvalidBlockRewardOutputType(block.get_id()),
),
},
Expand All @@ -713,7 +714,8 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::IssueNft(_, _, _)
| TxOutput::DataDeposit(_) => Err(
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _) => Err(
CheckBlockError::InvalidBlockRewardOutputType(block.get_id()),
),
}
Expand Down
6 changes: 3 additions & 3 deletions chainstate/src/detail/error_classification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ impl BlockProcessingErrorClassification for mintscript::translate::TranslationEr

Self::PoSAccounting(e) => e.classify(),
Self::TokensAccounting(e) => e.classify(),
Self::SignatureError(e) => e.classify(),
}
}
}
Expand Down Expand Up @@ -786,9 +787,8 @@ impl BlockProcessingErrorClassification for CheckTransactionError {
| CheckTransactionError::NoSignatureDataNotAllowed(_)
| CheckTransactionError::DataDepositMaxSizeExceeded(_, _, _)
| CheckTransactionError::TxSizeTooLarge(_, _, _)
| CheckTransactionError::DeprecatedTokenOperationVersion(_, _) => {
BlockProcessingErrorClass::BadBlock
}
| CheckTransactionError::DeprecatedTokenOperationVersion(_, _)
| CheckTransactionError::HtlcsAreNotActivated => BlockProcessingErrorClass::BadBlock,

CheckTransactionError::PropertyQueryError(err) => err.classify(),
CheckTransactionError::TokensError(err) => err.classify(),
Expand Down
3 changes: 2 additions & 1 deletion chainstate/src/detail/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@ impl<S: BlockchainStorage, V: TransactionVerificationStrategy> Chainstate<S, V>
| TxOutput::DelegateStaking(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::IssueNft(_, _, _)
| TxOutput::DataDeposit(_) => { /* do nothing */ }
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _) => { /* do nothing */ }
| TxOutput::CreateStakePool(pool_id, data) => {
let _ = db
.create_pool(*pool_id, data.as_ref().clone().into())
Expand Down
3 changes: 2 additions & 1 deletion chainstate/src/detail/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::DelegateStaking(_, _)
| TxOutput::DataDeposit(_) => None,
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _) => None,
TxOutput::IssueNft(_, issuance, _) => match issuance.as_ref() {
NftIssuance::V0(nft) => {
Some(RPCTokenInfo::new_nonfungible(RPCNonFungibleTokenInfo::new(
Expand Down
7 changes: 4 additions & 3 deletions chainstate/src/interface/chainstate_interface_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,10 @@ fn get_output_coin_amount(
output: &TxOutput,
) -> Result<Option<Amount>, ChainstateError> {
let amount = match output {
TxOutput::Transfer(v, _) | TxOutput::LockThenTransfer(v, _, _) | TxOutput::Burn(v) => {
v.coin_amount()
}
TxOutput::Transfer(v, _)
| TxOutput::LockThenTransfer(v, _, _)
| TxOutput::Burn(v)
| TxOutput::Htlc(v, _) => v.coin_amount(),
TxOutput::CreateStakePool(_, data) => Some(data.pledge()),
TxOutput::ProduceBlockFromStake(_, pool_id) => {
let pledge_amount = pos_accounting_view
Expand Down
36 changes: 34 additions & 2 deletions chainstate/src/rpc/types/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
use common::{
address::{AddressError, RpcAddress},
chain::{
output_value::OutputValue, stakelock::StakePoolData, timelock::OutputTimeLock,
tokens::TokenId, ChainConfig, DelegationId, Destination, PoolId, TxOutput,
htlc::HashedTimelockContract, output_value::OutputValue, stakelock::StakePoolData,
timelock::OutputTimeLock, tokens::TokenId, ChainConfig, DelegationId, Destination, PoolId,
TxOutput,
},
primitives::amount::RpcAmountOut,
};
Expand Down Expand Up @@ -81,6 +82,29 @@ impl RpcStakePoolData {
}
}

#[derive(Debug, Clone, serde::Serialize, rpc_description::HasValueHint)]
pub struct RpcHashedTimelockContract {
secret_hash: RpcHexString,
spend_key: RpcAddress<Destination>,
refund_timelock: OutputTimeLock,
refund_key: RpcAddress<Destination>,
}

impl RpcHashedTimelockContract {
fn new(
chain_config: &ChainConfig,
htlc: &HashedTimelockContract,
) -> Result<Self, AddressError> {
let result = Self {
secret_hash: RpcHexString::from_bytes(htlc.secret_hash.as_bytes().to_owned()),
spend_key: RpcAddress::new(chain_config, htlc.spend_key.clone())?,
refund_timelock: htlc.refund_timelock,
refund_key: RpcAddress::new(chain_config, htlc.refund_key.clone())?,
};
Ok(result)
}
}

#[derive(Debug, Clone, serde::Serialize, rpc_description::HasValueHint)]
#[serde(tag = "type", content = "content")]
pub enum RpcTxOutput {
Expand Down Expand Up @@ -123,6 +147,10 @@ pub enum RpcTxOutput {
DataDeposit {
data: RpcHexString,
},
Htlc {
value: RpcOutputValue,
htlc: RpcHashedTimelockContract,
},
}

impl RpcTxOutput {
Expand All @@ -139,6 +167,10 @@ impl RpcTxOutput {
timelock,
}
}
TxOutput::Htlc(value, htlc) => RpcTxOutput::Htlc {
value: RpcOutputValue::new(chain_config, value)?,
htlc: RpcHashedTimelockContract::new(chain_config, &htlc)?,
},
TxOutput::Burn(value) => RpcTxOutput::Burn {
value: RpcOutputValue::new(chain_config, value)?,
},
Expand Down
7 changes: 6 additions & 1 deletion chainstate/test-framework/src/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ impl<'f> BlockBuilder<'f> {
}

/// Adds a transaction that uses random utxos and accounts
pub fn add_test_transaction(mut self, rng: &mut (impl Rng + CryptoRng)) -> Self {
pub fn add_test_transaction(
mut self,
rng: &mut (impl Rng + CryptoRng),
support_htlc: bool,
) -> Self {
let utxo_set = self
.framework
.storage
Expand Down Expand Up @@ -148,6 +152,7 @@ impl<'f> BlockBuilder<'f> {
&self.pos_accounting_store,
None,
account_nonce_getter,
support_htlc,
)
.make(
rng,
Expand Down
Loading