-
Notifications
You must be signed in to change notification settings - Fork 0
/
ctc.go
executable file
·127 lines (99 loc) · 3.78 KB
/
ctc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/crypto"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
type CanonicalTransactionContract struct {
contractapi.Contract
}
type TransactionInfo struct {
ChaincodeName string `json:"chaincodeName"`
TransactionName string `json:"transactionName"`
Args []string `json:"args"`
}
type Batch struct {
Timestamp int64 `json:"timestamp"`
Transactions []TransactionInfo `json:"transactions"`
PrevStateHash []byte `json:"prevStateHash"`
NewStateHash []byte `json:"newStateHash"`
}
type BatchReadyForCommit struct {
Timestamp int64 `json:"timestamp"`
Transactions []TransactionInfo `json:"transactions"`
PrevStateHash []byte `json:"prevStateHash"`
NewStateHash []byte `json:"newStateHash"`
PrevBatchHash []byte `json:"prevBatchHash"`
}
const latestBatchHashKey = "latestBatchHash"
func (ctc *CanonicalTransactionContract) CommitBatch(ctx contractapi.TransactionContextInterface, payload string) error {
var batch Batch
if err := json.Unmarshal([]byte(payload), &batch); err != nil {
return fmt.Errorf("failed to unmarshal batch payload. Error: %s", err.Error())
}
var batchReadyForCommit BatchReadyForCommit;
latestBatchHash, err := ctx.GetStub().GetState(latestBatchHashKey)
if err != nil {
return fmt.Errorf("failed to check if latestBatchKey already exists in world state. Error: %s", err.Error())
}
//TODO: check if prevStateHash matches newStateHash of latest batch
batchReadyForCommit = BatchReadyForCommit {
Timestamp: batch.Timestamp,
Transactions: batch.Transactions,
PrevStateHash: batch.PrevStateHash,
NewStateHash: batch.NewStateHash,
PrevBatchHash: latestBatchHash,
}
batchJSON, err := json.Marshal(batchReadyForCommit)
if err != nil {
return fmt.Errorf("failed to marshal batch struct. Error: %s", err.Error())
}
batchHash := crypto.Keccak256(batchJSON)
err = ctx.GetStub().PutState(hex.EncodeToString(batchHash), batchJSON)
if err != nil {
return fmt.Errorf("failed to add batch into world state. Error: %s", err.Error())
}
err = ctx.GetStub().PutState(latestBatchHashKey, batchHash)
if err != nil {
return fmt.Errorf("failed to add latestBatchHash into world state. Error: %s", err.Error())
}
return nil;
}
func (ctc *CanonicalTransactionContract) GetBatchHistory(ctx contractapi.TransactionContextInterface) (string, error) {
var history []string
//TODO: handle errors
latestBatchHash, err := ctx.GetStub().GetState(latestBatchHashKey)
if err != nil {
return "", fmt.Errorf("failed to check if latestBatchKey already exists in world state. Error: %s", err.Error())
}
if latestBatchHash == nil {
return "", fmt.Errorf("latest batch hash does not exist in world state. Are you sure you added a batch?")
}
rawBatch, err := ctx.GetStub().GetState(hex.EncodeToString(latestBatchHash))
if err != nil {
return "", fmt.Errorf("failed to check if latest batch already exists in world state. Error: %s", err.Error())
}
for rawBatch != nil {
var batch BatchReadyForCommit
json.Unmarshal(rawBatch, &batch)
history = append(history, string(rawBatch))
rawBatch, _ = ctx.GetStub().GetState(hex.EncodeToString(batch.PrevBatchHash))
}
return strings.Join(history, ";"), nil
}
func (ctc *CanonicalTransactionContract) DeleteBatchChain (ctx contractapi.TransactionContextInterface) {
ctx.GetStub().DelState(latestBatchHashKey);
}
func main() {
chaincode, err := contractapi.NewChaincode(new(CanonicalTransactionContract))
if err != nil {
fmt.Printf("Error create statecontract chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting statecontract chaincode: %s", err.Error())
}
}