Skip to content

Commit 59c561e

Browse files
committed
WIP: create and sign assetLockTx
1 parent e0dc64b commit 59c561e

File tree

1 file changed

+271
-0
lines changed

1 file changed

+271
-0
lines changed

demo.js

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
"use strict";
2+
3+
let DashPhrase = require("dashphrase");
4+
let DashHd = require("dashhd");
5+
let DashKeys = require("dashkeys");
6+
let DashTx = require("dashtx");
7+
let DashPlatform = require("./dashplatform.js");
8+
9+
let KeyUtils = require("./key-utils.js");
10+
11+
// let DapiGrpc = require("@dashevo/dapi-grpc");
12+
let Dpp = require("@dashevo/wasm-dpp");
13+
14+
const DIP13_ECDSA = 0;
15+
16+
let identityEcdsaPath = "";
17+
{
18+
// m/purpose'/coin_type'/feature'/subfeature'/keytype'/identityindex'/keyindex'
19+
// ex: m/9'/5'/5'/0'/0'/<id>/<key>
20+
let purposeDip13 = 9;
21+
let coinDash = 5;
22+
let featureId = 5;
23+
let subfeatureKey = 0;
24+
let keyType = DIP13_ECDSA;
25+
identityEcdsaPath = `m/${purposeDip13}'/${coinDash}'/${featureId}'/${subfeatureKey}'/${keyType}'`;
26+
}
27+
28+
async function main() {
29+
let network = "testnet";
30+
31+
// let phrase = await DashPhrase.generate();
32+
let phrase =
33+
"casino reveal crop open ordinary garment spy pizza clown exercise poem enjoy";
34+
let salt = "";
35+
let seedBytes = await DashPhrase.toSeed(phrase, salt);
36+
let walletKey = await DashHd.fromSeed(seedBytes);
37+
38+
let accountIndex = 0; // pick the desired account for paying the fee
39+
let addressIndex = 8; // pick an address with funds
40+
let accountKey = await walletKey.deriveAccount(accountIndex);
41+
let use = DashHd.RECEIVE;
42+
let xprvKey = await accountKey.deriveXKey(use);
43+
let addressKey = await xprvKey.deriveAddress(addressIndex);
44+
if (!addressKey.privateKey) {
45+
throw new Error("not an error, just a lint hack");
46+
}
47+
48+
let addr = await DashHd.toAddr(addressKey.publicKey, { version: network });
49+
let pkhBytes = await DashKeys.addrToPkh(addr, {
50+
//@ts-ignore
51+
version: network,
52+
});
53+
let pkh = DashKeys.utils.bytesToHex(pkhBytes);
54+
let wif = await DashHd.toWif(addressKey.privateKey, { version: network });
55+
console.log();
56+
console.log(`Address: ${addr}`);
57+
// TODO is _this_ the assetLockPrivateKey??
58+
console.log(`WIF: ${wif}`);
59+
60+
KeyUtils.set(addr, {
61+
address: addr,
62+
publicKey: addressKey.publicKey,
63+
privateKey: addressKey.privateKey,
64+
pubKeyHash: pkh,
65+
});
66+
67+
let rpcAuthUrl = "https://api:[email protected]";
68+
let utxos = await DashTx.utils.rpc(rpcAuthUrl, "getaddressutxos", {
69+
addresses: [addr],
70+
});
71+
let total = DashTx.sum(utxos);
72+
console.log();
73+
console.log(`utxos (${total})`);
74+
console.log(utxos);
75+
76+
// TODO which hd paths to use for which addresses?
77+
let creditOutputs = [{ satoshis: total - 10000, pubKeyHash: pkh }];
78+
let totalCredits = DashTx.sum(creditOutputs);
79+
let burnOutput = { satoshis: totalCredits, pubKeyHash: pkh };
80+
//@ts-ignore - TODO add types
81+
let assetLockScript = DashPlatform.Tx.packAssetLock({
82+
creditOutputs,
83+
});
84+
85+
const VERSION_PLATFORM = 3;
86+
const TYPE_ASSET_LOCK = 8;
87+
let txDraft = {
88+
version: VERSION_PLATFORM,
89+
type: TYPE_ASSET_LOCK,
90+
inputs: utxos,
91+
outputs: [burnOutput],
92+
extraPayload: assetLockScript,
93+
};
94+
console.log();
95+
console.log(`txDraft:`);
96+
console.log(txDraft);
97+
98+
let dashTx = DashTx.create(KeyUtils);
99+
let txSigned = await dashTx.hashAndSignAll(txDraft);
100+
console.log();
101+
console.log(`txSigned:`);
102+
console.log(txSigned);
103+
104+
// let assetLockProof = await YoureAWizardHarry.doMagic();
105+
106+
// let idIndex = 0; // increment to first unused
107+
// await getKeysForIdentity(idIndex);
108+
109+
// let identityId = assetLockProof.createIdentifier();
110+
// let identity = Dpp.identity.create(identityId, dppKeys);
111+
// let signedTransition = signTransition(
112+
// idenity,
113+
// assetLockProof,
114+
// assetLockPrivateKeyBuffer,
115+
// );
116+
117+
console.log("");
118+
console.log("TODO");
119+
console.log(` - which is considered the "asset lock private key buffer"?`);
120+
console.log(` - can we bypass Dpp.IdentityPublicKey?`);
121+
console.log(` - what's all this super signing the transition about?`);
122+
console.log(` - how to broadcast the transition?`);
123+
}
124+
125+
async function getKeysForIdentity(idIndex) {
126+
let identityEcdsaKey = await DashHd.derivePath(walletKey, identityEcdsaPath);
127+
let identityKey = await DashHd.deriveChild(
128+
identityEcdsaKey,
129+
idIndex,
130+
DashHd.HARDENED,
131+
);
132+
133+
const MASTER_KEY = 0;
134+
const HIGH_AUTH_KEY = 1;
135+
const CRITICAL_KEY = 2;
136+
const TRANSFER_KEY = 3;
137+
138+
let keyDescs = [
139+
{
140+
id: MASTER_KEY,
141+
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.MASTER,
142+
},
143+
{
144+
id: HIGH_AUTH_KEY,
145+
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.HIGH,
146+
},
147+
{
148+
id: CRITICAL_KEY,
149+
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.CRITICAL,
150+
},
151+
{
152+
id: TRANSFER_KEY,
153+
purpose: Dpp.IdentityPublicKey.PURPOSES.TRANSFER,
154+
securityLevel: Dpp.IdentityPublicKey.SECURITY_LEVELS.CRITICAL,
155+
},
156+
];
157+
158+
let keys = [];
159+
let dppKeys = [];
160+
for (let keyDesc of keyDescs) {
161+
let key = await DashHd.deriveChild(
162+
identityKey,
163+
keyDesc.id,
164+
DashHd.HARDENED,
165+
);
166+
keys.push(key);
167+
168+
let MAGIC_NUMBER_1 = 1; // TODO why?
169+
let dppKey = new Dpp.IdentityPublicKey(MAGIC_NUMBER_1);
170+
dppKey.setId(keyDesc.id);
171+
dppKey.setData(key.publicKey);
172+
if (keyDesc.purpose) {
173+
dppKey.setPurpose(keyDesc.purpose);
174+
}
175+
dppKey.setSecurityLevel(keyDesc.securityLevel);
176+
dppKeys.push(dppKey);
177+
}
178+
179+
return dppKeys;
180+
}
181+
182+
function signTransition(identity, assetLockProof, assetLockPrivateKey) {
183+
// TODO is assetLockProof the same as txoutproof?
184+
185+
// Create ST
186+
const identityCreateTransition = Dpp.identity.createIdentityCreateTransition(
187+
identity,
188+
assetLockProof,
189+
);
190+
191+
// Create key proofs
192+
const [stMasterKey, stHighAuthKey, stCriticalAuthKey, stTransferKey] =
193+
identityCreateTransition.getPublicKeys();
194+
195+
// Sign master key
196+
197+
identityCreateTransition.signByPrivateKey(
198+
identityMasterPrivateKey.toBuffer(),
199+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
200+
);
201+
202+
stMasterKey.setSignature(identityCreateTransition.getSignature());
203+
204+
identityCreateTransition.setSignature(undefined);
205+
206+
// Sign high auth key
207+
208+
identityCreateTransition.signByPrivateKey(
209+
identityHighAuthPrivateKey.toBuffer(),
210+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
211+
);
212+
213+
stHighAuthKey.setSignature(identityCreateTransition.getSignature());
214+
215+
identityCreateTransition.setSignature(undefined);
216+
217+
// Sign critical auth key
218+
219+
identityCreateTransition.signByPrivateKey(
220+
identityCriticalAuthPrivateKey.toBuffer(),
221+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
222+
);
223+
224+
stCriticalAuthKey.setSignature(identityCreateTransition.getSignature());
225+
226+
identityCreateTransition.setSignature(undefined);
227+
228+
// Sign transfer key
229+
230+
identityCreateTransition.signByPrivateKey(
231+
identityTransferPrivateKey.toBuffer(),
232+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
233+
);
234+
235+
stTransferKey.setSignature(identityCreateTransition.getSignature());
236+
237+
identityCreateTransition.setSignature(undefined);
238+
239+
// Set public keys back after updating their signatures
240+
identityCreateTransition.setPublicKeys([
241+
stMasterKey,
242+
stHighAuthKey,
243+
stCriticalAuthKey,
244+
stTransferKey,
245+
]);
246+
247+
// Sign and validate state transition
248+
249+
identityCreateTransition.signByPrivateKey(
250+
assetLockPrivateKey,
251+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
252+
);
253+
254+
// TODO(versioning): restore
255+
// @ts-ignore
256+
// const result = await Dpp.stateTransition.validateBasic(
257+
// identityCreateTransition,
258+
// // TODO(v0.24-backport): get rid of this once decided
259+
// // whether we need execution context in wasm bindings
260+
// new StateTransitionExecutionContext(),
261+
// );
262+
263+
// if (!result.isValid()) {
264+
// const messages = result.getErrors().map((error) => error.message);
265+
// throw new Error(`StateTransition is invalid - ${JSON.stringify(messages)}`);
266+
// }
267+
268+
return identityCreateTransition;
269+
}
270+
271+
main();

0 commit comments

Comments
 (0)