gecko/vms/avm/static_service.go

163 lines
4.1 KiB
Go

// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package avm
import (
"encoding/json"
"errors"
"net/http"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/utils/formatting"
"github.com/ava-labs/gecko/utils/wrappers"
"github.com/ava-labs/gecko/utils/codec"
"github.com/ava-labs/gecko/vms/secp256k1fx"
cjson "github.com/ava-labs/gecko/utils/json"
)
var (
errUnknownAssetType = errors.New("unknown asset type")
)
// StaticService defines the base service for the asset vm
type StaticService struct{}
// BuildGenesisArgs are arguments for BuildGenesis
type BuildGenesisArgs struct {
GenesisData map[string]AssetDefinition `json:"genesisData"`
}
// AssetDefinition ...
type AssetDefinition struct {
Name string `json:"name"`
Symbol string `json:"symbol"`
Denomination cjson.Uint8 `json:"denomination"`
InitialState map[string][]interface{} `json:"initialState"`
}
// BuildGenesisReply is the reply from BuildGenesis
type BuildGenesisReply struct {
Bytes formatting.CB58 `json:"bytes"`
}
// BuildGenesis returns the UTXOs such that at least one address in [args.Addresses] is
// referenced in the UTXO.
func (*StaticService) BuildGenesis(_ *http.Request, args *BuildGenesisArgs, reply *BuildGenesisReply) error {
errs := wrappers.Errs{}
c := codec.NewDefault()
errs.Add(
c.RegisterType(&BaseTx{}),
c.RegisterType(&CreateAssetTx{}),
c.RegisterType(&OperationTx{}),
c.RegisterType(&ImportTx{}),
c.RegisterType(&ExportTx{}),
c.RegisterType(&secp256k1fx.TransferInput{}),
c.RegisterType(&secp256k1fx.MintOutput{}),
c.RegisterType(&secp256k1fx.TransferOutput{}),
c.RegisterType(&secp256k1fx.MintOperation{}),
c.RegisterType(&secp256k1fx.Credential{}),
)
if errs.Errored() {
return errs.Err
}
g := Genesis{}
for assetAlias, assetDefinition := range args.GenesisData {
asset := GenesisAsset{
Alias: assetAlias,
CreateAssetTx: CreateAssetTx{
BaseTx: BaseTx{
BCID: ids.Empty,
},
Name: assetDefinition.Name,
Symbol: assetDefinition.Symbol,
Denomination: byte(assetDefinition.Denomination),
},
}
if len(assetDefinition.InitialState) > 0 {
initialState := &InitialState{
FxID: 0, // TODO: Should lookup secp256k1fx FxID
}
for assetType, initialStates := range assetDefinition.InitialState {
switch assetType {
case "fixedCap":
for _, state := range initialStates {
b, err := json.Marshal(state)
if err != nil {
return err
}
holder := Holder{}
if err := json.Unmarshal(b, &holder); err != nil {
return err
}
cb58 := formatting.CB58{}
if err := cb58.FromString(holder.Address); err != nil {
return err
}
addr, err := ids.ToShortID(cb58.Bytes)
if err != nil {
return err
}
initialState.Outs = append(initialState.Outs, &secp256k1fx.TransferOutput{
Amt: uint64(holder.Amount),
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{addr},
},
})
}
case "variableCap":
for _, state := range initialStates {
b, err := json.Marshal(state)
if err != nil {
return err
}
owners := Owners{}
if err := json.Unmarshal(b, &owners); err != nil {
return err
}
out := &secp256k1fx.MintOutput{
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
},
}
for _, address := range owners.Minters {
cb58 := formatting.CB58{}
if err := cb58.FromString(address); err != nil {
return err
}
addr, err := ids.ToShortID(cb58.Bytes)
if err != nil {
return err
}
out.Addrs = append(out.Addrs, addr)
}
out.Sort()
initialState.Outs = append(initialState.Outs, out)
}
default:
return errUnknownAssetType
}
}
initialState.Sort(c)
asset.States = append(asset.States, initialState)
}
asset.Sort()
g.Txs = append(g.Txs, &asset)
}
g.Sort()
b, err := c.Marshal(&g)
if err != nil {
return err
}
reply.Bytes.Bytes = b
return nil
}