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
1 change: 0 additions & 1 deletion crates/sage-api/src/records/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ use specta::Type;
pub struct PeerRecord {
pub ip_addr: String,
pub port: u16,
pub trusted: bool,
pub peak_height: u32,
}
3 changes: 2 additions & 1 deletion crates/sage-api/src/records/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use specta::Type;

use crate::{Amount, AssetKind};
use crate::{AddressKind, Amount, AssetKind};

#[derive(Debug, Clone, Serialize, Deserialize, Type)]
pub struct TransactionRecord {
Expand All @@ -15,6 +15,7 @@ pub struct TransactionCoin {
pub coin_id: String,
pub amount: Amount,
pub address: Option<String>,
pub address_kind: AddressKind,
#[serde(flatten)]
pub kind: AssetKind,
}
10 changes: 10 additions & 0 deletions crates/sage-api/src/requests/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ pub struct GetTransactionsResponse {
pub total: u32,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type)]
pub struct GetTransaction {
pub height: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize, Type)]
pub struct GetTransactionResponse {
pub transaction: TransactionRecord,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type)]
pub struct GetNftStatus {}

Expand Down
1 change: 0 additions & 1 deletion crates/sage-api/src/requests/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pub struct RemovePeerResponse {}
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
pub struct AddPeer {
pub ip: String,
pub trusted: bool,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type)]
Expand Down
2 changes: 2 additions & 0 deletions crates/sage-api/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod address_kind;
mod amount;
mod asset_kind;
mod error_kind;
mod key_info;
mod unit;

pub use address_kind::*;
pub use amount::*;
pub use asset_kind::*;
pub use error_kind::*;
Expand Down
13 changes: 13 additions & 0 deletions crates/sage-api/src/types/address_kind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
use specta::Type;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type)]
#[serde(rename_all = "snake_case")]
pub enum AddressKind {
Own,
Burn,
Launcher,
Offer,
External,
Unknown,
}
1 change: 1 addition & 0 deletions crates/sage-cli/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ routes!(
get_dids await: GetDids = "/get_dids",
get_pending_transactions await: GetPendingTransactions = "/get_pending_transactions",
get_transactions await: GetTransactions = "/get_transactions",
get_transaction await: GetTransaction = "/get_transaction",
get_nft_status await: GetNftStatus = "/get_nft_status",
get_nft_collections await: GetNftCollections = "/get_nft_collections",
get_nft_collection await: GetNftCollection = "/get_nft_collection",
Expand Down
6 changes: 1 addition & 5 deletions crates/sage-wallet/src/sync_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,7 @@ impl SyncManager {
);
}
}
SyncCommand::ConnectPeer { ip, trusted } => {
if trusted {
self.state.lock().await.trust(ip);
}

SyncCommand::ConnectPeer { ip } => {
self.connect_batch(&[SocketAddr::new(ip, self.network.default_port)], true)
.await;
}
Expand Down
7 changes: 1 addition & 6 deletions crates/sage-wallet/src/sync_manager/peer_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,7 @@ impl SyncManager {
} else if force && state.peer_count() >= self.options.target_peers {
let mut peers = state.peers_with_heights();

peers.sort_by_key(|(peer, height)| {
(
!state.trusted_peers().contains(&peer.socket_addr().ip()),
*height,
)
});
peers.sort_by_key(|(_peer, height)| *height);

let count = state.peer_count() - self.options.target_peers + 1;

Expand Down
17 changes: 1 addition & 16 deletions crates/sage-wallet/src/sync_manager/peer_state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
collections::{HashMap, HashSet},
collections::HashMap,
net::IpAddr,
time::{Duration, SystemTime, UNIX_EPOCH},
};
Expand Down Expand Up @@ -29,14 +29,12 @@ impl Drop for PeerInfo {
pub struct PeerState {
peers: HashMap<IpAddr, PeerInfo>,
banned_peers: HashMap<IpAddr, u64>,
trusted_peers: HashSet<IpAddr>,
}

impl PeerState {
pub fn reset(&mut self) {
self.peers.clear();
self.banned_peers.clear();
self.trusted_peers.clear();
}

pub fn peak(&self) -> Option<(u32, Bytes32)> {
Expand Down Expand Up @@ -80,10 +78,6 @@ impl PeerState {
}

pub fn ban(&mut self, ip: IpAddr, duration: Duration, message: &str) {
if self.trusted_peers.contains(&ip) {
return;
}

debug!("Banning peer {ip} ({duration:?}): {message}");

let start = SystemTime::now();
Expand Down Expand Up @@ -111,11 +105,6 @@ impl PeerState {
})
}

pub fn trust(&mut self, ip: IpAddr) {
self.trusted_peers.insert(ip);
self.banned_peers.remove(&ip);
}

pub fn update_peak(&mut self, ip: IpAddr, height: u32, header_hash: Bytes32) {
if let Some(peer) = self.peers.get_mut(&ip) {
peer.claimed_peak = height;
Expand All @@ -135,10 +124,6 @@ impl PeerState {
self.peers.insert(state.peer.socket_addr().ip(), state);
}

pub fn trusted_peers(&self) -> &HashSet<IpAddr> {
&self.trusted_peers
}

pub fn banned_peers(&mut self) -> &HashMap<IpAddr, u64> {
self.banned_peers.retain(|_, ban_until| {
let start = SystemTime::now();
Expand Down
1 change: 0 additions & 1 deletion crates/sage-wallet/src/sync_manager/sync_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pub enum SyncCommand {
},
ConnectPeer {
ip: IpAddr,
trusted: bool,
},
SubscribeCoins {
coin_ids: Vec<Bytes32>,
Expand Down
8 changes: 8 additions & 0 deletions crates/sage-wallet/src/wallet/nfts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,14 @@ mod tests {
test.wait_for_coins().await;
}

let nft = test
.wallet
.db
.nft_row(nft.info.launcher_id)
.await?
.expect("missing nft");
assert_eq!(nft.owner_did, Some(did.info.launcher_id));

Ok(())
}
}
91 changes: 64 additions & 27 deletions crates/sage/src/endpoints/data.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
use base64::{prelude::BASE64_STANDARD, Engine};
use chia::{
clvm_traits::{FromClvm, ToClvm},
protocol::Program,
puzzles::nft::NftMetadata,
protocol::{Bytes32, Program},
puzzles::{
nft::NftMetadata, offer::SETTLEMENT_PAYMENTS_PUZZLE_HASH,
singleton::SINGLETON_LAUNCHER_PUZZLE_HASH,
},
};
use chia_wallet_sdk::{encode_address, Nft};
use clvmr::Allocator;
use hex_literal::hex;
use sage_api::{
Amount, AssetKind, CatRecord, CoinRecord, DerivationRecord, DidRecord, GetCat, GetCatCoins,
GetCatCoinsResponse, GetCatResponse, GetCats, GetCatsResponse, GetDerivations,
AddressKind, Amount, AssetKind, CatRecord, CoinRecord, DerivationRecord, DidRecord, GetCat,
GetCatCoins, GetCatCoinsResponse, GetCatResponse, GetCats, GetCatsResponse, GetDerivations,
GetDerivationsResponse, GetDids, GetDidsResponse, GetNft, GetNftCollection,
GetNftCollectionResponse, GetNftCollections, GetNftCollectionsResponse, GetNftData,
GetNftDataResponse, GetNftResponse, GetNftStatus, GetNftStatusResponse, GetNfts,
GetNftsResponse, GetPendingTransactions, GetPendingTransactionsResponse, GetSyncStatus,
GetSyncStatusResponse, GetTransactions, GetTransactionsResponse, GetXchCoins,
GetXchCoinsResponse, NftCollectionRecord, NftData, NftRecord, NftSortMode,
PendingTransactionRecord, TransactionCoin, TransactionRecord,
GetSyncStatusResponse, GetTransaction, GetTransactionResponse, GetTransactions,
GetTransactionsResponse, GetXchCoins, GetXchCoinsResponse, NftCollectionRecord, NftData,
NftRecord, NftSortMode, PendingTransactionRecord, TransactionCoin, TransactionRecord,
};
use sage_database::{CoinKind, CoinStateRow, Database, NftRow};
use sage_wallet::WalletError;

use crate::{parse_asset_id, parse_collection_id, parse_nft_id, Result, Sage};
use crate::{parse_asset_id, parse_collection_id, parse_nft_id, Result, Sage, BURN_PUZZLE_HASH};

impl Sage {
pub async fn get_sync_status(&self, _req: GetSyncStatus) -> Result<GetSyncStatusResponse> {
Expand Down Expand Up @@ -271,25 +274,8 @@ impl Sage {
.skip(req.offset.try_into()?)
.take(req.limit.try_into()?)
{
let spent_rows = wallet.db.get_coin_states_by_spent_height(height).await?;
let created_rows = wallet.db.get_coin_states_by_created_height(height).await?;

let mut spent = Vec::new();
let mut created = Vec::new();

for row in spent_rows {
spent.push(self.transaction_coin(&wallet.db, row).await?);
}

for row in created_rows {
created.push(self.transaction_coin(&wallet.db, row).await?);
}

transactions.push(TransactionRecord {
height,
spent,
created,
});
let transaction = self.transaction_record(&wallet.db, height).await?;
transactions.push(transaction);
}

Ok(GetTransactionsResponse {
Expand All @@ -298,6 +284,12 @@ impl Sage {
})
}

pub async fn get_transaction(&self, req: GetTransaction) -> Result<GetTransactionResponse> {
let wallet = self.wallet()?;
let transaction = self.transaction_record(&wallet.db, req.height).await?;
Ok(GetTransactionResponse { transaction })
}

pub async fn get_nft_status(&self, _req: GetNftStatus) -> Result<GetNftStatusResponse> {
let wallet = self.wallet()?;

Expand Down Expand Up @@ -734,15 +726,60 @@ impl Sage {
}
};

let address_kind = if let Some(p2_puzzle_hash) = p2_puzzle_hash {
self.address_kind(db, p2_puzzle_hash).await?
} else {
AddressKind::Unknown
};

Ok(TransactionCoin {
coin_id: hex::encode(coin_id),
address: p2_puzzle_hash
.map(|p2_puzzle_hash| {
encode_address(p2_puzzle_hash.to_bytes(), &self.network().address_prefix)
})
.transpose()?,
address_kind,
amount: Amount::u64(coin.coin_state.coin.amount),
kind,
})
}

async fn transaction_record(&self, db: &Database, height: u32) -> Result<TransactionRecord> {
let spent_rows = db.get_coin_states_by_spent_height(height).await?;
let created_rows = db.get_coin_states_by_created_height(height).await?;

let mut spent = Vec::new();
let mut created = Vec::new();

for row in spent_rows {
spent.push(self.transaction_coin(db, row).await?);
}

for row in created_rows {
created.push(self.transaction_coin(db, row).await?);
}

Ok(TransactionRecord {
height,
spent,
created,
})
}

async fn address_kind(&self, db: &Database, p2_puzzle_hash: Bytes32) -> Result<AddressKind> {
if p2_puzzle_hash == BURN_PUZZLE_HASH.into() {
return Ok(AddressKind::Burn);
} else if p2_puzzle_hash == SINGLETON_LAUNCHER_PUZZLE_HASH.into() {
return Ok(AddressKind::Launcher);
} else if p2_puzzle_hash == SETTLEMENT_PAYMENTS_PUZZLE_HASH.into() {
return Ok(AddressKind::Offer);
}

Ok(if db.is_p2_puzzle_hash(p2_puzzle_hash).await? {
AddressKind::Own
} else {
AddressKind::External
})
}
}
2 changes: 0 additions & 2 deletions crates/sage/src/endpoints/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ impl Sage {
.map(|info| PeerRecord {
ip_addr: info.0.socket_addr().ip().to_string(),
port: info.0.socket_addr().port(),
trusted: false,
peak_height: info.1,
})
.collect(),
Expand All @@ -49,7 +48,6 @@ impl Sage {
self.command_sender
.send(SyncCommand::ConnectPeer {
ip: req.ip.parse()?,
trusted: req.trusted,
})
.await?;

Expand Down
1 change: 1 addition & 0 deletions crates/sage/src/peers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Peers {
pub connections: HashSet<IpAddr>,
// TODO: Remove this in a backwards compatible way
pub trusted: HashSet<IpAddr>,
pub banned: HashMap<IpAddr, u64>,
}
Expand Down
9 changes: 1 addition & 8 deletions crates/sage/src/sage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,7 @@ impl Sage {
}

self.command_sender
.send(SyncCommand::ConnectPeer {
ip,
trusted: peers.trusted.contains(&ip),
})
.send(SyncCommand::ConnectPeer { ip })
.await?;
}

Expand All @@ -321,10 +318,6 @@ impl Sage {
peers.banned.insert(ip, ban);
}

for &ip in state.trusted_peers() {
peers.trusted.insert(ip);
}

let peer_path = peer_dir.join(format!("{}.bin", self.config.network.network_id));
fs::write(&peer_path, peers.to_bytes()?)?;

Expand Down
4 changes: 4 additions & 0 deletions crates/sage/src/utils/coins.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use chia::protocol::{Bytes32, Coin};
use chia_wallet_sdk::Cat;
use hex_literal::hex;
use sage_wallet::Wallet;

use crate::{Error, Result};

use super::parse_coin_id;

pub const BURN_PUZZLE_HASH: [u8; 32] =
hex!("000000000000000000000000000000000000000000000000000000000000dead");

pub async fn fetch_coins(wallet: &Wallet, coin_ids: Vec<String>) -> Result<Vec<Coin>> {
let coin_ids = coin_ids
.into_iter()
Expand Down
Loading
Loading