diff --git a/src/consts.ts b/src/consts.ts
index d1dd9a2c..c5ef1b70 100644
--- a/src/consts.ts
+++ b/src/consts.ts
@@ -51,7 +51,7 @@ export const ALGORITHM_TYPE = {
}
export const TEST_NODE = '139.219.111.50'
-// export const TEST_NODE = '192.168.3.97'
+// export const TEST_NODE = '192.168.50.10'
// export const TEST_NODE = '54.222.182.88'
export const MAIN_NODE = '54.222.182.88'
@@ -63,7 +63,8 @@ export const HTTP_JSON_PORT = '20336'
export const REST_API = {
getBalance: '/api/v1/balance',
- sendRawTx: '/api/v1/transaction'
+ sendRawTx: '/api/v1/transaction',
+ getMerkleProof : '/api/v1/merkleproof' // end with /txHash
}
@@ -73,11 +74,11 @@ export const ONT_NETWORK = {
}
export const TEST_ONT_URL = {
- SOCKET_URL: `ws://${TEST_NODE}:${HTTP_WS_PORT}/`,
+ SOCKET_URL: `ws://${TEST_NODE}:${HTTP_WS_PORT}`,
- RPC_URL: `http://${TEST_NODE}:${HTTP_JSON_PORT}/`,
+ RPC_URL: `http://${TEST_NODE}:${HTTP_JSON_PORT}`,
-REST_URL: `http://${TEST_NODE}:${HTTP_REST_PORT}/`,
+ REST_URL: `http://${TEST_NODE}:${HTTP_REST_PORT}`,
sendRawTxByRestful : `http://${TEST_NODE}:${HTTP_REST_PORT}${REST_API.sendRawTx}`
}
diff --git a/src/core.ts b/src/core.ts
index e4401152..db207ad5 100644
--- a/src/core.ts
+++ b/src/core.ts
@@ -21,13 +21,15 @@ import * as base58 from 'bs58'
import * as ecurve from 'ecurve'
import * as bigInteger from 'bigi'
import { ab2hexstring, hexstring2ab, StringReader, hexstr2str, num2hexstring } from './utils'
-import { ADDR_VERSION, TEST_ONT_URL } from './consts'
+import { ADDR_VERSION, TEST_ONT_URL, REST_API } from './consts'
import * as scrypt from './scrypt'
import {ERROR_CODE} from './error'
import { VmType } from './transaction/vmcode';
-import { buildGetDDOTx, buildRestfulParam, sendRawTxRestfulUrl} from './transaction/transactionBuilder'
+import { buildRestfulParam, sendRawTxRestfulUrl} from './transaction/transactionBuilder'
import axios from 'axios'
import { DDO } from './transaction/ddo'
+import { getPublicKeyStatus, buildGetDDOTx } from './smartcontract/ontidContract'
+import { verifyLeafHashInclusion } from './merkle'
var ec = require('elliptic').ec
var wif = require('wif')
@@ -249,4 +251,113 @@ export function verifyOntidClaim(claim : any) {
}
}
})
+}
+
+const getDDO = (ontid : string, url ?: string) => {
+ let tx = buildGetDDOTx(ontid)
+ let param = buildRestfulParam(tx)
+ url = url || TEST_ONT_URL.REST_URL
+ let requestUrl = sendRawTxRestfulUrl(url , true)
+ return axios.post(requestUrl, param).then((res: any) => {
+ if (res.data.Result && res.data.Result.length > 0) {
+ console.log('ddo hexstr: ' + res.data.Result[0])
+ const ddo = DDO.deserialize(res.data.Result[0])
+ console.log('ddo: ' + JSON.stringify(ddo))
+ return ddo
+ }
+ })
+}
+
+export const getMerkleProof = (txHash : string, url ?: string) => {
+ url = url || TEST_ONT_URL.REST_URL
+ let requestUrl = `${url}${REST_API.getMerkleProof}/${txHash} `
+ return axios.get(requestUrl).then((res:any)=> {
+ console.log('merkle : ' + JSON.stringify(res.data))
+ return res.data.Result
+ })
+}
+
+const getRovocationList = (url : string) => {
+ return axios.get(url).then(res => {
+ return res.data
+ })
+}
+
+const VerifyOntidClaimResult = {
+ CLAIM_NOT_ONCHAIN : 'CLAIM_NOT_ONCHAIN',
+ INVALID_SIGNATURE : 'INVALID_SIGNATURE',
+ PK_IN_REVOKEED : 'PK_IN_REVOKED',
+ EXPIRED_CLAIM : 'EXPIRED_CLAIM',
+ REVOKED_CLAIM : 'REVOKED_CLAIM',
+ VALID_CLAIM : 'VALID_CLAIM'
+}
+
+/*
+*@claim : claim json object
+*@url : the node to send tx, eg: http://192.168.3.111:20334
+*/
+
+export async function verifyOntidClaimAsync(claim : any, url ?: string) {
+ if (!claim.Metadata || !claim.Metadata.Issuer) {
+ throw new Error('Invalid claim.')
+ }
+
+ //verify expiration
+ const expiration = new Date( claim.Metadata.Expires )
+ let d = new Date()
+ if(d > expiration) {
+ return VerifyOntidClaimResult.EXPIRED_CLAIM
+ }
+
+ // verify signature
+ let issuerDid = claim.Metadata.Issuer
+ //issuer is : ONTID#PkId
+ let issuerPkId = issuerDid.substr(issuerDid.indexOf('#') + 1)
+ //pkStatus = { publicKey, status : [IN USE, Revoked] }
+ let pkStatus = await getPublicKeyStatus(issuerDid, issuerPkId, url)
+ if (pkStatus.status === 'Revoked') {
+ return VerifyOntidClaimResult.PK_IN_REVOKEED
+ }
+
+ //verify signature
+ const pk = pkStatus.publicKey.substr(0,4) === '1202' ? pkStatus.publicKey.substr(4) : pkStatus.publicKey
+ //the order of claim's attributes matters.
+ let signature = Object.assign({}, {
+ Context: claim.Context,
+ Id: claim.Id,
+ Content: claim.Content,
+ Metadata: claim.Metadata,
+ })
+
+ let result = verifySignature(JSON.stringify(claim), JSON.stringify(signature), hexstring2ab(pk))
+ if(!result) {
+ return VerifyOntidClaimResult.INVALID_SIGNATURE
+ }
+ if(claim.Proof) {
+ // verify merkle
+ let merkle = claim.Proof
+ const leafHash = merkle.BlockRoot
+ const leafIndex = merkle.BlockHeight
+ const proof = merkle.TargetHashes
+ const rootHash = merkle.CurBlockRoot
+ const treeSize = merkle.CurBlockHeight
+
+ let verifyMerkleResult = verifyLeafHashInclusion(leafHash, leafIndex, proof, rootHash, treeSize)
+ if (!verifyMerkleResult) {
+ return VerifyOntidClaimResult.CLAIM_NOT_ONCHAIN
+ }
+ }
+
+
+ //verify revoke - optional
+ if(claim.Metadata.Revocation) {
+ let url = claim.Metadata.Crl
+ if(claim.Metadata.Revocation === 'RevocationList' && claim.Metadata.Crl) {
+
+ } else if(claim.Metadata.Revocation === 'RevocationUrl') {
+
+ }
+ }
+
+ return VerifyOntidClaimResult.VALID_CLAIM
}
\ No newline at end of file
diff --git a/src/crypto.ts b/src/crypto.ts
index 25cea760..e7c74f2e 100644
--- a/src/crypto.ts
+++ b/src/crypto.ts
@@ -1,3 +1,5 @@
+import { StringReader } from "./utils";
+
export enum SignatureSchema {
SHA224withECDSA = 0,
SHA256withECDSA,
@@ -35,4 +37,34 @@ export class PublicKey {
algorithm: number
curve: number
pk: string
+
+ static deserialize(sr : StringReader) {
+ let pub = new PublicKey()
+ const algorithm = parseInt(sr.read(1), 16)
+ const curve = parseInt(sr.read(1),16)
+ const pk = sr.read(33)
+ pub.algorithm = algorithm
+ pub.curve = curve
+ pub.pk = pk
+ return pub
+ }
+}
+
+export enum PK_STATUS {
+ IN_USE = '01',
+ REVOKED = '00'
+}
+
+export class PublicKeyStatus {
+ pk : PublicKey
+ status : string
+
+ static deserialize(hexstr : string) : PublicKeyStatus {
+ let ps = new PublicKeyStatus()
+ const sr = new StringReader(hexstr)
+ const status = sr.read(1)
+ ps.status = status
+ ps.pk = PublicKey.deserialize(sr)
+ return ps
+ }
}
\ No newline at end of file
diff --git a/src/identity.ts b/src/identity.ts
index 9e91f403..78ccae24 100644
--- a/src/identity.ts
+++ b/src/identity.ts
@@ -21,7 +21,7 @@ import * as scrypt from './scrypt'
import { ab2hexstring, hexstring2ab } from './utils'
import {DEFAULT_ALGORITHM, Algorithm} from './consts'
import {ERROR_CODE} from './error'
-import { buildGetDDOTx, buildRegisterOntidTx, buildRestfulParam } from './transaction/transactionBuilder';
+import { buildRestfulParam } from './transaction/transactionBuilder';
import { checkPrivateKey } from './core';
export class ControlData {
diff --git a/src/merkle.ts b/src/merkle.ts
new file mode 100644
index 00000000..1470a445
--- /dev/null
+++ b/src/merkle.ts
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The ontology Authors
+ * This file is part of The ontology library.
+ *
+ * The ontology is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The ontology is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with The ontology. If not, see .
+ */
+
+import * as cryptoJS from 'crypto-js'
+
+
+/*
+ verify a Merkle Audit Path
+
+ leaf_hash: The hash of the leaf for which the proof was provided.
+ leaf_index: Index of the leaf in the tree.
+ proof: A list of SHA-256 hashes representing the Merkle audit path.
+ tree_size: The size of the tree
+ root_hash: The root hash of the tree
+
+ Returns:
+ true when the proof is valid
+*/
+export function verifyLeafHashInclusion(leafHash : string, leafIndex : number, proof : Array,
+rootHash : string, treeSize : number) {
+ if(treeSize <= leafIndex) {
+ throw new Error('Wrong params, the tree size is smaller than the leaf index')
+ }
+
+ let calculatedRootHash = calculateRootHashFromAuditPath(leafHash, leafIndex, proof, treeSize)
+ if(calculatedRootHash !== rootHash) {
+ return false
+ }
+ return true
+}
+
+export function calculateRootHashFromAuditPath(leafHash : string, leafIndex : number, proof : Array, treeSize : number) {
+ let calculatedHash = leafHash
+ let lastNode = treeSize - 1
+ let pos = 0
+ let pathLen = proof.length
+ while(lastNode > 0) {
+ if(pos > pathLen) {
+ throw new Error('Proof too short');
+ }
+ if(leafIndex % 2 ===1) {
+ calculatedHash = hashChildren(proof[pos], calculatedHash)
+ pos += 1
+ } else if (leafIndex < lastNode ){
+ calculatedHash = hashChildren(calculatedHash, proof[pos])
+ pos += 1
+ }
+ leafIndex = Math.floor( leafIndex / 2 )
+ lastNode = Math.floor( lastNode / 2)
+ }
+ if(pos < pathLen) {
+ throw new Error('Proof too long')
+ }
+ return calculatedHash
+}
+
+export function hashChildren(left : string, right : string) {
+ let data = '01' + left
+ data += right
+ let hex = cryptoJS.enc.Hex.parse(data);
+ return cryptoJS.SHA256(hex).toString();
+}
\ No newline at end of file
diff --git a/src/sdk/index.ts b/src/sdk/index.ts
index 94a8f78a..d0354a39 100644
--- a/src/sdk/index.ts
+++ b/src/sdk/index.ts
@@ -23,7 +23,8 @@ import {Claim, Metadata, Signature} from '../claim'
import * as scrypt from '../scrypt'
import {sendBackResult2Native, EventEmitter, str2hexstr, ab2hexstring} from '../utils'
import * as core from '../core'
-import {buildAddAttributeTx, buildTxParam, buildRpcParam, buildRegisterOntidTx, parseEventNotify, buildGetDDOTx, makeTransferTransaction, buildRestfulParam, sendRawTxRestfulUrl} from '../transaction/transactionBuilder'
+import { buildTxParam, buildRpcParam, parseEventNotify, makeTransferTransaction, buildRestfulParam, sendRawTxRestfulUrl} from '../transaction/transactionBuilder'
+import { buildAddAttributeTx, buildRegisterOntidTx, buildGetDDOTx} from '../smartcontract/ontidContract'
import { ERROR_CODE } from '../error';
import { ONT_NETWORK, TEST_NODE, REST_API, HTTP_REST_PORT, TEST_ONT_URL } from '../consts';
import { encrypt } from '../scrypt';
@@ -364,6 +365,13 @@ export class SDK {
callback && sendBackResult2Native(JSON.stringify(obj), callback)
socket.close()
}
+ if(res.Error !== 0) {
+ let obj = {
+ error : res.Error,
+ result : ''
+ }
+ callback && sendBackResult2Native(JSON.stringify(obj), callback)
+ }
}
txSender.sendTxWithSocket(param, socketCallback)
diff --git a/src/smartcontract/data/IdContract.avm b/src/smartcontract/data/IdContract.avm
new file mode 100644
index 00000000..cd2dc3b3
Binary files /dev/null and b/src/smartcontract/data/IdContract.avm differ
diff --git a/src/smartcontract/data/idContract.abi.ts b/src/smartcontract/data/idContract.abi.ts
index af63ed6d..b476959c 100644
--- a/src/smartcontract/data/idContract.abi.ts
+++ b/src/smartcontract/data/idContract.abi.ts
@@ -1,5 +1,5 @@
export default {
- "hash": "80a45524f3f6a5b98d633e5c7a7458472ec5d625",
+ "hash": "8055b362904715fd84536e754868f4c8d27ca3f6",
"entrypoint": "Main",
"functions":
[
@@ -196,6 +196,47 @@ export default {
],
"returntype": "ByteArray"
},
+ {
+ "name": "GetPublicKeyId",
+ "parameters":
+ [
+ {
+ "name": "ontId",
+ "type": "ByteArray"
+ },
+ {
+ "name": "publicKey",
+ "type": "ByteArray"
+ }
+ ],
+ "returntype": "ByteArray"
+ },
+ {
+ "name": "GetPublicKeyStatus",
+ "parameters":
+ [
+ {
+ "name": "ontId",
+ "type": "ByteArray"
+ },
+ {
+ "name": "pkId",
+ "type": "ByteArray"
+ }
+ ],
+ "returntype": "ByteArray"
+ },
+ {
+ "name": "GetRecovery",
+ "parameters":
+ [
+ {
+ "name": "ontId",
+ "type": "ByteArray"
+ }
+ ],
+ "returntype": "ByteArray"
+ },
{
"name": "GetDDO",
"parameters":
diff --git a/src/smartcontract/data/idContract.avm b/src/smartcontract/data/idContract.avm
deleted file mode 100755
index f1255149..00000000
Binary files a/src/smartcontract/data/idContract.avm and /dev/null differ
diff --git a/src/smartcontract/data/idContract_v0.2.avm b/src/smartcontract/data/idContract_v0.2.avm
deleted file mode 100644
index f7245b07..00000000
Binary files a/src/smartcontract/data/idContract_v0.2.avm and /dev/null differ
diff --git a/src/smartcontract/ontidContract.ts b/src/smartcontract/ontidContract.ts
new file mode 100644
index 00000000..fa2c6548
--- /dev/null
+++ b/src/smartcontract/ontidContract.ts
@@ -0,0 +1,185 @@
+
+import AbiInfo from '../smartcontract/abi/abiInfo'
+import AbiFunction from "../smartcontract/abi/abiFunction";
+import { Parameter, ParameterType } from '../smartcontract/abi/parameter'
+
+import {TEST_ONT_URL} from '../consts'
+import { sendRawTxRestfulUrl } from '../transaction/transactionBuilder';
+import axios from 'axios'
+import * as core from '../core'
+import {ab2hexstring, str2hexstr} from '../utils'
+import {Transaction} from '../transaction/transaction'
+import {makeInvokeTransaction} from '../transaction/transactionBuilder'
+
+import abiJson from '../smartcontract/data/idContract.abi'
+const abiInfo = AbiInfo.parseJson(JSON.stringify(abiJson))
+
+
+export function getPublicKeyStatus(ontid : string, pkId : string, url ?: string) {
+ url = url || TEST_ONT_URL.REST_URL
+ let requestUrl = sendRawTxRestfulUrl(url, true)
+ let param = ''
+ return axios.post(url, param).then(res => {
+ return res.data
+ })
+}
+
+export function buildRegisterOntidTx(ontid: string, privateKey: string) {
+ let publicKey = ab2hexstring(core.getPublicKey(privateKey, true))
+ if (ontid.substr(0, 3) == 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ console.log("Register ", ontid)
+ let f = abiInfo.getFunction('RegIdWithPublicKey')
+
+ let name1 = f.parameters[0].getName(),
+ type1 = ParameterType.ByteArray
+ let p1 = new Parameter(name1, type1, ontid)
+
+
+ let name2 = f.parameters[1].getName(),
+ type2 = ParameterType.ByteArray
+ //algorithm&curve
+ publicKey = '1202' + publicKey
+
+ let p2 = new Parameter(name2, type2, publicKey)
+
+ f.setParamsValue(p1, p2)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+
+ return tx
+}
+
+//all parameters shuld be hex string
+export function buildAddAttributeTx(path: string, value: string, type: string, ontid: string, privateKey: string) {
+ let publicKey = ab2hexstring(core.getPublicKey(privateKey, true))
+ //algorithm&curve
+ publicKey = '1202' + publicKey
+ let f = abiInfo.getFunction('AddAttribute')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, path)
+ let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, type)
+ let p4 = new Parameter(f.parameters[3].getName(), ParameterType.ByteArray, value)
+ let p5 = new Parameter(f.parameters[4].getName(), ParameterType.ByteArray, publicKey)
+
+ f.setParamsValue(p1, p2, p3, p4, p5)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildGetDDOTx(ontid: string) {
+ let f = abiInfo.getFunction('GetDDO')
+ if (ontid.substr(0, 3) == 'did') {
+ ontid = str2hexstr(ontid)
+ }
+
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let nonce = ab2hexstring(core.generateRandomArray(10))
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, nonce)
+ f.setParamsValue(p1, p2)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash())
+
+ return tx
+}
+
+export function buildAddPKTx(ontid : string, newPk : string, sender : string, privateKey : string) {
+ let f = abiInfo.getFunction('AddKey')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ newPk = '1202' + newPk
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, newPk)
+ sender = '1202' + sender
+ let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, sender)
+
+ f.setParamsValue(p1, p2, p3)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildGetPublicKeysTx(ontid : string, privateKey : string) {
+ let f = abiInfo.getFunction('GetPublicKeys')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ f.setParamsValue(p1)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildRemovePkTx(ontid : string, pk2Remove : string, sender : string, privateKey : string) {
+ let f = abiInfo.getFunction('RemoveKey')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ pk2Remove = '1202' + pk2Remove
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, pk2Remove)
+ sender = '1202' + sender
+ let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, sender)
+
+ f.setParamsValue(p1, p2, p3)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildAddRecoveryTx(ontid : string, recovery : string, publicKey : string, privateKey : string) {
+ let f = abiInfo.getFunction('AddRecovery')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, recovery)
+ publicKey = '1202' + publicKey
+ let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, publicKey)
+
+ f.setParamsValue(p1, p2, p3)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildChangeRecoveryTx(ontid : string, newrecovery : string, oldrecovery : string, privateKey : string) {
+ let f = abiInfo.getFunction('ChangeRecovery')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, newrecovery)
+ let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, oldrecovery)
+
+ f.setParamsValue(p1, p2, p3)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildGetPublicKeyStatusTx(ontid: string, pkId: string, privateKey?: string) {
+ let f = abiInfo.getFunction('GetPublicKeyStatus')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, pkId)
+
+ f.setParamsValue(p1, p2)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
+
+export function buildGetPublicKeyIdTx(ontid: string, pk: string, privateKey ?: string) {
+ let f = abiInfo.getFunction('GetPublicKeyId')
+ if (ontid.substr(0, 3) === 'did') {
+ ontid = str2hexstr(ontid)
+ }
+ pk = '1202' + pk
+ let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
+ let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, pk)
+
+ f.setParamsValue(p1, p2)
+ let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
+ return tx
+}
\ No newline at end of file
diff --git a/src/transaction/ddo.ts b/src/transaction/ddo.ts
index e2ed5957..95232cf8 100644
--- a/src/transaction/ddo.ts
+++ b/src/transaction/ddo.ts
@@ -79,8 +79,7 @@ export class DDO {
//recovery
const recoveryTotalLen = parseInt(ss.read(4), 16)
if(recoveryTotalLen > 0 ) {
- const recLen = parseInt(ss.read(4), 16)
- const recovery = hexstr2str(ss.read(recLen))
+ const recovery = ss.read(recoveryTotalLen)
ddo.recovery = recovery
}
diff --git a/src/transaction/transactionBuilder.ts b/src/transaction/transactionBuilder.ts
index 38b9fef9..09de5dd7 100644
--- a/src/transaction/transactionBuilder.ts
+++ b/src/transaction/transactionBuilder.ts
@@ -159,7 +159,7 @@ export const pushHexString = (param : string) => {
}
-//params is like [functionName, param1, param2...]
+//params is like [param1, param2...]
export const buildSmartContractParam = (functionName : string, params : Array) => {
let result = ''
for (let i= params.length -1; i > -1; i--) {
@@ -293,72 +293,12 @@ export function buildTxParam (tx : Transaction, is_pre_exec : boolean = false) {
return JSON.stringify(Object.assign({}, Default_params, { Data: serialized }, op))
}
-//all parameters shuld be hex string
-export function buildAddAttributeTx (path : string, value : string, type: string, ontid : string, privateKey : string) {
- let publicKey = ab2hexstring(core.getPublicKey(privateKey, true))
- //algorithm&curve
- publicKey = '1202' + publicKey
- let f = abiInfo.getFunction('AddAttribute')
- if(ontid.substr(0,3) === 'did') {
- ontid = str2hexstr(ontid)
- }
- let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
- let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, path)
- let p3 = new Parameter(f.parameters[2].getName(), ParameterType.ByteArray, type)
- let p4 = new Parameter(f.parameters[3].getName(), ParameterType.ByteArray, value)
- let p5 = new Parameter(f.parameters[4].getName(), ParameterType.ByteArray, publicKey)
-
- f.setParamsValue(p1, p2, p3, p4, p5)
- let tx = makeInvokeTransaction( f,abiInfo.getHash(), privateKey)
- return tx
-}
-
-export function buildRegisterOntidTx (ontid: string, privateKey: string) {
- let publicKey = ab2hexstring(core.getPublicKey(privateKey, true))
- if (ontid.substr(0, 3) == 'did') {
- ontid = str2hexstr(ontid)
- }
- console.log("Register ", ontid)
- let f = abiInfo.getFunction('RegIdWithPublicKey')
-
- let name1 = f.parameters[0].getName(),
- type1 = ParameterType.ByteArray
- let p1 = new Parameter(name1, type1, ontid)
-
-
- let name2 = f.parameters[1].getName(),
- type2 = ParameterType.ByteArray
- //algorithm&curve
- publicKey = '1202' + publicKey
-
- let p2 = new Parameter(name2, type2, publicKey)
-
- f.setParamsValue(p1, p2)
- let tx = makeInvokeTransaction( f, abiInfo.getHash(), privateKey)
-
- return tx
-}
-
-export function buildGetDDOTx(ontid : string) {
- let f = abiInfo.getFunction('GetDDO')
- if (ontid.substr(0, 3) == 'did') {
- ontid = str2hexstr(ontid)
- }
-
- let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
- let nonce = ab2hexstring( core.generateRandomArray(10) )
- let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, nonce)
- f.setParamsValue(p1,p2)
- let tx = makeInvokeTransaction( f, abiInfo.getHash(), '')
-
- return tx
-}
//{"jsonrpc": "2.0", "method": "sendrawtransaction", "params": ["raw transactioin in hex"], "id": 0}
-export function buildRpcParam(tx : any) {
+export function buildRpcParam(tx : any, method ?: string) {
let param = tx.serialize()
let result = {
"jsonrpc": "2.0",
- "method": "sendrawtransaction",
+ "method": method || "sendrawtransaction",
"params": [param],
"id": 10
}
diff --git a/src/transaction/txSender.ts b/src/transaction/txSender.ts
index b52560fe..c170fcb0 100644
--- a/src/transaction/txSender.ts
+++ b/src/transaction/txSender.ts
@@ -19,6 +19,7 @@
import {ONT_NETWORK, MAIN_ONT_URL, TEST_ONT_URL} from '../consts'
import {Transaction} from './transaction'
import axios from 'axios'
+import { ERROR_CODE } from '../error';
var WebSocket : any
if(typeof window != 'undefined' && (window as any).WebSocket){
@@ -57,6 +58,17 @@ export default class TxSender {
socket.onerror = (event : any) => {
//no server or server is stopped
console.log(event)
+ let res
+ if (typeof event.data === 'string') {
+ res = JSON.parse(event.data)
+ } else {
+ res = event.data
+ }
+ res.Error = ERROR_CODE.NETWORK_ERROR
+ //pass socket to let caller decide when to close the it.
+ if (callback) {
+ callback(res, socket)
+ }
socket.close()
}
}
diff --git a/test/claim.test.ts b/test/claim.test.ts
index 2f9b919b..7c61a01c 100644
--- a/test/claim.test.ts
+++ b/test/claim.test.ts
@@ -67,7 +67,7 @@ describe('test claim', () => {
Context : claim.Context,
Id : claim.Id,
Content : claim.Content,
- Metadata : claim.Metadata,
+ Metadata : claim.Metadata
})
let result = verifySignature(JSON.stringify(data), claim.Signature.Value, publicKey)
expect(result).toBeTruthy()
diff --git a/test/core.test.ts b/test/core.test.ts
index 1aa91d5a..f61994c3 100644
--- a/test/core.test.ts
+++ b/test/core.test.ts
@@ -21,7 +21,7 @@ import * as core from '../src/core'
import * as utils from '../src/utils'
import * as scrypt from '../src/scrypt'
import { ab2hexstring } from '../src/utils';
-import { verifySignature } from '../src/core';
+import { verifySignature, getMerkleProof } from '../src/core';
describe('test core', ()=>{
@@ -32,29 +32,29 @@ describe('test core', ()=>{
privateKey = utils.ab2hexstring( core.generatePrivateKey() )
})
- // test('test getWIFFromPrivateKey', () => {
- // wifKey = core.getWIFFromPrivateKey(privateKey)
- // expect(wifKey).toBeDefined()
- // })
+ test('test getWIFFromPrivateKey', () => {
+ wifKey = core.getWIFFromPrivateKey(privateKey)
+ expect(wifKey).toBeDefined()
+ })
- // test('test getPrivateKeyFromWIF', () => {
- // let key = core.getPrivateKeyFromWIF(wifKey)
- // expect(key).toEqual(privateKey)
- // })
+ test('test getPrivateKeyFromWIF', () => {
+ let key = core.getPrivateKeyFromWIF(wifKey)
+ expect(key).toEqual(privateKey)
+ })
- // test('get public key', () => {
- // let pkBuffer = core.getPublicKey(privateKey, true)
- // let pk = utils.ab2hexstring(pkBuffer)
- // console.log('get pk: ' + pk)
- // expect(pk).toBeDefined()
- // })
+ test('get public key', () => {
+ let pkBuffer = core.getPublicKey(privateKey, true)
+ let pk = utils.ab2hexstring(pkBuffer)
+ console.log('get pk: ' + pk)
+ expect(pk).toBeDefined()
+ })
- // test('encrypt private key', () => {
- // let privateKey = 'b02304dcb35bc9a055147f07b2a3291db4ac52f664ec38b436470c98db4200d9'
- // let wif = core.getWIFFromPrivateKey(privateKey)
- // let encrypt = scrypt.encrypt(wif, '123456')
- // console.log('encrypt: '+ encrypt)
- // })
+ test('encrypt private key', () => {
+ let privateKey = 'b02304dcb35bc9a055147f07b2a3291db4ac52f664ec38b436470c98db4200d9'
+ let wif = core.getWIFFromPrivateKey(privateKey)
+ let encrypt = scrypt.encrypt(wif, '123456')
+ console.log('encrypt: '+ encrypt)
+ })
test('sign and verify', () => {
let privateKey = core.generatePrivateKeyStr()
diff --git a/test/deployCodeTx.test.ts b/test/deployCodeTx.test.ts
index 41389ed1..6e0d7244 100644
--- a/test/deployCodeTx.test.ts
+++ b/test/deployCodeTx.test.ts
@@ -34,7 +34,7 @@ import json from '../src/smartcontract/data/idContract.abi'
import { VmCode, VmType } from '../src/transaction/vmcode';
var fs = require('fs')
-let avm = fs.readFileSync('/Users/mickeywang/Desktop/Workspace/ont-sdk-ts-local/src/smartcontract/data/idContract.avm')
+let avm = fs.readFileSync('/Volumes/Workspace/ontio/ontology-ts-sdk/src/smartcontract/data/IdContract.avm')
var avmCode = ab2hexstring(avm)
var privateKey = '7c47df9664e7db85c1308c080f398400cb24283f5d922e76b478b5429e821b93'
@@ -111,9 +111,12 @@ const getContract = () => {
// let scriptHash = '8046031450d43928654f50dcd50646331bb49e1a'
- let url = `${TEST_ONT_URL.REST_URL}api/v1/contract/${scriptHash}`
+ let url = `${TEST_ONT_URL.REST_URL}/api/v1/contract/${scriptHash}`
+ console.log('url : '+ url)
axios.get(url).then((res)=>{
console.log(res.data)
+ }).catch(err => {
+ console.log(err)
})
}
diff --git a/test/merkle.test.ts b/test/merkle.test.ts
new file mode 100644
index 00000000..0521e9b8
--- /dev/null
+++ b/test/merkle.test.ts
@@ -0,0 +1,35 @@
+import {verifyLeafHashInclusion} from '../src/merkle'
+
+test('test verify leaf in tree', () => {
+ const merkle = {
+ "Type": "MerkleProof",
+ "TransactionsRoot": "cc61e9484b603f6a29ccca0847977147cf5d1f36c749b74361de04f79554c7c4",
+ "BlockHeight": 0,
+ "CurBlockRoot": "815e20bda34d3a26450cc45726b34b143e9c5391642c340e25aceb76d28d2c88",
+ "CurBlockHeight": 4172,
+ "TargetHashes": [
+ "8efa212233346badd344d0cb926f0b9d62b0eac077c9299c97c1cd4c5fec1450",
+ "3daa4b24d4762c8ab20cccc9fe1ad4ec2926545194d12cd0b13b58dcddf47afd",
+ "8cb9c7a58049f809485fbf2cc4bed21966195603748643383349a63c2b04bd07",
+ "1178ee5780a0d3c795d46f145033302664418b15aa016aee1e6a9bef958801fd",
+ "6f9a4bf07ba2f05b707b497a00d376d9158b8e7d852395ff4a5e82e23e611cc7",
+ "78f88b81b660f67e901fbe3e5c274be0e77e28712f334965d9f3af7ed6f4f31a",
+ "6d18e1c63641485ef692edbe69b516bdb5b46b7123e68e4f27dda161860b8748",
+ "49efca7304446c69bc7de684f76bac6d9b7ed77279166c4438da99f65a8460d2",
+ "d0ee3b8f10e0354ba6b6c2ef0d831e75bd4246b23a9c79451061eef749196167",
+ "80b2ca8c07b4a701cb5ae14a5c171bc8be9a6a88b6417953908cafd1ec99d83a",
+ "4e3d005c338414583a0154263b5a62a7be4e2d071430eb8ead7ca0cf543d32b9",
+ "b411acb7ac430dca5758b19bce9063cba0ec3d58096a48544f2745df043ef7f7",
+ "2e4b0a10b6478bdeea059eb19c1425ab226b0a41b35aad9bcf911e24b4da4906"
+ ]
+ }
+
+ const leafHash = merkle.TransactionsRoot
+ const leafIndex = merkle.BlockHeight
+ const proof = merkle.TargetHashes
+ const rootHash = merkle.CurBlockRoot
+ const treeSize = merkle.CurBlockHeight
+ let result = verifyLeafHashInclusion(leafHash, leafIndex, proof, rootHash, treeSize)
+ console.log(result)
+ expect(result).toBeTruthy()
+})
\ No newline at end of file
diff --git a/test/tx.node.ts b/test/tx.node.ts
index 92bb9a21..9d9bed5d 100644
--- a/test/tx.node.ts
+++ b/test/tx.node.ts
@@ -16,8 +16,9 @@
* along with The ontology. If not, see .
*/
-import { makeInvokeTransaction , parseEventNotify, buildAddAttributeTx, buildGetDDOTx,
- buildRpcParam, buildRegisterOntidTx, buildTxParam, buildRestfulParam, sendRawTxRestfulUrl } from '../src/transaction/transactionBuilder'
+import { makeInvokeTransaction , parseEventNotify,
+ buildRpcParam, buildTxParam, buildRestfulParam, sendRawTxRestfulUrl } from '../src/transaction/transactionBuilder'
+import {buildAddAttributeTx, buildGetDDOTx, buildRegisterOntidTx, buildAddPKTx, buildGetPublicKeysTx, buildRemovePkTx, buildAddRecoveryTx, buildChangeRecoveryTx, buildGetPublicKeyIdTx, buildGetPublicKeyStatusTx} from '../src/smartcontract/ontidContract'
import {Transaction} from '../src/transaction/transaction'
import InvokeCode from '../src/transaction/payload/invokeCode'
import { Identity } from '../src/identity'
@@ -33,6 +34,7 @@ import { TEST_ONT_URL} from '../src/consts'
import { getHash } from '../src/core';
import TxSender from '../src/transaction/txSender'
import axios from 'axios'
+import { PublicKeyStatus } from '../src/crypto';
const codeHash = '80e7d2fc22c24c466f44c7688569cc6e6d6c6f92'
@@ -53,6 +55,7 @@ var pk2: string
var ontid: string
var oldrecovery : string
var newrecovery : string
+var pkId : string
var abiInfo: AbiInfo
var identity: Identity
@@ -63,12 +66,13 @@ abiInfo = AbiInfo.parseJson(JSON.stringify(json2))
// console.log('publick key: ' + publicKey)
privateKey = '7c47df9664e7db85c1308c080f398400cb24283f5d922e76b478b5429e821b93'
-publicKey = ab2hexstring(core.getPublicKey(privateKey, false))
-let publicKey2 = ab2hexstring(core.getPublicKey(privateKey, true))
+publicKey = ab2hexstring(core.getPublicKey(privateKey, true))
+pkId = ''
+// let publicKey2 = ab2hexstring(core.getPublicKey(privateKey, true))
-var pkPoint = core.getPublicKeyPoint(privateKey)
-console.log('pk false: '+ publicKey)
-console.log('pk true: ' + publicKey2)
+// var pkPoint = core.getPublicKeyPoint(privateKey)
+// console.log('pk false: '+ publicKey)
+// console.log('pk true: ' + publicKey2)
@@ -237,91 +241,66 @@ const testAddAttribute = () => {
})
}
+const testGetPublicKeyId = () => {
+ let tx = buildGetPublicKeyIdTx(ontid, publicKey)
+ let param = buildRestfulParam(tx)
+ console.log(param)
+ let url = sendRawTxRestfulUrl(TEST_ONT_URL.REST_URL, true)
+ console.log(url)
+ axios.post(url, param).then((res) => {
+ console.log(res.data)
+ }).catch(err => {
+ console.log(err)
+ })
+}
-const testAddPK = () => {
- let f = abiInfo.getFunction('AddKey')
-
- let p1 = new Parameter('id', ParameterType.ByteArray, ontid)
- let p2 = new Parameter('newpubkey', ParameterType.ByteArray, pk2)
- let p3 = new Parameter('sender', ParameterType.ByteArray, publicKey)
-
- f.setParamsValue(p1, p2, p3)
- let tx = makeInvokeTransaction( f, abiInfo.getHash(), privateKey)
+const testGetPublicKeyStatus = () => {
+ let tx = buildGetPublicKeyStatusTx(ontid, '01')
+ let param = buildRestfulParam(tx)
+ let url = sendRawTxRestfulUrl(TEST_ONT_URL.REST_URL, true)
+ axios.post(url, param).then((res) => {
+ console.log(res.data)
+ let ps = PublicKeyStatus.deserialize(res.data.Result[0])
+ console.log(ps)
+ }).catch(err => {
+ console.log(err)
+ })
+}
- let serialized = tx.serialize()
- // console.log('add pk tx: ' + serialized)
-
- let param = JSON.stringify(Object.assign({}, Default_params, { Data: serialized }))
+const testAddPK = () => {
+ let tx = buildAddPKTx(ontid, pk2, publicKey, privateKey)
+ let param = buildTxParam(tx)
console.log('add pk param: ' + param)
sendTx(param)
}
const testGetPublicKeys = () => {
- let f = abiInfo.getFunction('GetPublicKeys')
- let p1 = new Parameter('id', ParameterType.ByteArray, ontid)
- f.setParamsValue(p1)
- let tx = makeInvokeTransaction(f, abiInfo.getHash(),privateKey)
- let serialized = tx.serialize()
-
- let param = JSON.stringify(Object.assign({}, Default_params, {Data : serialized}))
- sendTx(param)
+ let tx = buildGetPublicKeysTx(ontid, privateKey)
+ // let param = buildTxParam(tx)
+ // sendTx(param)
+ let param = buildRestfulParam(tx)
+ let url = sendRawTxRestfulUrl(TEST_ONT_URL.REST_URL, true)
+ axios.post(url, param).then(res => {
+ console.log(res.data)
+ })
}
const testRemovePK = () => {
- let f = abiInfo.getFunction('RemoveKey')
-
- let p1 = new Parameter('id', ParameterType.ByteArray, ontid)
- let p2 = new Parameter('oldpubkey', ParameterType.ByteArray, pk2)
- let p3 = new Parameter('sender', ParameterType.ByteArray, publicKey)
-
- f.setParamsValue(p1, p2, p3)
- let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
-
- let serialized = tx.serialize()
-
- // let hashed = core.getHash(serialized)
- // console.log('remove pk tx: ' + serialized)
- // console.log('hashed:' + hashed)
-
- let param = JSON.stringify(Object.assign({}, Default_params, { Data: serialized }))
+ let tx = buildRemovePkTx(ontid, pk2, publicKey, privateKey)
+ let param = buildTxParam(tx)
console.log('remove pk param: ' + param)
sendTx(param)
}
const testAddRecovery = () => {
- let f = abiInfo.getFunction('AddRecovery')
-
- let p1 = new Parameter('id', ParameterType.ByteArray, ontid)
- let p2 = new Parameter('recovery', ParameterType.ByteArray, oldrecovery)
- let p3 = new Parameter('pk', ParameterType.ByteArray, publicKey)
-
- f.setParamsValue(p1, p2, p3)
- let tx = makeInvokeTransaction(f, abiInfo.getHash(),privateKey)
-
- let serialized = tx.serialize()
-
- // let hashed = core.getHash(serialized)
- // console.log('remove pk tx: ' + serialized)
- // console.log('hashed:' + hashed)
-
- let param = JSON.stringify(Object.assign({}, Default_params, { Data: serialized }))
- console.log('change recovery param: ' + param)
+ let tx = buildAddRecoveryTx(ontid, oldrecovery, publicKey, privateKey)
+ let param = buildTxParam(tx)
sendTx(param)
}
const testChangeRecovery = () => {
- let f = abiInfo.getFunction('ChangeRecovery')
-
- let p1 = new Parameter('id', ParameterType.ByteArray, ontid)
- let p2 = new Parameter('newrecovery', ParameterType.ByteArray, newrecovery)
- let p3 = new Parameter('recovery', ParameterType.ByteArray, oldrecovery)
-
- f.setParamsValue(p1, p2, p3)
- let tx = makeInvokeTransaction(f, abiInfo.getHash(), privateKey)
-
- let serialized = tx.serialize()
-
- let param = JSON.stringify(Object.assign({}, Default_params, { Data: serialized }))
+ let tx = buildChangeRecoveryTx(ontid, newrecovery, oldrecovery, privateKey)
+ let param = buildTxParam(tx)
console.log('change recovery param: ' + param)
sendTx(param)
}
@@ -365,7 +344,7 @@ const testVerifyOntidClaim = () => {
// testAddAttribute()
-testDDOTx()
+// testDDOTx()
// testVerifyOntidClaim()
@@ -383,4 +362,6 @@ testDDOTx()
// testChangeRecovery()
+// testGetPublicKeyId()
+testGetPublicKeyStatus()
\ No newline at end of file