Skip to content

Commit 4c4ec40

Browse files
committed
WIP: creates assetLockTx
1 parent 962ad2b commit 4c4ec40

File tree

1 file changed

+297
-0
lines changed

1 file changed

+297
-0
lines changed

demo.js

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

0 commit comments

Comments
 (0)