chore: sync submodule state (parent ref update)
Made-with: Cursor
This commit is contained in:
207
fabric/chaincode/bridge/bridge.go
Normal file
207
fabric/chaincode/bridge/bridge.go
Normal file
@@ -0,0 +1,207 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hyperledger/fabric-contract-api-go/contractapi"
|
||||
)
|
||||
|
||||
// BridgeChaincode provides functions for cross-chain asset bridging
|
||||
type BridgeChaincode struct {
|
||||
contractapi.Contract
|
||||
}
|
||||
|
||||
// Asset represents a bridged asset
|
||||
type Asset struct {
|
||||
ID string `json:"id"`
|
||||
Owner string `json:"owner"`
|
||||
Amount uint64 `json:"amount"`
|
||||
TokenType string `json:"tokenType"`
|
||||
Locked bool `json:"locked"`
|
||||
EvmTxHash string `json:"evmTxHash,omitempty"`
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
}
|
||||
|
||||
// InitLedger initializes the ledger with sample assets
|
||||
func (s *BridgeChaincode) InitLedger(ctx contractapi.TransactionContextInterface) error {
|
||||
assets := []Asset{
|
||||
{ID: "asset1", Owner: "Org1MSP", Amount: 1000, TokenType: "ERC20", Locked: false},
|
||||
{ID: "asset2", Owner: "Org2MSP", Amount: 2000, TokenType: "ERC20", Locked: false},
|
||||
}
|
||||
|
||||
for _, asset := range assets {
|
||||
assetJSON, err := json.Marshal(asset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(asset.ID, assetJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to put to world state. %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadAsset returns the asset stored in the world state with given id
|
||||
func (s *BridgeChaincode) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) {
|
||||
assetJSON, err := ctx.GetStub().GetState(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read from world state: %v", err)
|
||||
}
|
||||
if assetJSON == nil {
|
||||
return nil, fmt.Errorf("the asset %s does not exist", id)
|
||||
}
|
||||
|
||||
var asset Asset
|
||||
err = json.Unmarshal(assetJSON, &asset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &asset, nil
|
||||
}
|
||||
|
||||
// LockAsset locks an asset for bridge transfer to EVM
|
||||
func (s *BridgeChaincode) LockAsset(
|
||||
ctx contractapi.TransactionContextInterface,
|
||||
assetId string,
|
||||
evmDestination string,
|
||||
requestId string,
|
||||
) error {
|
||||
asset, err := s.ReadAsset(ctx, assetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if asset.Locked {
|
||||
return fmt.Errorf("asset %s is already locked", assetId)
|
||||
}
|
||||
|
||||
asset.Locked = true
|
||||
asset.RequestID = requestId
|
||||
assetJSON, err := json.Marshal(asset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Emit event for EVM bridge to pick up
|
||||
err = ctx.GetStub().SetEvent("BridgeToEVM", []byte(fmt.Sprintf(`{"assetId":"%s","amount":%d,"evmRecipient":"%s","requestId":"%s"}`, assetId, asset.Amount, evmDestination, requestId)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set event: %v", err)
|
||||
}
|
||||
|
||||
return ctx.GetStub().PutState(assetId, assetJSON)
|
||||
}
|
||||
|
||||
// UnlockAsset unlocks an asset after bridge completion
|
||||
func (s *BridgeChaincode) UnlockAsset(
|
||||
ctx contractapi.TransactionContextInterface,
|
||||
assetId string,
|
||||
evmTxHash string,
|
||||
) error {
|
||||
asset, err := s.ReadAsset(ctx, assetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
asset.Locked = false
|
||||
asset.EvmTxHash = evmTxHash
|
||||
assetJSON, err := json.Marshal(asset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctx.GetStub().PutState(assetId, assetJSON)
|
||||
}
|
||||
|
||||
// BurnAsset burns an asset on Fabric side (mint on EVM side)
|
||||
func (s *BridgeChaincode) BurnAsset(
|
||||
ctx contractapi.TransactionContextInterface,
|
||||
assetId string,
|
||||
evmRecipient string,
|
||||
requestId string,
|
||||
) error {
|
||||
asset, err := s.ReadAsset(ctx, assetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Emit event for EVM minting
|
||||
err = ctx.GetStub().SetEvent("BridgeToEVM", []byte(fmt.Sprintf(`{"assetId":"%s","amount":%d,"evmRecipient":"%s","requestId":"%s","action":"mint"}`, assetId, asset.Amount, evmRecipient, requestId)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set event: %v", err)
|
||||
}
|
||||
|
||||
// Delete asset (burn)
|
||||
return ctx.GetStub().DelState(assetId)
|
||||
}
|
||||
|
||||
// CreateAsset creates a new asset
|
||||
func (s *BridgeChaincode) CreateAsset(
|
||||
ctx contractapi.TransactionContextInterface,
|
||||
id string,
|
||||
amount uint64,
|
||||
tokenType string,
|
||||
) error {
|
||||
clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get client MSP ID: %v", err)
|
||||
}
|
||||
|
||||
asset := Asset{
|
||||
ID: id,
|
||||
Owner: clientMSPID,
|
||||
Amount: amount,
|
||||
TokenType: tokenType,
|
||||
Locked: false,
|
||||
}
|
||||
|
||||
assetJSON, err := json.Marshal(asset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctx.GetStub().PutState(id, assetJSON)
|
||||
}
|
||||
|
||||
// GetAllAssets returns all assets found in world state
|
||||
func (s *BridgeChaincode) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
|
||||
resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resultsIterator.Close()
|
||||
|
||||
var assets []*Asset
|
||||
for resultsIterator.HasNext() {
|
||||
queryResponse, err := resultsIterator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var asset Asset
|
||||
err = json.Unmarshal(queryResponse.Value, &asset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assets = append(assets, &asset)
|
||||
}
|
||||
|
||||
return assets, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
chaincode, err := contractapi.NewChaincode(&BridgeChaincode{})
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating bridge chaincode: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := chaincode.Start(); err != nil {
|
||||
fmt.Printf("Error starting bridge chaincode: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user