ืืชืืืืช 2017, ืืชืืื ื ืืืฆืืจ ืืกื ื'ืจ ืืืืืงืฆ'ืืื [ืฉื ืืงืืฉืืจ ื ืืฆืืื ืืคืจืืคืื] ืขื ืืื ืืืื ืืืชืจืื ืืช ืขื ืคื ื ืฉืืืื P2P ืงืืืกืืื.
ื ืขืื 2.5
ืฉื ื, ืืืฆืืื ื ืืืฉืจ ืืช ืืจืขืืื ืฉืื ื: ืืืฉืืื ืืกื ื'ืจ ืืืื ืื ืืขืช ืขืืืจ iOS, Web PWA, Windows, GNU/Linux, Mac OS ืืื ืืจืืืื.
ืืืื ื ืกืคืจ ืืื ืืื ืขืืื ืฉืืื ืืืืืงืฆ'ืืื ืืืืฆื ืืืฉืืื ืืงืื ืืืืืื ืืขืืื ืขื ื-API ืฉืื.
ืจืฆืื ื ืฉื-blockchain ืืคืชืืจ ืืช ืืขืืืช ืืืืืื ืืืคืจืืืืช ืฉื ืฉืืืื P2P ืงืืืกืืื:
- ืืืืฆื ืืืช ืืืฆืืจืช ืืฉืืื - ืืื ืืืคืื ืื ืื ืืืืืื, ืืื ืืืฉื ืืกืคืจื ืืชืืืืช ืื ืืืงืืืื ืืืืืืจืคืืื.
- ืื ื ืืฉืื ืืขืืื ืืื ื ืืืฆืจืื ืงืฉืจืื ืืฉืืจืื; ืื ืืชืงืฉืืจืช ืืชืจืืฉืช ืืืืฆืขืืช ืืขืจืืช ืืืืืจืช ืฉื ืฆืืชืื. ืืชืืืืช ื-IP ืฉื ืืืฉืชืืฉืื ืืื ื ื ืืืฉืืช ืื ืืื.
- ืื ืืืืืขืืช ืืืฆืคื ืืช ืืงืฆื ืืงืฆื curve25519xsalsa20poly1305. ื ืจืื ืฉืื ืื ืืคืชืืข ืืฃ ืืื, ืืื ืงืื ืืืงืืจ ืฉืื ื ืคืชืื.
- ืืชืงืคืช MITM ืืื ื ื ืืืืช - ืื ืืืืขื ืืื ืขืกืงื ืืืชืืื ืขื ืืื Ed25519 EdDSA.
- ืืืืืขื ืืกืชืืืืช ืืืืืง ืืฉืื. ืขืงืืืืช ื
timestamp
ืืชื ืื ืืืื ืืชืงื ืืช ืืืกืืืืช, ืืืื ืืช ืกืืจ ืืืืืขืืช. - "ืื ืืืจืชื ืืช ืื" ืื ืืขืืื ืขื ืืืืขืืช ืืืืืงืฆ'ืืื.
- ืืื ืืื ื ืืจืืื ืฉืขืืฉื ืืืืงืืช ืขื "ืืืชื ืืืืช" ืฉื ืืืืขื. ืื ื ืขืฉื ืขื ืืื ืืขืจืืช ืืืืืจืช ืฉื ืฆืืชืื ืืืืืกืกืช ืขื ืงืื ืฆื ืืืก, ืืืื ืืืขืืืช ืืืฉืชืืฉืื.
- ืืืกืจ ืืคืฉืจืืช ืืฆื ืืืจื - ืื ื ืืชื ืืืกืื ืืฉืืื ืืช ืืื ื ืืชื ืืืืืง ืืืืขืืช.
- Blockchain 2FA ืืื ืืืืคื ื-2FA ืืืืื ืื ืืืืฆืขืืช SMS,
ืืจืก ืืจืื ืืจืืืืช. - ืืืืืืช ืืงืื ืืช ืื ืืฉืืืืช ืฉืื ืืื ืืืฉืืจ ืืื ืขืช ืคืืจืืฉื ืฉืืื ื ืฆืจืื ืืืืกื ืฉืืืืช ืืืืคื ืืงืืื ืืื.
- ืืืฉืืจ ืืกืืจืช ืืืืขื. ืื ืืืืฉืืจ ืฉื ืืืฉืชืืฉ, ืืื ืืจืฉืช. ืืขืืงืจื ืฉื ืืืจ, ืืื ืืืฉืืจ ืืืืืืชื ืฉื ืื ืืขื ืืงืจืื ืืช ืืืืืขื ืฉืื. ืืืื ืชืืื ื ืฉืืืืฉืืช ืืฉืืืืช ืืชืจืืืช ืงืจืืืืืช.
ืืชืจืื ืืช ืืืืืงืฆ'ืืื ืืืืืื ืื ืืื ืืืจืฆืื ืืืืงื ืขื ืืืืขืืช ืืงืจืืคืื Ethereum, Dogecoin, Lisk, Dash, Bitcoin (ืื ืขืืืื ืืชืืืื) ืืืืืืช ืฉืืืืช ืืกืืืื ืื ืืฆ'ืืืื. ืืคืืื ืืฆืจื ื ืืืืืฃ ืงืจืืคืื ืืืื ื.
ืืื - ืืื ืืื ืขืืื.
ืืืืขื ืืื ืขืกืงื
ืืืื ืืืจ ืจืืืืื ืืื ืฉืขืกืงืืืช ืืืืืงืฆ'ืืื ืืขืืืจืืช ืืกืืืื ืื (ืืืืขืืช) ืืืฉืชืืฉ ืืื ืืืืจ. ืืื ืืืืงืืื. ืืฆืจื ื ืกืื ืืืืื ืฉื ืขืกืงื ืืืขืืจืช ืืืืขืืช.
ืืื ืืฉืืื ืืืืขื ืืืกื ื'ืจ ืืืืืงืฆ'ืืื, ืขืืื ืืขืืืจ ืืกืคืจ ืฉืืืื:
- ืืฆืคื ืช ืืงืกื ืืืืขื
- ืืื ืก ืืงืกื ืฆืืคื ืืขืกืงื
- ืืชืื ืขื ืืขืกืงื
- ืฉืื ืขืกืงื ืืื ืฆืืืช ืจืฉืช
- ืืขืจืืช ืืืืืจืช ืฉื ืฆืืชืื ืงืืืขืช ืืช ื"ืืืชื ืืืืช" ืฉื ืืืืขื
- ืื ืืื ืชืงืื, ืืขืกืงื ืขื ืืืืืขื ื ืืืืช ืืืืืง ืืื
- ืื ืืขื ืืืืืจ ืืช ืขืกืงืช ืืืืืขื ืืืคืขื ื
ืฉืืืื 1-3 ื-7 ืืืืฆืขืื ืืืืคื ืืงืืื ืขื ืืืงืื, ืืฉืืืื 5-6 ืืืืฆืขืื ืขื ืืืืจืืื.
ืืฆืคื ืช ืืืืขืืช
ืืืืืขื ืืืฆืคื ืช ืืืคืชื ืืคืจืื ืฉื ืืฉืืื ืืืืคืชื ืืฆืืืืจื ืฉื ืื ืืขื. ื ืืงื ืืช ืืืคืชื ืืฆืืืืจื ืืืจืฉืช, ืื ืืฉื ืื ืืฉ ืืืชืื ืืช ืืืฉืืื ืฉื ืื ืืขื, ืืืืืจ ืืืฆืข ืขืกืงื ืืืช ืืคืืืช. ืืชื ืืืื ืืืฉืชืืฉ ืืืงืฉืช REST GET /api/accounts/getPublicKey?address={ADAMANT address}
, ืืืขืช ืืขืื ืช ืฆ'ืืืื, ืืืคืชืืืช ืืฆืืืืจืืื ืฉื ืื ื ืืฉืื ืืืจ ืืืื ืืืื ืื.
ืืืกื ื'ืจ ืืฆืคืื ืืืืขืืช ืืืืฆืขืืช ืืืืืืจืืชื curve25519xsalsa20poly1305 (
ืื ื ืืืืื ื-JavaScript:
/**
* Encodes a text message for sending to ADM
* @param {string} msg message to encode
* @param {*} recipientPublicKey recipient's public key
* @param {*} privateKey our private key
* @returns {{message: string, nonce: string}}
*/
adamant.encodeMessage = function (msg, recipientPublicKey, privateKey) {
const nonce = Buffer.allocUnsafe(24)
sodium.randombytes(nonce)
if (typeof recipientPublicKey === 'string') {
recipientPublicKey = hexToBytes(recipientPublicKey)
}
const plainText = Buffer.from(msg)
const DHPublicKey = ed2curve.convertPublicKey(recipientPublicKey)
const DHSecretKey = ed2curve.convertSecretKey(privateKey)
const encrypted = nacl.box(plainText, nonce, DHPublicKey, DHSecretKey)
return {
message: bytesToHex(encrypted),
nonce: bytesToHex(nonce)
}
}
ืืฆืืจืช ืขืกืงื ืขื ืืืืขื
ืืขืกืงื ืืฉ ืืช ืืืื ื ืืืืื ืืื:
{
"id": "15161295239237781653",
"height": 7585271,
"blockId": "16391508373936326027",
"type": 8,
"block_timestamp": 45182260,
"timestamp": 45182254,
"senderPublicKey": "bd39cc708499ae91b937083463fce5e0668c2b37e78df28f69d132fce51d49ed",
"senderId": "U16023712506749300952",
"recipientId": "U17653312780572073341",
"recipientPublicKey": "23d27f616e304ef2046a60b762683b8dabebe0d8fc26e5ecdb1d5f3d291dbe21",
"amount": 204921300000000,
"fee": 50000000,
"signature": "3c8e551f60fedb81e52835c69e8b158eb1b8b3c89a04d3df5adc0d99017ffbcb06a7b16ad76d519f80df019c930960317a67e8d18ab1e85e575c9470000cf607",
"signatures": [],
"confirmations": 3660548,
"asset": {}
}
ืขืืืจ ืขืกืงืช ืืืืขื, ืืืืจ ืืืฉืื ืืืืชืจ ืืื asset
- ืขืืื ืืืงื ืืืืขื ืืืืืืืงื chat
ืขื ืืื ื:
message
- ืฉืืืจ ืืช ืืืืืขื ืืืืฆืคื ืชown_message
- ืืtype
- ืกืื ืืืืขื
ืื ืืืืืขืืช ืืืืืงืืช ืืกืืืื. ืืขืืงืจื ืฉื ืืืจ, ืืคืจืืืจ type
ืืืืจ ืื ืืื ืืืืื message
. ืืชื ืืืื ืืฉืืื ืจืง ืืืืขืช ืืงืกื, ืื ืฉืืชื ืืืื ืืฉืืื ืืืืืืงื ืขื ืืืจืื ืืขื ืืื ืื ืืคื ืื - ืืืฉื, ืื ืืฉืืื ืืืฆืข ืืขืืจืืช ืฉื ืืืืขืืช ืงืจืืคืืืืจืคืืื ืืฆ'ืืืื.
ืืชืืฆืื ืืื, ืื ื ืืืฆืจืื ืขืกืงื:
{
"transaction": {
"type": 8,
"amount": 0,
"senderId": "U12499126640447739963",
"senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
"asset": {
"chat": {
"message": "cb682accceef92d7cddaaddb787d1184ab5428",
"own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
"type": 1
}
},
"recipientId": "U15677078342684640219",
"timestamp": 63228087,
"signature": "ััั ะฑัะดะตั ะฟะพะดะฟะธัั"
}
}
ืืชืืืช ืขืกืงื
ืืื ืืืืืื ืฉืืืื ืืืืืื ืืืืชื ืืืืช ืฉื ืืฉืืื ืืื ืืขื, ืืืื ืืฉืืืื ืืชืืื ืืืืืขื, ืืขืกืงื ื ืืชืืช. ืืชืืื ืืืืืืืืช ืืืคืฉืจืช ืืืืช ืืช ืืืืชื ืืืืช ืฉื ืขืกืงื ืืืืฆืขืืช ืืคืชื ืฆืืืืจื - ืืื ืฆืืจื ืืืคืชื ืคืจืื ืืฉื ืื.
ืืื ืืืชืืื ืขืฆืื ืืชืืฆืขืช ืืืืฆืขืืช ืืืคืชื ืืคืจืื:
ืืืืืืจืื ืืจืื ืฉืชืืืื ืื ื ืืฉืืืืื ืืช ืืขืกืงื ืขื SHA-256 ืืืืืจ ืืื ืืืชืืื ืขืืื signature
, ืืืืื ืืขืกืงื ืืื ืืืง ืื-hash SHA-256.
ืืืฉืื ืืืืืื:
1 - ืฆืืจ ืืืืง ื ืชืื ืื, ืืืื ืืืืขื
/**
* Calls `getBytes` based on transaction type
* @see privateTypes
* @implements {ByteBuffer}
* @param {transaction} trs
* @param {boolean} skipSignature
* @param {boolean} skipSecondSignature
* @return {!Array} Contents as an ArrayBuffer.
* @throws {error} If buffer fails.
*/
adamant.getBytes = function (transaction) {
...
switch (transaction.type) {
case constants.Transactions.SEND:
break
case constants.Transactions.CHAT_MESSAGE:
assetBytes = this.chatGetBytes(transaction)
assetSize = assetBytes.length
break
โฆ
default:
alert('Not supported yet')
}
var bb = new ByteBuffer(1 + 4 + 32 + 8 + 8 + 64 + 64 + assetSize, true)
bb.writeByte(transaction.type)
bb.writeInt(transaction.timestamp)
...
bb.flip()
var arrayBuffer = new Uint8Array(bb.toArrayBuffer())
var buffer = []
for (var i = 0; i < arrayBuffer.length; i++) {
buffer[i] = arrayBuffer[i]
}
return Buffer.from(buffer)
}
2 - ืกืคืืจืช SHA-256 ืืืืืง ืื ืชืื ืื
/**
* Creates hash based on transaction bytes.
* @implements {getBytes}
* @implements {crypto.createHash}
* @param {transaction} trs
* @return {hash} sha256 crypto hash
*/
adamant.getHash = function (trs) {
return crypto.createHash('sha256').update(this.getBytes(trs)).digest()
}
3 - ืืชืื ืขื ืืขืกืงื
adamant.transactionSign = function (trs, keypair) {
var hash = this.getHash(trs)
return this.sign(hash, keypair).toString('hex')
}
/**
* Creates a signature based on a hash and a keypair.
* @implements {sodium}
* @param {hash} hash
* @param {keypair} keypair
* @return {signature} signature
*/
adamant.sign = function (hash, keypair) {
return sodium.crypto_sign_detached(hash, Buffer.from(keypair.privateKey, 'hex'))
}
ืฉืืืืช ืขืกืงื ืขื ืืืืขื ืืฆืืืช ืจืฉืช
ืืืืืื ืฉืืจืฉืช ืืืืืจืช, ืื ืืื ืืืฆืืชืื ืขื API ืคืชืื ืืชืืื. ืืืฆืืข ืืงืฉืช POST ืื ืงืืืช ืืงืฆื api/transactions
:
curl 'api/transactions' -X POST
-d 'TX_DATA'
ืืชืืืื ื ืงืื ืืืื ืขืกืงื ืืืกืื
{
"success": true,
"nodeTimestamp": 63228852,
"transactionId": "6146865104403680934"
}
ืืืืืช ืขืกืงื
ืืขืจืืช ืืืืืจืช ืฉื ืฆืืชืื, ืืืืืกืกืช ืขื ืงืื ืฆื ืืืก, ืงืืืขืช ืืช ื"ืืืชื ืืืืช" ืฉื ืืืืขืช ืืขืกืงื. ืืื ืืืื, ืืชื, ืืื ืืืืืคื ืืืืืขื ืืืืจืช, ืืืื ืฆืืื ื ื ืืื ืฉืขืช ืืฉืืืื. ืืื ืืชืจืื ืืฉืื ืืืื ืฉื ืืืืืงืฆ'ืืื โ ืืื ืืื ื ืืจืืื ืฉืืืจืื ืขื ืืืืืืช, ืืื ื ืืชื ืืืืืฃ ืืช ืจืฆืฃ ืืืืืขืืช ืืชืืืืชื.
ืจืืฉืืช, ืฆืืืช ืืื ืืืืง ืืช ืืืืืง, ืืืืืจ ืืื ืฉืืื ืืืชื ืืืืจืื - ืื ืืจืื ืืืืจ ืฉืืื ืชืงืื, ืืขืกืงื ืชืืืื ืืืืืง ืืื ืฉื ืืฉืจืฉืจืช - ืื ืงืื ืฆื ืืืก.
ื ืืชื ืืจืืืช ืืช ืืืืง ืืงืื ืืฆืืืช ืฉืืืจืื ืืืืืงืืช ื-GitHub -
ืืืื ืขืกืงื ืขื ืืืืขื ืืืืืง
ืื ืืืฉื ืืกืืื, ืืขืกืงื ืขื ืืืืืขื ืฉืื ื ืชืืืื ืืืืืง ืืื ืืื ืขื ืขืกืงืืืช ืชืงืคืืช ืืืจืืช.
ืืืืืงืื ืืฉ ืจืฆืฃ ืงืคืื ื, ืืื ืืืืง ืขืืงื ื ืืฆืจ ืขื ืกืื ื-hash ืฉื ืืืืงืื ืงืืืืื.
ืื ืงืืื ืืื ืฉืื ืืืกืจ ืฉืื ื ื ืืื ืืจืฆืฃ ืืื ืืื ื ืืชื "ืืกืืจ ืืืชื ืืืืฉ". ืื ืืกืคืจ ืืืืขืืช ื ืื ืกืืช ืืืกืืื, ืืกืืจ ืฉืืื ืืืงืืข ืืคื timestamp
ืืืืขืืช.
ืงืจืืืช ืืืืขืืช
ืืคืืืงืฆืืืช ืืืกื ื'ืจ ืืืืืจืช ืืืืืืงืฆ'ืืื ืขืกืงืืืช ืฉื ืฉืืืืช ืื ืืขื. ืืฉืืื ืื ืขืฉืื ื ื ืงืืืช ืงืฆื api/chatrooms
.
ืื ืืขืกืงืืืช ืืืื ืืช ืืืืื - ื ืืชื ืืงืื ืืืืขืืช ืืืฆืคื ืืช. ืืื ืจืง ืื ืืขื ืืืื ืืคืขื ื ืืืืฆืขืืช ืืืคืชื ืืคืจืื ืฉืื ืืืืคืชื ืืฆืืืืจื ืฉื ืืฉืืื:
**
* Decodes the incoming message
* @param {any} msg encoded message
* @param {string} senderPublicKey sender public key
* @param {string} privateKey our private key
* @param {any} nonce nonce
* @returns {string}
*/
adamant.decodeMessage = function (msg, senderPublicKey, privateKey, nonce) {
if (typeof msg === 'string') {
msg = hexToBytes(msg)
}
if (typeof nonce === 'string') {
nonce = hexToBytes(nonce)
}
if (typeof senderPublicKey === 'string') {
senderPublicKey = hexToBytes(senderPublicKey)
}
if (typeof privateKey === 'string') {
privateKey = hexToBytes(privateKey)
}
const DHPublicKey = ed2curve.convertPublicKey(senderPublicKey)
const DHSecretKey = ed2curve.convertSecretKey(privateKey)
const decrypted = nacl.box.open(msg, nonce, DHPublicKey, DHSecretKey)
return decrypted ? decode(decrypted) : ''
}
ืื ืขืื?
ืืืืืื ืฉืืืืขืืช ืืืขืืจืืช ืืฆืืจื ืื ืชืื ื-5 ืฉื ืืืช - ืื ืืืื ืฉืื ืืืคืืขื ืืืืง ืจืฉืช ืืืฉ - ืืืขื ื ืืืืืืจ ืฉืงืข ืืงืื ืืฆืืืช ืืฆืืืช ืืฆืืืช. ืืืฉืจ ืฆืืืช ืืงืื ืขืกืงื ืืืฉื, ืืื ืืืืง ืืช ืชืงืคืืชื ืืืขืืืจ ืืืชื ืืฆืืชืื ืืืจืื. ืืขืกืงื ืืืื ื ืืืงืืืืช ืืกื ื'ืจ ืขืื ืืคื ื ืฉืืชืจืืฉ ืงืื ืฆื ืืืก ืืืืืื ืืืกืืื. ืื ื ืขืืืจ ืืืืขืืช ืืืืคื ืืืืื, ืืืืืง ืืื ืฉืืืืื ืืืืืืื ืจืืืืื.
ืืื ืืืืกื ืืช ืคื ืงืก ืืืชืืืืช, ืขืฉืื ื KVS - Key-Value Storage - ืื ืกืื ืืืจ ืฉื ืขืกืงื ืฉืื asset
ืื ืื NaCl-box ืฉืืืฆืคื ืช, ืืื
ืืขืืจืช ืงืืฆืื/ืชืืื ืืช ืืฆ'ืืืื ืงืืืฆืชืืื ืขืืืื ืืืจืฉืื ืขืืืื ืจืื. ืืืืื, ืืคืืจืื ืืืขืืืืช ืืืืขืืช ืืคืฉืจ "ืืืคืืง" ืืช ืื ืืืืืจืืช, ืืื ืื ืื ื ืจืืฆืื ืืฉืืืจ ืขื ืืืชื ืจืืช ืคืจืืืืช.
ืื, ืืฉ ืขืื ืขืืืื ืืขืฉืืช - ืืืืคื ืืืืืืื, ืคืจืืืืช ืืืืชืืช ืื ืืื ืฉืืฉืชืืฉืื ืื ืืชืืืจื ืืฆืืชื ืจืฉืช ืฆืืืืจืืื, ืืื ืืืืื ืืช ืฉืืื. ืืืื ืืืื ืืืืฉืชืืฉืื ืืชื ืืืฉื ืฉืขืืฉื ืืช ืื? ืื ื ืืื, 0. ืืฆืืื ื ืืคืชืืจ ืืช ืืืขืื ืืื ืืืืคื ืืืงื ืขื ืืจืกืช Tor ืฉื ืืืกื ื'ืจ.
ืืืืื ื ืฉืฉืืื ืืืืืงืฆ'ืืื ืืืื ืืืชืงืืื. ืืขืืจ, ืืื ืจืง โโื ืืกืืื ืืื ื-2012 -
ืืืกืคืงื ืืช ื ืืืขืช ืืื ืฉืฉืืืืื ืืืืืงืฆ'ืืื ืืงืืืืื ืืช ืืื ื - ืื ืฉืื ืื ืืืื ืื ืืงืืช ืืืจืืืช ืขื ืืืฉืืื ืฉืืื, ืืขืืืช ืขื ืืืืข ืืืฉื ืืื ืขืืืื ืื ืืจื ื, ืืืืื ืืืืืื ืื ืืืคืฉืจืช ืืืืจืืืืช ืืืืืืช ืืืืืงืฆ'ืืื. ืื ืืืืื ืืื ืืืืืืื ื ืืกืคืื ืฉื ืืคืจืืืงื ืฉืื ื ืืืคืืขื ืืืืฉื. ืชืจืื.
ืืงืืจ: www.habr.com