Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
bca0d65
Prep for lit-peer
GTC6244 Nov 20, 2025
0d9e8bf
deployconfig for naga test
Garandor Nov 20, 2025
41460aa
WIP adding a second keyset
GTC6244 Nov 21, 2025
f05df13
Merge branch 'master' into keysets
GTC6244 Nov 25, 2025
f4c506d
Merge branch 'master' into keysets
GTC6244 Nov 26, 2025
f651236
prettier
GTC6244 Dec 3, 2025
cedb94b
Clippy!
GTC6244 Dec 3, 2025
c2e50fd
fix node_restarts_without_key_material - and maybe an FSM update?
GTC6244 Dec 3, 2025
5bd06cf
remove keyset test ( next branch )
GTC6244 Dec 3, 2025
6dce84d
Better handling of shadow splicing. (#26)
GTC6244 Dec 4, 2025
105a9ec
Quick ordering update for shadowOpts struct.
GTC6244 Dec 4, 2025
e41f197
Merge branch 'master' into keysets
GTC6244 Dec 4, 2025
4c489cf
abi staleness update
GTC6244 Dec 5, 2025
a793783
Merge branch 'master' into keysets
GTC6244 Dec 9, 2025
e16f278
blockchain staleness ?
GTC6244 Dec 9, 2025
b73a503
Handle datil old peers (#34)
mikelodder7 Dec 10, 2025
0677831
Keysets - handle multiples in DKG. (#15)
GTC6244 Dec 10, 2025
6498ee2
Merge branch 'master' into keysets
GTC6244 Dec 12, 2025
03f414d
fix tests
GTC6244 Dec 12, 2025
6e91c23
cargo fmt
GTC6244 Dec 12, 2025
cebdcb5
cargo update / abi staleness
GTC6244 Dec 12, 2025
a5de633
Merge branch 'master' into keysets
GTC6244 Dec 17, 2025
6cd79df
Fixes to merges & clippy updates
GTC6244 Dec 17, 2025
ea6776b
update tests
GTC6244 Dec 17, 2025
3d6b4d2
Fix deploy/test JS ( which I broke with a bad merge )
GTC6244 Dec 18, 2025
96775ed
prettier....
GTC6244 Dec 18, 2025
527d17f
Feature/node 4848 test datil keys in naga (#24)
GTC6244 Jan 6, 2026
0de3518
Feature/node 4874 support multiple chains at anvil level (#41)
GTC6244 Jan 6, 2026
907f940
Merge branch 'master' into keysets
GTC6244 Jan 6, 2026
8cbff16
Feature/node 4876 - using both chains in some tests ( adapt end user …
GTC6244 Jan 8, 2026
6521720
abi staleness + cargo fmt.
GTC6244 Jan 9, 2026
1ddd393
Remove traces of custom version upgrade testing. (#57)
GTC6244 Jan 9, 2026
68eda1d
fix: Invalid signature combination (#65)
mikelodder7 Jan 9, 2026
057a2fa
re-instate decryption assertion
GTC6244 Jan 9, 2026
eaa99d5
clippy.
GTC6244 Jan 9, 2026
cd4243f
remove unused val
GTC6244 Jan 9, 2026
468d3f7
make openapi spec (#66)
mikelodder7 Jan 11, 2026
ca8a759
Feature/node 4923 refactor upgrade tests to use local configurations …
GTC6244 Jan 13, 2026
cc37cc3
Merge branch 'master' into keysets
GTC6244 Jan 13, 2026
36da7ad
merge master fixes
GTC6244 Jan 13, 2026
eba9e96
Merge branch 'master' into keysets
GTC6244 Jan 13, 2026
00dee1f
try to update docs
GTC6244 Jan 13, 2026
3bd5a01
Merge branch 'keysets' of https://github.com/LIT-Protocol/lit-peer in…
GTC6244 Jan 13, 2026
7971384
force deploy on lit-actions.
GTC6244 Jan 14, 2026
d0dadb1
force deploy on more lit actions.
GTC6244 Jan 14, 2026
98b2947
Feature/node 4931 implement lit actions for keysets (datil support!) …
GTC6244 Jan 14, 2026
cf91a68
Merge branch 'master' into keysets
GTC6244 Jan 14, 2026
1a81d2c
Merge branch 'master' into keysets
GTC6244 Jan 14, 2026
eac046b
Remerge build.rs!
GTC6244 Jan 14, 2026
0932842
cargo fmt
GTC6244 Jan 14, 2026
eb18995
more debugging.
GTC6244 Jan 14, 2026
90a8322
Merge branch 'master' into keysets
GTC6244 Jan 14, 2026
5779ea5
remerge build.rs
GTC6244 Jan 14, 2026
de46379
cargo fmt
GTC6244 Jan 14, 2026
585a7f3
new deploy-config, 7 64core boxes, threshold 4
Garandor Jan 15, 2026
e42ec90
Merge branch 'release-naga-test-2025-01-14' into network-naga-test
Garandor Jan 15, 2026
72eb3cb
fix: Use RAII to deregister payment tracker for all requests
DashKash54 Jan 22, 2026
f418c28
refac: Cargo fmt
DashKash54 Jan 23, 2026
b3ecc59
test: Fix Delegation failure test scenario
DashKash54 Jan 23, 2026
0bb00e2
test: Debug failing session_sig_with_mgb_pkp_lit_action
DashKash54 Jan 23, 2026
f91f8cc
refac: Remove debug statements
DashKash54 Jan 23, 2026
caa0cbf
Merge branch 'master' into test
Garandor Jan 26, 2026
cf06c7f
Merge remote-tracking branch 'origin/fix-always-deregister-payment-tr…
Garandor Jan 26, 2026
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
394 changes: 394 additions & 0 deletions rust/lit-node/lit-node-testnet/src/end_user/datil_pkp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,394 @@
use crate::DEFAULT_DATIL_KEY_SET_NAME;
use crate::end_user::EndUser;
use ethers::middleware::SignerMiddleware;
use ethers::types::{Address, Bytes, H160, U256};
use lit_blockchain::util::decode_revert;
use lit_blockchain_lite::contracts::pkp_permissions::{AuthMethod, PKPPermissions};
use lit_blockchain_lite::contracts::pkpnft::PKPNFT;
use lit_core::utils::binary::bytes_to_hex;
use std::sync::Arc;
use tracing::{debug, error, info};

use super::Pkp;

impl Pkp {
pub async fn datil_new(end_user: &EndUser) -> Result<Self, anyhow::Error> {
let key_type: U256 = U256::from(2); // 2 is ECDSA key type

let pkpnft_address = end_user.actions().datil_contracts().pkpnft.address();

info!(
"Datil signing provider: {:?}",
end_user.datil_signing_provider()
);

let client = Arc::new(SignerMiddleware::new(
end_user.datil_signing_provider(),
end_user.wallet.clone(),
));

let pkpnft = PKPNFT::new(pkpnft_address, client);

info!("Minting a new PKP on the Datil test chain.");
let mint_cost = pkpnft.mint_cost().call().await?;
info!("Mint cost: {:}", mint_cost);

let mint_tx = pkpnft.mint_next(key_type).value(mint_cost);

let receipt = mint_tx
.send()
.await
.map_err(|e| {
let revert_msg = format!(
"Failed to send Datil PKP mint transaction: {}",
decode_revert(&e, end_user.actions().datil_contracts().pkpnft.abi())
);
error!(revert_msg);
anyhow::anyhow!(revert_msg)
})?
.await
.map_err(|e| {
let revert_msg = format!(
"Failed while waiting for Datil PKP mint confirmation: {}",
e
);
error!(revert_msg);
anyhow::anyhow!(revert_msg)
})?
.ok_or_else(|| anyhow::anyhow!("Transaction failed - no receipt generated"))?;

if receipt.logs.is_empty() {
return Err(anyhow::anyhow!("Transaction receipt contains no logs"));
}
let token_id = receipt.logs[0].topics[1];
let token_id = U256::from(token_id.as_bytes());

let r = end_user
.actions()
.datil_contracts()
.pubkey_router
.get_pubkey(token_id)
.call()
.await?;
let pubkey = bytes_to_hex(r);

let eth_address = pkpnft.get_eth_address(token_id).call().await?;

info!(
"Minted Datil PKP with token id: {} / pubkey : {} / eth address: {:?}",
token_id, &pubkey, eth_address
);

Ok(Pkp {
signing_provider: end_user.datil_signing_provider().clone(),
actions: Arc::new(end_user.actions().clone()),
pubkey: pubkey.clone(),
token_id,
eth_address,
key_set_id: DEFAULT_DATIL_KEY_SET_NAME.to_string(),
is_datil: true,
})
}

#[doc = "Grant an address permission to use a Datil PKP"]
pub async fn datil_add_permitted_address_to_pkp(
&self,
addr_to_add: H160,
scopes: &[U256],
) -> Result<bool, anyhow::Error> {
let client = self.signing_provider.clone();

let token_id = self.token_id;

info!(
"datil_add_permitted_address_to_pkp - adding address: {} to Datil PKP: {}",
addr_to_add, self.pubkey
);

let pkp_permissions_address = self.actions.datil_contracts().pkp_permissions.address();
let pkp_permissions = PKPPermissions::new(pkp_permissions_address, client.clone());
let pacc = pkp_permissions.add_permitted_address(token_id, addr_to_add, scopes.to_vec());

let tx = pacc.send().await;
if tx.is_err() {
error!("Error adding address to Datil PKP: {:?}", tx.unwrap_err());
return Err(anyhow::anyhow!(
"Error adding address to Datil PKP - couldn't send tx"
));
}
let tx = tx.unwrap();

let tr = tx.await;
if tr.is_err() {
error!("Error adding address to Datil PKP: {:?}", tr.unwrap_err());
return Err(anyhow::anyhow!(
"Error adding address to Datil PKP - waiting for tx"
));
}
let tr = tr.unwrap();
if tr.is_none() {
error!("Error adding address to Datil PKP: No transaction receipt?");
return Err(anyhow::anyhow!(
"Error adding address to DatilPKP - no tx receipt"
));
}

let pa = pkp_permissions
.get_permitted_addresses(token_id)
.call()
.await?;
info!("permitted addresses: {:?}", pa);
if !pa.contains(&addr_to_add) {
return Err(anyhow::anyhow!("Address not added to permitted list"));
}

Ok(true)
}

#[doc = "Transfer a PKP"]
pub async fn datil_transfer_pkp_with_wallet(
&self,
to_address: Address,
) -> Result<bool, anyhow::Error> {
info!(
"Transferring Datil PKP with token id: {} to address: {}",
self.token_id, to_address
);

let pkpnft_address = self.actions.datil_contracts().pkpnft.address();
let pkpnft = PKPNFT::new(pkpnft_address, self.signing_provider.clone());

let cc = pkpnft.transfer_from(
self.signing_provider.clone().address(),
to_address,
self.token_id,
);
let tx = cc.send().await;
if tx.is_err() {
let e = tx.unwrap_err();
info!(
"Decoded error: {}",
decode_revert(&e, self.actions.datil_contracts().pkpnft.abi()).to_string()
);
error!("Error sending transfer Datil PKP: {:?}", e);
return Err(anyhow::anyhow!("Error transferring Datil PKP - sending tx"));
}
let tx = tx.unwrap();

let tr = tx.await;
if tr.is_err() {
error!(
"Error waiting for transfer Datil PKP: {:?}",
tr.unwrap_err()
);
return Err(anyhow::anyhow!(
"Error transferring Datil PKP - waiting for tx"
));
}
let tr = tr.unwrap();
if tr.is_none() {
error!("Error transferring Datil PKP: No transaction receipt?");
return Err(anyhow::anyhow!(
"Error transferring Datil PKP - no tx receipt"
));
}

Ok(true)
}

#[doc = "Grant an action permission to use a Datil PKP"]
pub async fn datil_add_permitted_action_to_pkp(
&self,
ipfs_cid: &str,
scopes: &[U256],
) -> Result<bool, anyhow::Error> {
info!(
"datil_add_permitted_action_to_pkp - ipfs_cid to permit for token id: {} is: {}",
self.token_id, ipfs_cid
);

let pkp_permissions_address = self.actions.datil_contracts().pkp_permissions.address();
let pkp_permissions =
PKPPermissions::new(pkp_permissions_address, self.signing_provider.clone());
let pacc = pkp_permissions.add_permitted_action(
self.token_id,
Bytes::from(bs58::decode(ipfs_cid).into_vec().unwrap()),
scopes.to_vec(),
);

let tx = pacc.send().await;
if tx.is_err() {
error!("Error adding action to Datil PKP: {:?}", tx.unwrap_err());
return Err(anyhow::anyhow!("Error adding action to Datil PKP"));
}
let tx = tx.unwrap();

let tr = tx.await;
if tr.is_err() {
error!("Error adding action to Datil PKP: {:?}", tr.unwrap_err());
return Err(anyhow::anyhow!("Error adding action to Datil PKP"));
}
let tr = tr.unwrap();
if tr.is_none() {
error!("Error adding action to Datil PKP: No transaction receipt?");
return Err(anyhow::anyhow!("Error adding action to Datil PKP"));
}

Ok(true)
}

#[doc = "Grant a Address Authmethod permission to use a Datil PKP"]
pub async fn datil_add_permitted_address_auth_method_to_pkp(
&self,
address_token: Vec<u8>,
scopes: &[U256],
) -> Result<bool, anyhow::Error> {
let address_auth_method = AuthMethod {
auth_method_type: U256::from(1),
id: Bytes::from(address_token),
user_pubkey: Bytes::from(vec![]),
};
debug!("Address Auth method to permit: {:?}", address_auth_method);

let pkp_permissions_address = self.actions.datil_contracts().pkp_permissions.address();
let pkp_permissions =
PKPPermissions::new(pkp_permissions_address, self.signing_provider.clone());
let paam = pkp_permissions.add_permitted_auth_method(
self.token_id,
address_auth_method,
scopes.to_vec(),
);

let tx = paam.send().await;
if tx.is_err() {
error!(
"Error adding address authMethod to Datil PKP: {:?}",
tx.unwrap_err()
);
return Err(anyhow::anyhow!(
"Error adding address authMethod to Datil PKP"
));
}
let tx = tx.unwrap();

let tr = tx.await;
if tr.is_err() {
error!(
"Error adding address authMethod to Datil PKP: {:?}",
tr.unwrap_err()
);
return Err(anyhow::anyhow!(
"Error adding address authMethod to Datil PKP"
));
}
let tr = tr.unwrap();
if tr.is_none() {
error!("Error adding address authMethod to Datil PKP: No transaction receipt?");
return Err(anyhow::anyhow!(
"Error adding address authMethod to Datil PKP"
));
}

Ok(true)
}

pub async fn datil_mint_grant_and_burn_next_pkp(
end_user: &EndUser,
ipfs_cid: &str,
) -> Result<Self, anyhow::Error> {
// Use the deployer account by default
let client = end_user.datil_signing_provider().clone();

let key_type: U256 = U256::from(2);

let pkpnft_address = end_user.actions().datil_contracts().pkpnft.address();
let pkpnft = PKPNFT::new(pkpnft_address, Arc::new(client));

info!("Minting, granting and burning a new Datil PKP from the test harness.");
let mint_cost = pkpnft.mint_cost().call().await?;

// Convert ipfs_cid to Bytes
let ipfs_bytes = Bytes::from(bs58::decode(ipfs_cid).into_vec()?);

let mgb_tx = pkpnft
.mint_grant_and_burn_next(key_type, ipfs_bytes)
.value(mint_cost);

let receipt = mgb_tx
.send()
.await
.map_err(|e| {
let revert_msg = format!(
"Failed to send Datil PKP mint transaction: {}",
decode_revert(&e, end_user.actions().datil_contracts().pkpnft.abi())
);
error!(revert_msg);
anyhow::anyhow!(revert_msg)
})?
.await
.map_err(|e| {
let revert_msg = format!(
"Failed while waiting for Datil PKP mint confirmation: {}",
e
);
error!(revert_msg);
anyhow::anyhow!(revert_msg)
})?
.ok_or_else(|| anyhow::anyhow!("Transaction failed - no receipt generated"))?;

let token_id = receipt.logs[0].topics[1];
let token_id = U256::from(token_id.as_bytes());

let r = end_user
.actions()
.datil_contracts()
.pubkey_router
.get_pubkey(token_id)
.call()
.await?;

let pubkey = bytes_to_hex(r);
let eth_address = pkpnft.get_eth_address(token_id).call().await?;

info!(
"Minted Datil PKP with token id: {} / pubkey : {} / eth address: {:?}",
token_id, &pubkey, eth_address
);

Ok(Pkp {
signing_provider: end_user.datil_signing_provider().clone(),
actions: Arc::new(end_user.actions().clone()),
pubkey,
token_id,
key_set_id: "".to_string(),
eth_address: eth_address.into(),
is_datil: true,
})
}

pub async fn datil_burn_pkp(&self) -> Result<bool, anyhow::Error> {
let pkpnft_address = self.actions.datil_contracts().pkpnft.address();
let pkpnft = PKPNFT::new(pkpnft_address, self.signing_provider.clone());

let cc = pkpnft.burn(self.token_id);
let tx = cc.send().await;
if tx.is_err() {
error!("Error burning Datil PKP: {:?}", tx.unwrap_err());
return Err(anyhow::anyhow!("Error burning Datil PKP - sending tx"));
}
let tx = tx.unwrap();

let tr = tx.await;
if tr.is_err() {
error!("Error burning Datil PKP: {:?}", tr.unwrap_err());
return Err(anyhow::anyhow!("Error burning Datil PKP - waiting for tx"));
}
let tr = tr.unwrap();
if tr.is_none() {
error!("Error burning Datil PKP: No transaction receipt?");
return Err(anyhow::anyhow!("Error burning Datil PKP - no tx receipt"));
}

Ok(true)
}
}
Loading