Skip to content

Commit

Permalink
WIP: create and sign assetLockTx
Browse files Browse the repository at this point in the history
  • Loading branch information
coolaj86 committed Aug 23, 2024
1 parent e0dc64b commit 59c561e
Showing 1 changed file with 271 additions and 0 deletions.
271 changes: 271 additions & 0 deletions demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
"use strict";

let DashPhrase = require("dashphrase");
let DashHd = require("dashhd");
let DashKeys = require("dashkeys");
let DashTx = require("dashtx");
let DashPlatform = require("./dashplatform.js");

let KeyUtils = require("./key-utils.js");

// let DapiGrpc = require("@dashevo/dapi-grpc");
let Dpp = require("@dashevo/wasm-dpp");

const DIP13_ECDSA = 0;

let identityEcdsaPath = "";
{
// m/purpose'/coin_type'/feature'/subfeature'/keytype'/identityindex'/keyindex'
// ex: m/9'/5'/5'/0'/0'/<id>/<key>
let purposeDip13 = 9;
let coinDash = 5;
let featureId = 5;
let subfeatureKey = 0;
let keyType = DIP13_ECDSA;
identityEcdsaPath = `m/${purposeDip13}'/${coinDash}'/${featureId}'/${subfeatureKey}'/${keyType}'`;
}

async function main() {
let network = "testnet";

// let phrase = await DashPhrase.generate();
let phrase =
"casino reveal crop open ordinary garment spy pizza clown exercise poem enjoy";
let salt = "";
let seedBytes = await DashPhrase.toSeed(phrase, salt);
let walletKey = await DashHd.fromSeed(seedBytes);

let accountIndex = 0; // pick the desired account for paying the fee
let addressIndex = 8; // pick an address with funds
let accountKey = await walletKey.deriveAccount(accountIndex);
let use = DashHd.RECEIVE;
let xprvKey = await accountKey.deriveXKey(use);
let addressKey = await xprvKey.deriveAddress(addressIndex);
if (!addressKey.privateKey) {
throw new Error("not an error, just a lint hack");
}

let addr = await DashHd.toAddr(addressKey.publicKey, { version: network });
let pkhBytes = await DashKeys.addrToPkh(addr, {
//@ts-ignore
version: network,
});
let pkh = DashKeys.utils.bytesToHex(pkhBytes);
let wif = await DashHd.toWif(addressKey.privateKey, { version: network });
console.log();
console.log(`Address: ${addr}`);
// TODO is _this_ the assetLockPrivateKey??
console.log(`WIF: ${wif}`);

KeyUtils.set(addr, {
address: addr,
publicKey: addressKey.publicKey,
privateKey: addressKey.privateKey,
pubKeyHash: pkh,
});

let rpcAuthUrl = "https://api:[email protected]";
let utxos = await DashTx.utils.rpc(rpcAuthUrl, "getaddressutxos", {
addresses: [addr],
});
let total = DashTx.sum(utxos);
console.log();
console.log(`utxos (${total})`);
console.log(utxos);

// TODO which hd paths to use for which addresses?
let creditOutputs = [{ satoshis: total - 10000, pubKeyHash: pkh }];
let totalCredits = DashTx.sum(creditOutputs);
let burnOutput = { satoshis: totalCredits, pubKeyHash: pkh };
//@ts-ignore - TODO add types
let assetLockScript = DashPlatform.Tx.packAssetLock({
creditOutputs,
});

const VERSION_PLATFORM = 3;
const TYPE_ASSET_LOCK = 8;
let txDraft = {
version: VERSION_PLATFORM,
type: TYPE_ASSET_LOCK,
inputs: utxos,
outputs: [burnOutput],
extraPayload: assetLockScript,
};
console.log();
console.log(`txDraft:`);
console.log(txDraft);

let dashTx = DashTx.create(KeyUtils);
let txSigned = await dashTx.hashAndSignAll(txDraft);
console.log();
console.log(`txSigned:`);
console.log(txSigned);

// let assetLockProof = await YoureAWizardHarry.doMagic();

// let idIndex = 0; // increment to first unused
// await getKeysForIdentity(idIndex);

// let identityId = assetLockProof.createIdentifier();
// let identity = Dpp.identity.create(identityId, dppKeys);
// let signedTransition = signTransition(
// idenity,
// assetLockProof,
// assetLockPrivateKeyBuffer,
// );

console.log("");
console.log("TODO");
console.log(` - which is considered the "asset lock private key buffer"?`);
console.log(` - can we bypass Dpp.IdentityPublicKey?`);
console.log(` - what's all this super signing the transition about?`);
console.log(` - how to broadcast the transition?`);
}

async function getKeysForIdentity(idIndex) {
let identityEcdsaKey = await DashHd.derivePath(walletKey, identityEcdsaPath);
let identityKey = await DashHd.deriveChild(
identityEcdsaKey,
idIndex,
DashHd.HARDENED,
);

const MASTER_KEY = 0;
const HIGH_AUTH_KEY = 1;
const CRITICAL_KEY = 2;
const TRANSFER_KEY = 3;

let keyDescs = [
{
id: MASTER_KEY,
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.MASTER,
},
{
id: HIGH_AUTH_KEY,
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.HIGH,
},
{
id: CRITICAL_KEY,
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.CRITICAL,
},
{
id: TRANSFER_KEY,
purpose: Dpp.IdentityPublicKey.PURPOSES.TRANSFER,
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.CRITICAL,
},
];

let keys = [];
let dppKeys = [];
for (let keyDesc of keyDescs) {
let key = await DashHd.deriveChild(
identityKey,
keyDesc.id,
DashHd.HARDENED,
);
keys.push(key);

let MAGIC_NUMBER_1 = 1; // TODO why?
let dppKey = new Dpp.IdentityPublicKey(MAGIC_NUMBER_1);
dppKey.setId(keyDesc.id);
dppKey.setData(key.publicKey);
if (keyDesc.purpose) {
dppKey.setPurpose(keyDesc.purpose);
}
dppKey.setSecurityLevel(keyDesc.securityLevel);
dppKeys.push(dppKey);
}

return dppKeys;
}

function signTransition(identity, assetLockProof, assetLockPrivateKey) {
// TODO is assetLockProof the same as txoutproof?

// Create ST
const identityCreateTransition = Dpp.identity.createIdentityCreateTransition(
identity,
assetLockProof,
);

// Create key proofs
const [stMasterKey, stHighAuthKey, stCriticalAuthKey, stTransferKey] =
identityCreateTransition.getPublicKeys();

// Sign master key

identityCreateTransition.signByPrivateKey(
identityMasterPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stMasterKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

// Sign high auth key

identityCreateTransition.signByPrivateKey(
identityHighAuthPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stHighAuthKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

// Sign critical auth key

identityCreateTransition.signByPrivateKey(
identityCriticalAuthPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stCriticalAuthKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

// Sign transfer key

identityCreateTransition.signByPrivateKey(
identityTransferPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stTransferKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

// Set public keys back after updating their signatures
identityCreateTransition.setPublicKeys([
stMasterKey,
stHighAuthKey,
stCriticalAuthKey,
stTransferKey,
]);

// Sign and validate state transition

identityCreateTransition.signByPrivateKey(
assetLockPrivateKey,
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

// TODO(versioning): restore
// @ts-ignore
// const result = await Dpp.stateTransition.validateBasic(
// identityCreateTransition,
// // TODO(v0.24-backport): get rid of this once decided
// // whether we need execution context in wasm bindings
// new StateTransitionExecutionContext(),
// );

// if (!result.isValid()) {
// const messages = result.getErrors().map((error) => error.message);
// throw new Error(`StateTransition is invalid - ${JSON.stringify(messages)}`);
// }

return identityCreateTransition;
}

main();

0 comments on commit 59c561e

Please sign in to comment.