194 lines
4.3 KiB
Go
194 lines
4.3 KiB
Go
|
package core
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"crypto/sha256"
|
||
|
"encoding/hex"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"hash"
|
||
|
"log"
|
||
|
"time"
|
||
|
|
||
|
"thesis/crypto"
|
||
|
"thesis/ent"
|
||
|
)
|
||
|
|
||
|
/*
|
||
|
** Type 1: Transaction sync
|
||
|
** Type 2: New Transaction cast
|
||
|
*/
|
||
|
type DataPacket struct {
|
||
|
Type int
|
||
|
Data []byte
|
||
|
}
|
||
|
|
||
|
func (p DataPacket) Serialize() []byte {
|
||
|
data, err := json.Marshal(p)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return data
|
||
|
}
|
||
|
|
||
|
func DeSerialize(p []byte) DataPacket {
|
||
|
|
||
|
var msg DataPacket
|
||
|
err := json.Unmarshal(p, &msg)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return msg
|
||
|
}
|
||
|
|
||
|
func SyncContent(msg DataPacket) {
|
||
|
if msg.Type == 1 {
|
||
|
fmt.Println("got a tx sync")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ValidateContent(client *ent.Client, pk *crypto.PublicKey) error {
|
||
|
txs, err := client.Transactions.Query().All(context.Background())
|
||
|
handleError(err)
|
||
|
for i := 0; i < len(txs); i++ {
|
||
|
currentTx := &Transaction{
|
||
|
Type: txs[i].Type,
|
||
|
Timestamp: int64(txs[i].Timestamp),
|
||
|
Comment: txs[i].Comment,
|
||
|
Content: txs[i].Content,
|
||
|
Hash: txs[i].Hash,
|
||
|
Signature: txs[i].Signature,
|
||
|
}
|
||
|
// fmt.Println(currentTx)
|
||
|
err := crypto.ValidateSignature(currentTx.Signature, pk, []byte(currentTx.Hash))
|
||
|
handleError(err)
|
||
|
log.Printf("Valid signature for tx: %s", currentTx.Hash)
|
||
|
}
|
||
|
|
||
|
blocks, err := client.Blocks.Query().All(context.Background())
|
||
|
handleError(err)
|
||
|
for i := 0; i < len(blocks); i++ {
|
||
|
// currentBlock := &core.Block{
|
||
|
// Hash: blocks[i].Hash,
|
||
|
// Nonce: blocks[i].ID,
|
||
|
// Length: blocks[i].Length,
|
||
|
// PreviousHash: blocks[i].PreviousHash,
|
||
|
// }
|
||
|
|
||
|
txs, err := blocks[i].QueryMinedTxs().All(context.Background())
|
||
|
handleError(err)
|
||
|
var hash hash.Hash
|
||
|
for j := 0; j < len(txs); j++ {
|
||
|
tx := &Transaction{
|
||
|
Type: txs[j].Type,
|
||
|
Timestamp: int64(txs[j].Timestamp),
|
||
|
Comment: txs[j].Comment,
|
||
|
Content: txs[j].Content,
|
||
|
Hash: txs[j].Hash,
|
||
|
Signature: txs[j].Signature,
|
||
|
}
|
||
|
txBytes, err := json.Marshal(tx)
|
||
|
handleError(err)
|
||
|
hash = sha256.New()
|
||
|
hash.Write(txBytes)
|
||
|
}
|
||
|
if fmt.Sprintf("0x%x", string(hash.Sum(nil))) == blocks[i].Hash {
|
||
|
log.Printf("Block %d validated \n", blocks[i].ID)
|
||
|
} else {
|
||
|
log.Printf("Block %d is invalid !!!\n", blocks[i].ID)
|
||
|
return errors.New("invalid block detected")
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func AddNewTx(client *ent.Client, content []byte, commit string, sig string, key *ent.Key) error {
|
||
|
|
||
|
// key := db.GetKeyFromHex(pk)
|
||
|
// if key == nil {
|
||
|
// return
|
||
|
// }
|
||
|
tx := &Transaction{
|
||
|
Type: 2,
|
||
|
Timestamp: time.Now().Unix(),
|
||
|
Comment: "regular tx",
|
||
|
Content: content,
|
||
|
Signature: sig,
|
||
|
}
|
||
|
txBytes, err := json.Marshal(tx)
|
||
|
handleError(err)
|
||
|
hash := sha256.New()
|
||
|
hash.Write(txBytes)
|
||
|
tx.Hash = fmt.Sprintf("0x%x", string(hash.Sum(nil)))
|
||
|
pubBytes, err := hex.DecodeString(key.PublicKey[2:])
|
||
|
handleError(err)
|
||
|
pk := new(crypto.PublicKey).Uncompress(pubBytes)
|
||
|
fmt.Println(hash)
|
||
|
err = crypto.ValidateSignature(sig, pk, []byte(fmt.Sprintf("%s%s%s", key.PublicKey, tx.Comment, commit)))
|
||
|
if err != nil {
|
||
|
fmt.Println("Invalid data submitted")
|
||
|
// return nil
|
||
|
}
|
||
|
txContent := &TransactionContent{
|
||
|
Signer: key.PublicKey,
|
||
|
Commitment: commit,
|
||
|
}
|
||
|
contentBytes, err := json.Marshal(txContent)
|
||
|
handleError(err)
|
||
|
dbTX, err := client.Transactions.Create().
|
||
|
SetComment(tx.Comment).
|
||
|
SetHash(tx.Hash).
|
||
|
SetTimestamp(int(tx.Timestamp)).
|
||
|
SetSignature(tx.Signature).
|
||
|
SetType(tx.Type).
|
||
|
SetContent(contentBytes).
|
||
|
Save(context.Background())
|
||
|
handleError(err)
|
||
|
// db.AddTx(client, txObj)
|
||
|
txBytes, err = json.Marshal(tx)
|
||
|
handleError(err)
|
||
|
hash = sha256.New()
|
||
|
hash.Write(txBytes)
|
||
|
|
||
|
blocks, err := client.Blocks.Query().All(context.Background())
|
||
|
handleError(err)
|
||
|
var block Block
|
||
|
|
||
|
if len(blocks) == 0 {
|
||
|
block = Block{
|
||
|
Hash: fmt.Sprintf("0x%x", string(hash.Sum(nil))),
|
||
|
Nonce: 0,
|
||
|
Length: 1,
|
||
|
PreviousHash: "0x000",
|
||
|
}
|
||
|
} else {
|
||
|
lastBlock := blocks[len(blocks)-1]
|
||
|
|
||
|
block = Block{
|
||
|
Hash: fmt.Sprintf("0x%x", string(hash.Sum(nil))),
|
||
|
Nonce: lastBlock.ID,
|
||
|
Length: 1,
|
||
|
PreviousHash: lastBlock.Hash,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dbBlock, err := client.Blocks.Create().
|
||
|
SetHash(block.Hash).
|
||
|
SetID(block.Nonce).
|
||
|
SetLength(block.Length).
|
||
|
SetPreviousHash(block.PreviousHash).
|
||
|
Save(context.Background())
|
||
|
handleError(err)
|
||
|
_, err = dbTX.Update().AddBlock(dbBlock).Save(context.Background())
|
||
|
handleError(err)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func handleError(err error) {
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|