Skip to content

Commit

Permalink
feat(dashpay): use v20 assetlocks (#1246)
Browse files Browse the repository at this point in the history
* feat: use v20 assetlocks
  • Loading branch information
HashEngineering authored Jan 16, 2024
1 parent 8ba371f commit add3638
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 65 deletions.
6 changes: 3 additions & 3 deletions wallet/src/de/schildbach/wallet/data/InvitationLinkData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import android.os.Parcelable
import de.schildbach.wallet.Constants
import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
import org.bitcoinj.evolution.CreditFundingTransaction
import org.bitcoinj.evolution.AssetLockTransaction
import org.bouncycastle.crypto.params.KeyParameter

@Parcelize
Expand All @@ -38,8 +38,8 @@ data class InvitationLinkData(val link: Uri, var validation: Boolean?) : Parcela
private const val PARAM_IS_LOCK = "islock"
private const val PARAM_IS_LOCK_2 = "is-lock"

fun create(username: String, displayName: String, avatarUrl: String, cftx: CreditFundingTransaction, aesKeyParameter: KeyParameter): InvitationLinkData {
val privateKey = cftx.creditBurnPublicKey.decrypt(aesKeyParameter)
fun create(username: String, displayName: String, avatarUrl: String, cftx: AssetLockTransaction, aesKeyParameter: KeyParameter): InvitationLinkData {
val privateKey = cftx.assetLockPublicKey.decrypt(aesKeyParameter)
val linkBuilder = Uri.parse("https://invitations.dashpay.io/applink").buildUpon()
.appendQueryParameter(PARAM_USER, username)
.appendQueryParameter(PARAM_CFTX, cftx.txId.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import org.bitcoinj.core.Coin
import org.bitcoinj.core.Sha256Hash
import org.bitcoinj.evolution.CreditFundingTransaction
import org.bitcoinj.evolution.AssetLockTransaction
import org.bitcoinj.wallet.Wallet
import org.bitcoinj.wallet.authentication.AuthenticationGroupExtension
import org.dash.wallet.common.WalletDataProvider
Expand Down Expand Up @@ -75,22 +75,22 @@ data class BlockchainIdentityData(var creationState: CreationState = CreationSta
}

@Ignore
private var creditFundingTransactionCache: CreditFundingTransaction? = null
private var creditFundingTransactionCache: AssetLockTransaction? = null

fun findCreditFundingTransaction(wallet: Wallet?): CreditFundingTransaction? {
fun findAssetLockTransaction(wallet: Wallet?): AssetLockTransaction? {
if (creditFundingTxId == null) {
return null
}
if (wallet != null) {
creditFundingTransactionCache = wallet.getTransaction(creditFundingTxId)?.run {
val authExtension = wallet.getKeyChainExtension(AuthenticationGroupExtension.EXTENSION_ID) as AuthenticationGroupExtension
authExtension.getCreditFundingTransaction(this)
authExtension.getAssetLockTransaction(this)
}
}
return creditFundingTransactionCache
}

fun getIdentity(wallet: Wallet?): String? = findCreditFundingTransaction(wallet)?.let { it.creditBurnIdentityIdentifier.toStringBase58() }
fun getIdentity(wallet: Wallet?): String? = findAssetLockTransaction(wallet)?.let { it.identityId.toStringBase58() }

fun getErrorMetadata() = creationStateErrorMessage?.let {
val metadataIndex = it.indexOf("Metadata(")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
import org.bitcoinj.core.listeners.PeerConnectedEventListener;
import org.bitcoinj.core.listeners.PeerDisconnectedEventListener;
import org.bitcoinj.core.listeners.PreBlocksDownloadListener;
import org.bitcoinj.evolution.CreditFundingTransaction;
import org.bitcoinj.evolution.AssetLockTransaction;
import org.bitcoinj.evolution.SimplifiedMasternodeList;
import org.bitcoinj.evolution.SimplifiedMasternodeListDiff;
import org.bitcoinj.evolution.SimplifiedMasternodeListManager;
Expand Down Expand Up @@ -329,14 +329,14 @@ public void onCoinsSent(final Wallet wallet, final Transaction tx, final Coin pr
log.info("onCoinsSent: {}", tx.getTxId());


if(CreditFundingTransaction.isCreditFundingTransaction(tx) && tx.getPurpose() == Transaction.Purpose.UNKNOWN) {
if(AssetLockTransaction.isAssetLockTransaction(tx) && tx.getPurpose() == Transaction.Purpose.UNKNOWN) {
// Handle credit function transactions (username creation, topup, invites)
AuthenticationGroupExtension authExtension =
(AuthenticationGroupExtension) wallet.getKeyChainExtension(AuthenticationGroupExtension.EXTENSION_ID);
CreditFundingTransaction cftx = authExtension.getCreditFundingTransaction(tx);
AssetLockTransaction cftx = authExtension.getAssetLockTransaction(tx);

long blockChainHeadTime = blockChain.getChainHead().getHeader().getTime().getTime();
platformRepo.handleSentCreditFundingTransaction(cftx, blockChainHeadTime);
platformRepo.handleSentAssetLockTransaction(cftx, blockChainHeadTime);

// TODO: if we detect a username creation that we haven't processed, should we?
}
Expand Down
44 changes: 22 additions & 22 deletions wallet/src/de/schildbach/wallet/ui/dashpay/CreateIdentityService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlinx.coroutines.*
import org.bitcoinj.core.RejectMessage
import org.bitcoinj.core.RejectedTransactionException
import org.bitcoinj.core.TransactionConfidence
import org.bitcoinj.evolution.CreditFundingTransaction
import org.bitcoinj.evolution.AssetLockTransaction
import org.bitcoinj.wallet.Wallet
import org.bitcoinj.wallet.authentication.AuthenticationGroupExtension
import org.bouncycastle.crypto.params.KeyParameter
Expand Down Expand Up @@ -265,10 +265,10 @@ class CreateIdentityService : LifecycleService() {
when {
(blockchainIdentityDataTmp != null && blockchainIdentityDataTmp.restoring) -> {
// TODO: handle case when blockchain reset has happened and the cftx was not found yet
val cftx = blockchainIdentityDataTmp.findCreditFundingTransaction(walletApplication.wallet)
val cftx = blockchainIdentityDataTmp.findAssetLockTransaction(walletApplication.wallet)
?: throw IllegalStateException()

restoreIdentity(cftx.creditBurnIdentityIdentifier.bytes)
restoreIdentity(cftx.identityId.bytes)
return
}
(blockchainIdentityDataTmp != null && !retryWithNewUserName) -> {
Expand Down Expand Up @@ -325,10 +325,10 @@ class CreateIdentityService : LifecycleService() {
val authenticationGroupExtension = wallet.getKeyChainExtension(AuthenticationGroupExtension.EXTENSION_ID) as AuthenticationGroupExtension
val blockchainIdentity = platformRepo.initBlockchainIdentity(blockchainIdentityData, wallet)
// look for the credit funding tx in case there was an error in the next step previously
for (tx in authenticationGroupExtension.creditFundingTransactions) {
tx as CreditFundingTransaction
if (authenticationGroupExtension.identityFundingKeyChain.findKeyFromPubHash(tx.creditBurnPublicKeyId.bytes) != null) {
blockchainIdentity.initializeCreditFundingTransaction(tx)
for (tx in authenticationGroupExtension.assetLockTransactions) {
tx as AssetLockTransaction
if (authenticationGroupExtension.identityFundingKeyChain.findKeyFromPubHash(tx.assetLockPublicKeyId.bytes) != null) {
blockchainIdentity.initializeAssetLockTransaction(tx)
}
}

Expand All @@ -338,22 +338,22 @@ class CreateIdentityService : LifecycleService() {
// Step 2: Create and send the credit funding transaction
//
// check to see if the funding transaction exists
if (blockchainIdentity.creditFundingTransaction == null) {
if (blockchainIdentity.assetLockTransaction == null) {
val useCoinJoin = coinJoinConfig.getMode() != CoinJoinMode.NONE
platformRepo.createCreditFundingTransactionAsync(blockchainIdentity, encryptionKey, useCoinJoin)
platformRepo.createAssetLockTransactionAsync(blockchainIdentity, encryptionKey, useCoinJoin)
}
}

if (blockchainIdentityData.creationState <= CreationState.CREDIT_FUNDING_TX_SENDING) {
platformRepo.updateIdentityCreationState(blockchainIdentityData, CreationState.CREDIT_FUNDING_TX_SENDING)
val timerIsLock = AnalyticsTimer(analytics, log, AnalyticsConstants.Process.PROCESS_USERNAME_CREATE_ISLOCK)
// check to see if the funding transaction has been sent previously
val sent = blockchainIdentity.creditFundingTransaction!!.confidence?.let {
val sent = blockchainIdentity.assetLockTransaction!!.confidence?.let {
it.isSent || it.isIX || it.numBroadcastPeers() > 0 || it.confidenceType == TransactionConfidence.ConfidenceType.BUILDING
} ?: false

if (!sent) {
sendTransaction(blockchainIdentity.creditFundingTransaction!!)
sendTransaction(blockchainIdentity.assetLockTransaction!!)
}
timerIsLock.logTiming()
}
Expand Down Expand Up @@ -407,10 +407,10 @@ class CreateIdentityService : LifecycleService() {

when {
(blockchainIdentityDataTmp != null && blockchainIdentityDataTmp.restoring) -> {
val cftx = blockchainIdentityDataTmp.findCreditFundingTransaction(walletApplication.wallet)
val cftx = blockchainIdentityDataTmp.findAssetLockTransaction(walletApplication.wallet)
?: throw IllegalStateException()

restoreIdentity(cftx.creditBurnIdentityIdentifier.bytes)
restoreIdentity(cftx.identityId.bytes)
return
}
(blockchainIdentityDataTmp != null && !retryWithNewUserName) -> {
Expand Down Expand Up @@ -474,10 +474,10 @@ class CreateIdentityService : LifecycleService() {
//
// Step 2: Create and send the credit funding transaction
//
platformRepo.obtainCreditFundingTransactionAsync(blockchainIdentity, blockchainIdentityData.invite!!)
platformRepo.obtainAssetLockTransactionAsync(blockchainIdentity, blockchainIdentityData.invite!!)
} else {
// if we are retrying, then we need to initialize the credit funding tx
platformRepo.obtainCreditFundingTransactionAsync(blockchainIdentity, blockchainIdentityData.invite!!)
platformRepo.obtainAssetLockTransactionAsync(blockchainIdentity, blockchainIdentityData.invite!!)
}

if (blockchainIdentityData.creationState <= CreationState.CREDIT_FUNDING_TX_SENDING) {
Expand Down Expand Up @@ -647,24 +647,24 @@ class CreateIdentityService : LifecycleService() {

val authExtension = walletApplication.wallet!!.getKeyChainExtension(AuthenticationGroupExtension.EXTENSION_ID) as AuthenticationGroupExtension
//authExtension.setWallet(walletApplication.wallet!!) // why is the wallet not set? we didn't deserialize it probably!
val cftxs = authExtension.creditFundingTransactions
val cftxs = authExtension.assetLockTransactions

val creditFundingTransaction: CreditFundingTransaction? = cftxs.find { it.creditBurnIdentityIdentifier.bytes!!.contentEquals(identity) }
val creditFundingTransaction: AssetLockTransaction? = cftxs.find { it.identityId.bytes!!.contentEquals(identity) }

val existingBlockchainIdentityData = blockchainIdentityDataDao.load()
if (existingBlockchainIdentityData != null) {
log.info("Attempting restore of existing identity and username; save credit funding txid")
val blockchainIdentity = platformRepo.blockchainIdentity
blockchainIdentity.creditFundingTransaction = creditFundingTransaction
blockchainIdentity.assetLockTransaction = creditFundingTransaction
existingBlockchainIdentityData.creditFundingTxId = creditFundingTransaction!!.txId
platformRepo.updateBlockchainIdentityData(existingBlockchainIdentityData)
return
}

val loadingFromCreditFundingTransaction = creditFundingTransaction != null
val loadingFromAssetLockTransaction = creditFundingTransaction != null
val existingIdentity: Identity?

if (!loadingFromCreditFundingTransaction) {
if (!loadingFromAssetLockTransaction) {
existingIdentity = platformRepo.getIdentityFromPublicKeyId()
if (existingIdentity == null) {
throw IllegalArgumentException("identity $identity does not match a credit funding transaction or it doesn't exist on the network")
Expand All @@ -690,7 +690,7 @@ class CreateIdentityService : LifecycleService() {
// Step 3: Find the identity
//
platformRepo.updateIdentityCreationState(blockchainIdentityData, CreationState.IDENTITY_REGISTERING)
if (loadingFromCreditFundingTransaction) {
if (loadingFromAssetLockTransaction) {
platformRepo.recoverIdentityAsync(blockchainIdentity, creditFundingTransaction!!)
} else {
val firstIdentityKey = platformRepo.getBlockchainIdentityKey(0, encryptionKey)!!
Expand Down Expand Up @@ -746,7 +746,7 @@ class CreateIdentityService : LifecycleService() {
* @param cftx The credit funding transaction to send
* @return True if successful
*/
private suspend fun sendTransaction(cftx: CreditFundingTransaction): Boolean {
private suspend fun sendTransaction(cftx: AssetLockTransaction): Boolean {
log.info("Sending credit funding transaction: ${cftx.txId}")
return suspendCoroutine { continuation ->
cftx.confidence.addEventListener(object : TransactionConfidence.Listener {
Expand Down
Loading

0 comments on commit add3638

Please sign in to comment.