BlockChain - Transaction(1) , Wallet

정종찬·2022년 5월 7일
0
    암호화

    블록체인 
        탈중앙화
        분산원장관리

        무결성 : 정보는 일반적으로 수정이 가능한데, 이는 권한이 있는 사용자에게만 허가 
        기밀성 : 정보를 저장하고 전송하면서 부적절한 노출을 방지, 정보 보안의 주된 목적
        가용성 : 활용되어야 할 정보에 접근할 수 없다면, 기밀성과 무결성이 훼손된 것만큼이나 무의미하다.

    지갑 
        프라이빗키 으로 퍼블릭키를 만들수 있지만 퍼블릭키로 프라이빗키를 유추할수 없다
    private Key 
    public Key 

    타원 곡선 디지털 서명 알고리즘 (ECDSA)
    
    영지식증명 (Zero Knowledge Proof)
        증명하는 사람(A), 증명을 원하는 사람(B) 
        A와 B는 증명된 내용에 합의
        그 외의 사람들은 동의하지 않는다.
        증명하는 과정에서 A는 B에게 아무런 정보도 주지 않는다. 
main.js


import { initHttpServer } from "./httpServer.js";
import { initP2PServer } from "./p2pServer.js";
import { initWallet } from "./wallet.js";

const httpPort = parseInt(process.env.HTTP_PORT) || 3001;
const p2pPort = parseInt(process.env.P2P_PORT) || 6001;

initWallet()
initHttpServer(httpPort);
initP2PServer(p2pPort);
httpServer.js


// 웹에 명령어를 입력해서 내 노드를 제어하는 서버
// const epress = require('express') // 전부다 가져온다.
import express from 'express';              // 필요한 것만 가져와서 간결하게 쓸수 있다.
import bodyParser from 'body-parser';
import { getBlocks, createBlock } from './block.js';
import { connectionToPeer, getPeers, mineBlock } from './p2pServer.js';
import { getPublicKeyFromWallet } from './wallet.js'
// import path from 'path';

// 초기화 함수
const initHttpServer = (myHttpPoryt) => {
    const app = express();
    // const __dirname = path.resolve();
    app.use(bodyParser.json());

    app.get('/', (req, res) => {
        //res.sendFile(path.join(__dirname, './index.html'));;
        res.send('Hello, World!');;
    })

    app.get('/blocks', (req, res) => {
        res.send(getBlocks());
    })

    // app.post('/createblock', (req, res) => {
    //     const data = req.body.data
    //     res.send(createBlock(data));        
    // })

    app.post('/createblock', (req, res) => {
        res.send(createBlock(req.body.data));        
    })
    
    app.post('/mineBlock', (req, res) => {
        res.send(mineBlock(req.body.data));
    })

    app.post('/peers', (req, res) => {
        res.send(getPeers())
    })

    app.post('/addPeer', (req, res) => {
        console.log('/addrPeer : ', req.body.message);
        res.send(connectionToPeer(req.body.data));
    })

    // app.post('/sendMessage', (req, res) => {
    //     res.send(sendMessage(req.body.data))
    // })

    // app.post('/allblocks', (req, res) => {
    //     res.send(responseAllMessage(req.body.data))
    // })

    // app.use('/latestblock', (req, res) => {
    //     res.send(responseLatestMessage(req.body.data))
    // })
    
    app.post('/allblocks', (req, res) => {
        res.send(queryAllMessage(req.body.data))
    })

    app.use('/latestblock', (req, res) => {
        res.send(queryLatestMessage(req.body.data))
    })

    app.get('/address', (req, res) => {
        const address = getPublicKeyFromWallet();
        res.send( {'address' : address } );
    })

    app.listen(myHttpPoryt, () => {
        console.log('listening httpServer Port : ', myHttpPoryt);
    })
}

export { initHttpServer }

wallet.js



import ecdsa from 'elliptic'
import fs from 'fs';

const ec = new ecdsa.ec('secp256k1');
const privateKeyLocation = 'wallet/' + (process.env.PRIVATE_KEY || 'defalut' );
const privateKeyFile = privateKeyLocation + '/private_key';

const createPrivateKey = () => {
    const keyPair = ec.genKeyPair();
    const privateKey = keyPair.getPrivate();
    
    // console.log(privateKey);
    // console.log(privateKey.toString(16));

    return privateKey.toString(16)
}

const initWallet = () => {
    // 이미 만들어져 있을 때
    if (fs.existsSync(privateKeyFile)) {
        console.log('지갑에 비밀키가 만들어져 있음');
        return;
    } 

    if (!fs.existsSync('wallet/')) { fs.mkdirSync('wallet/'); }                     // 폴더가 없으면 만들어줘
    if (!fs.existsSync(privateKeyLocation)) { fs.mkdirSync(privateKeyLocation); }   // 폴더에 로케이션이 없으면 만들어줘

    const privateKey = createPrivateKey();
    fs.writeFileSync(privateKeyFile, privateKey);
}

const getPrivateKeyFromWallt = () => {
    const buffer = fs.readFileSync(privateKeyFile, 'utf-8');
    return buffer.toString();
}

const getPublicKeyFromWallet = () => {
    const privateKey = getPrivateKeyFromWallt();
    const publicKey = ec.keyFromPrivate(privateKey, 'hex');

    // console.log(publicKey.getPublic().encode('hex'));        

    return publicKey.getPublic().encode('hex')
}

export { initWallet, getPublicKeyFromWallet }
transation.js


import CryptoJS from 'crypto-js'

const COINBASE_AMOUNT = 50;

// 코인을 어디로 얼만큼 보냈는가
class TxOut {                           
    constructor(address, amount ) {
        this.address = address;         // string
        this.amount = amount;            // number        
    }
}

// 보내진 코인이 실제로 소유했다에 대한 증거
class TxIn {
    constructor(txOutId, txOutIndex, sign) {
        this.txOutId = txOutId;         // string
        this.txOutIndex = txOutIndex;   // number
        this.sign = sign;               // string
    }
}

//
class Transaction {
    constructor(id, txIns, txOuts) {
        this.id = id;                   // string
        this.txIns = txIns;             // TxIn []
        this.txOuts = txOuts;           // TxOut []
    }
}

// transaction id
const getTransactionID = (transaction) => {     
    // txIns 에 있는 내용들을 하나의 문자열로 만든다.
    const txInsContent = transaction.txIns
        .map((txIn) => txIn.txOutId + txIn.txOutIndex)
        .reduce((a, b) => a + b, '');
        /* 아래가 조금 복잡
        const txInsContent = transaction.txIns.map((txIn) => {
            (txIn.txOutId + txIn.txOutIndex).reduce((a, b) => {
                a + b, ''
        })
        */

    // txOuts 에 있는 내용들을 하나의 문자열로 만든다.
    const txOutsContent = transaction.txOuts
    .map((txOut) => txOut.address + txOut.amount)
    .reduce((a, b) => a + b, '');

    // 위 두 내용을 다 합해서 hash 처리한다.
    return CryptoJS.SHA256(txInsContent + txOutsContent).toString()
} 
// 이 내용이 변조되지않았다

// transaction signature 
const signTxIn = (transaction, txInIndex, privateKey) => {
    // const txIn = transaction.txIns[txInIndex];

    // TODO : sign 코드 검증
    const signature = toHexString(privateKey, transaction.id).toDER();
    return signature;
}
// 누가 보냈는지

// coinbase Transection 
const getCoinbaseTransaction = (address, blockIndex) => {
    const tr = new Transaction();

    const txIn = new TxIn();
    txIn.sign = '';
    txIn.txOutId = '';
    txIn.txOutIndex = blockIndex;
        
    const txOut = new TxOut();
    txOut.address = address;
    txOut.amount = COINBASE_AMOUNT;
    
    tr.txIns = [txIn];
    tr.txOuts = [txOut];
    tr.id = getTransactionID(tr);

    return tr;
}

profile
dalssenger

0개의 댓글