This commit is contained in:
Hossein Zoda 2026-04-27 04:19:53 +03:00
parent 988426e485
commit aa99f775da

View file

@ -222,9 +222,9 @@ pub enum IdoState {
/*UNUSED /*UNUSED
fn script_concat(script: Script, v: &[u8]) -> Script { fn script_concat(script: Script, v: &[u8]) -> Script {
let mut bytes = script.to_bytes(); let mut bytes = script.to_bytes();
bytes.extend_from_slice(v); bytes.extend_from_slice(v);
Script::from(bytes) Script::from(bytes)
} }
*/ */
fn build_p2nfth_script(nfthash: &[u8]) -> Script { fn build_p2nfth_script(nfthash: &[u8]) -> Script {
@ -561,7 +561,8 @@ pub async fn prepare_tables(pool: &SqlitePool) {
state BLOB NOT NULL, state BLOB NOT NULL,
txchain_entrypoint INTEGER NULL, txchain_entrypoint INTEGER NULL,
txchain_head INTEGER NULL, txchain_head INTEGER NULL,
is_valid INTEGER NOT NULL is_valid INTEGER NOT NULL,
is_token_created_at_preinit INTEGER NOT NULL
)", )",
) )
.execute(pool) .execute(pool)
@ -650,6 +651,7 @@ pub struct IdoDBRecord {
txchain_entrypoint: Option<i64>, txchain_entrypoint: Option<i64>,
txchain_head: Option<i64>, txchain_head: Option<i64>,
is_valid: bool, is_valid: bool,
is_token_created_at_preinit: bool,
} }
impl IdoDBRecord { impl IdoDBRecord {
fn from_row(row: &sqlx::sqlite::SqliteRow) -> Result<Self> { fn from_row(row: &sqlx::sqlite::SqliteRow) -> Result<Self> {
@ -666,6 +668,7 @@ impl IdoDBRecord {
txchain_entrypoint: row.get(9), txchain_entrypoint: row.get(9),
txchain_head: row.get(10), txchain_head: row.get(10),
is_valid: row.get(11), is_valid: row.get(11),
is_token_created_at_preinit: row.get(12),
}) })
} }
} }
@ -750,7 +753,7 @@ async fn ido_lookup(
) -> Result<Option<IdoDBRecord>> { ) -> Result<Option<IdoDBRecord>> {
let row = sqlx::query( let row = sqlx::query(
"SELECT id, preinit_txid, init_txid, launch_txid, offering_token_id, offered_token_id, "SELECT id, preinit_txid, init_txid, launch_txid, offering_token_id, offered_token_id,
status, parameters, state, txchain_entrypoint, txchain_head, is_valid status, parameters, state, txchain_entrypoint, txchain_head, is_valid, is_token_created_at_preinit
FROM ido WHERE id = ?", FROM ido WHERE id = ?",
) )
.bind(ido_id) .bind(ido_id)
@ -802,6 +805,7 @@ struct IdoContext {
parameters: IdoParameters, parameters: IdoParameters,
state: IdoState, state: IdoState,
is_valid_ido: bool, is_valid_ido: bool,
is_token_created_at_preinit: bool,
offered_token_id: Option<Vec<u8>>, offered_token_id: Option<Vec<u8>>,
offering_token_id: Option<Vec<u8>>, offering_token_id: Option<Vec<u8>>,
} }
@ -948,12 +952,12 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
) )
).to_bytes() ).to_bytes()
) != offeringBytecodeStorageOut.unwrap().script_pubkey { ) != offeringBytecodeStorageOut.unwrap().script_pubkey {
return Err(anyhow::anyhow!("on_create_info, offering bytecode storage does not match!")); return Err(anyhow::anyhow!("offering bytecode storage does not match!"));
} }
let launcherBytecodeStorageOut = tx.output.get(3); let launcherBytecodeStorageOut = tx.output.get(3);
if launcherBytecodeStorageOut.is_none() { if launcherBytecodeStorageOut.is_none() {
return Err(anyhow::anyhow!("on_create_info, launcher bytecode storage not defined!")); return Err(anyhow::anyhow!("launcher bytecode storage not defined!"));
} }
if build_p2sh32_script( if build_p2sh32_script(
&build_storage_script_with_data( &build_storage_script_with_data(
@ -1088,6 +1092,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
is_valid_ido: is_valid_ido, is_valid_ido: is_valid_ido,
offered_token_id: offered_token_id, offered_token_id: offered_token_id,
offering_token_id: None, offering_token_id: None,
is_token_created_at_preinit: !offered_token_is_in_supply,
}) })
} }
@ -1095,12 +1100,14 @@ async fn on_create_ido(
network: Option<Network>, network: Option<Network>,
pool: &SqlitePool, pool: &SqlitePool,
tx: &Transaction, tx: &Transaction,
block_height: i64,
) -> Result<()> { ) -> Result<()> {
match create_ido_context_from_preinit(network, tx).await { match create_ido_context_from_preinit(network, tx).await {
Ok(context) => { Ok(context) => {
// create the ido // create the ido
let mut dbtx = pool.begin().await?;
let result = sqlx::query( let result = sqlx::query(
"INSERT INTO ido (preinit_txid, init_txid, launch_txid, offering_token_id, offered_token_id, status, parameters, state, is_valid, txchain_entrypoint, txchain_head) "INSERT INTO ido (preinit_txid, init_txid, launch_txid, offering_token_id, offered_token_id, status, parameters, state, is_valid, is_token_created_at_preinit, txchain_entrypoint, txchain_head)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
) )
.bind(context.preinit_txid) .bind(context.preinit_txid)
@ -1112,43 +1119,29 @@ async fn on_create_ido(
.bind(serde_json::to_vec(&context.parameters).unwrap()) .bind(serde_json::to_vec(&context.parameters).unwrap())
.bind(serde_json::to_vec(&context.state).unwrap()) .bind(serde_json::to_vec(&context.state).unwrap())
.bind(context.is_valid_ido) .bind(context.is_valid_ido)
.bind(context.is_token_created_at_preinit)
.bind(None::<i64>) .bind(None::<i64>)
.bind(None::<i64>) .bind(None::<i64>)
.execute(pool) .execute(&mut *dbtx)
.await; .await;
match result { match result {
Ok(r) => { Ok(r) => {
// insert txchain entrypoint // insert txchain entrypoint
let ido_id = r.last_insert_rowid(); let ido_id = r.last_insert_rowid();
let serialized_tx = bitcoincash::consensus::serialize(tx); let txchain_item_id = upsert_ido_txchain(&mut dbtx, tx, ido_id, None::<i64>, block_height, 1)
let result2 = sqlx::query( .await?;
"INSERT INTO ido_txchain (prev_id, ido_id, txid, tx)
VALUES (?, ?, ?, ?)",
)
.bind(None::<i64>)
.bind(ido_id)
.bind(tx.txid().to_blob())
.bind(serialized_tx)
.execute(pool)
.await;
match result2 {
Ok(r2) => {
// update txchain_entrypoint & txchain_head for the ido
let item_id = r2.last_insert_rowid();
sqlx::query( sqlx::query(
"UPDATE ido SET txchain_entrypoint = ?, txchain_head = ? "UPDATE ido SET txchain_entrypoint = ?, txchain_head = ?
WHERE id = ?", WHERE id = ?",
) )
.bind(item_id) .bind(txchain_item_id)
.bind(item_id) .bind(txchain_item_id)
.bind(ido_id) .bind(ido_id)
.execute(pool) .execute(&mut *dbtx)
.await?; .await?;
dbtx.commit().await?;
Ok(()) Ok(())
} },
Err(e) => Err(e.into()),
}
}
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
} }
}, },
@ -1734,6 +1727,7 @@ async fn on_add_ido_tx(
parameters: serde_json::from_slice(&ido.parameters).expect("Failed to parse parameters"), parameters: serde_json::from_slice(&ido.parameters).expect("Failed to parse parameters"),
state: serde_json::from_slice(&ido.state).expect("Failed to parse state"), state: serde_json::from_slice(&ido.state).expect("Failed to parse state"),
is_valid_ido: ido.is_valid, is_valid_ido: ido.is_valid,
is_token_created_at_preinit: ido.is_token_created_at_preinit,
offered_token_id: ido.offered_token_id.clone(), offered_token_id: ido.offered_token_id.clone(),
offering_token_id: ido.offering_token_id.clone(), offering_token_id: ido.offering_token_id.clone(),
}; };
@ -1774,8 +1768,11 @@ pub async fn index_block(
for tx in sorted_txs { for tx in sorted_txs {
// detect a new ido // detect a new ido
if is_preinit_broadcast(tx) { if is_preinit_broadcast(tx) {
on_create_ido(network, pool, tx) match on_create_ido(network, pool, tx, block_height)
.await?; .await {
Err(err) => info!("failed to detect an ido, or an invalid ido detected, txid: {}, {}", hex::encode(tx.txid().to_blob()), err),
_ => (),
}
} else if is_ido_sig_in_tx_inputs(tx) { } else if is_ido_sig_in_tx_inputs(tx) {
// has ido sig // has ido sig
for input_index in [ 0, 1, 3 ] { for input_index in [ 0, 1, 3 ] {
@ -1792,8 +1789,11 @@ pub async fn index_block(
let ido = ido_lookup(pool, txchain_item.ido_id) let ido = ido_lookup(pool, txchain_item.ido_id)
.await? .await?
.expect("ido record not found!!"); .expect("ido record not found!!");
on_add_ido_tx(network, pool, &ido, &txchain_item, tx, block_height) match on_add_ido_tx(network, pool, &ido, &txchain_item, tx, block_height)
.await?; .await {
Err(err) => info!("add tx to an ido failed, txid: {}, {}", hex::encode(tx.txid().to_blob()), err),
_ => (),
}
} }
} }
} }