github.com/mavryk-network/mvgo@v1.19.9/rpc/genesis.go (about)

     1  // Copyright (c) 2020-2022 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package rpc
     5  
     6  import (
     7  	"encoding/hex"
     8  	"encoding/json"
     9  	"fmt"
    10  	"strconv"
    11  
    12  	"github.com/echa/bson"
    13  
    14  	"github.com/mavryk-network/mvgo/mavryk"
    15  	"github.com/mavryk-network/mvgo/micheline"
    16  )
    17  
    18  // lacking the algorithm to compute KT1 addresses from content,
    19  // we hard-code all mainnet vesting KT1 addresses here
    20  var vestingContractAddrs = []mavryk.Address{
    21  	mavryk.MustParseAddress("KT1QuofAgnsWffHzLA7D78rxytJruGHDe7XG"),
    22  	mavryk.MustParseAddress("KT1CSKPf2jeLpMmrgKquN2bCjBTkAcAdRVDy"),
    23  	mavryk.MustParseAddress("KT1SLWhfqPtQq7f4zLomh8BNgDeprF9B6d2M"),
    24  	mavryk.MustParseAddress("KT1WPEis2WhAc2FciM2tZVn8qe6pCBe9HkDp"),
    25  	mavryk.MustParseAddress("KT1Um7ieBEytZtumecLqGeL56iY6BuWoBgio"),
    26  	mavryk.MustParseAddress("KT1Cz7TyVFvHxXpxLS57RFePrhTGisUpPhvD"),
    27  	mavryk.MustParseAddress("KT1Q1kfbvzteafLvnGz92DGvkdypXfTGfEA3"),
    28  	mavryk.MustParseAddress("KT1PDAELuX7CypUHinUgFgGFskKs7ytwh5Vw"),
    29  	mavryk.MustParseAddress("KT1A56dh8ivKNvLiLVkjYPyudmnY2Ti5Sba3"),
    30  	mavryk.MustParseAddress("KT1RUT25eGgo9KKWXfLhj1xYjghAY1iZ2don"),
    31  	mavryk.MustParseAddress("KT1FuFDZGdw86p6krdBUKoZfEMkcUmezqX5o"),
    32  	mavryk.MustParseAddress("KT1THsDNgHtN56ew9VVCAUWnqPC81pqAxCEp"),
    33  	mavryk.MustParseAddress("KT1EWLAQGPMF2uhtVRPaCH2vtFVN36Njdr6z"),
    34  	mavryk.MustParseAddress("KT1FN5fcNNcgieGjzxbVEPWUpJGwZEpzNGA8"),
    35  	mavryk.MustParseAddress("KT1TcAHw5gpejyemwRtdNyFKGBLc4qwA5gtw"),
    36  	mavryk.MustParseAddress("KT1VsSxSXUkgw6zkBGgUuDXXuJs9ToPqkrCg"),
    37  	mavryk.MustParseAddress("KT1Msatnmdy24sQt6knzpALs4tvHfSPPduA2"),
    38  	mavryk.MustParseAddress("KT1LZFMGrdnPjRLsCZ1aEDUAF5myA5Eo4rQe"),
    39  	mavryk.MustParseAddress("KT1LQ99RfGcmFe98PiBcGXuyjBkWzAcoXXhW"),
    40  	mavryk.MustParseAddress("KT1Kfbk3B6NYPCPohPBDU3Hxf5Xeyy9PdkNp"),
    41  	mavryk.MustParseAddress("KT1DnfT4hfikoMY3uiPE9mQV4y3Xweramb2k"),
    42  	mavryk.MustParseAddress("KT19xDbLsvQKnp9xqfDNPWJbKJJmV93dHDUa"),
    43  	mavryk.MustParseAddress("KT1HvwFnXteMbphi7mfPDhCWkZSDvXEz8iyv"),
    44  	mavryk.MustParseAddress("KT1KRyTaxCAM3YRquifEe29BDbUKNhJ6hdtx"),
    45  	mavryk.MustParseAddress("KT1Gow8VzXZx3Akn5kvjACqnjnyYBxQpzSKr"),
    46  	mavryk.MustParseAddress("KT1W148mcjmfvr9J2RvWcGHxsAFApq9mcfgT"),
    47  	mavryk.MustParseAddress("KT1D5NmtDtgCwPxYNb2ZK2But6dhNLs1T1bV"),
    48  	mavryk.MustParseAddress("KT1TzamC1SCj68ia2E4q2GWZeT24yRHvUZay"),
    49  	mavryk.MustParseAddress("KT1CM1g1o9RKDdtDKgcBWE59X2KgTc2TcYtC"),
    50  	mavryk.MustParseAddress("KT1FL3C6t9Lyfskyb6rQrCRQTnf7M9t587VM"),
    51  	mavryk.MustParseAddress("KT1JW6PwhfaEJu6U3ENsxUeja48AdtqSoekd"),
    52  	mavryk.MustParseAddress("KT1VvXEpeBpreAVpfp4V8ZujqWu2gVykwXBJ"),
    53  }
    54  
    55  type GenesisData struct {
    56  	Accounts    []*X0
    57  	Contracts   []*X1
    58  	Commitments []*X2
    59  }
    60  
    61  // bootstrap account with or without known public key
    62  type X0 struct {
    63  	Addr  mavryk.Address
    64  	Key   mavryk.Key
    65  	Value int64
    66  }
    67  
    68  // bootstrap contract
    69  type X1 struct {
    70  	Addr     mavryk.Address
    71  	Delegate mavryk.Address
    72  	Value    int64
    73  	Script   micheline.Script
    74  }
    75  
    76  // commitment
    77  type X2 struct {
    78  	Addr  mavryk.Address
    79  	Value int64
    80  }
    81  
    82  func (b *GenesisData) Supply() int64 {
    83  	var s int64
    84  	for _, v := range b.Accounts {
    85  		s += v.Value
    86  	}
    87  	for _, v := range b.Contracts {
    88  		s += v.Value
    89  	}
    90  	for _, v := range b.Commitments {
    91  		s += v.Value
    92  	}
    93  	return s
    94  }
    95  
    96  func (b *GenesisData) UnmarshalText(data []byte) error {
    97  	buf := make([]byte, hex.DecodedLen(len(data)))
    98  	if _, err := hex.Decode(buf, data); err != nil {
    99  		return err
   100  	}
   101  	// decode BSON
   102  	encoded := &bootstrap{}
   103  	if err := bson.Unmarshal(buf[4:], encoded); err != nil {
   104  		return err
   105  	}
   106  	// convert BSON to Structs
   107  	acc, err := encoded.DecodeAccounts()
   108  	if err != nil {
   109  		return err
   110  	}
   111  	b.Accounts = acc
   112  	contracts, err := encoded.DecodeContracts()
   113  	if err != nil {
   114  		return err
   115  	}
   116  	b.Contracts = contracts
   117  	commit, err := encoded.DecodeCommitments()
   118  	if err != nil {
   119  		return err
   120  	}
   121  	b.Commitments = commit
   122  	return nil
   123  }
   124  
   125  // BSON data types
   126  type bootstrap struct {
   127  	Accounts    [][]string  `bson:"bootstrap_accounts"`
   128  	Contracts   []*contract `bson:"bootstrap_contracts"`
   129  	Commitments [][]string  `bson:"commitments"`
   130  }
   131  
   132  type contract struct {
   133  	Delegate string `bson:"delegate"`
   134  	Value    string `bson:"amount"`
   135  	Script   bson.M `bson:"script"`
   136  }
   137  
   138  func (b *bootstrap) DecodeContracts() ([]*X1, error) {
   139  	// ignore non-mainnet contract lists (we don't know their addresses)
   140  	if len(b.Contracts) != len(vestingContractAddrs) {
   141  		return nil, nil
   142  	}
   143  	c := make([]*X1, len(b.Contracts))
   144  	for i, v := range b.Contracts {
   145  		c[i] = &X1{
   146  			Addr: vestingContractAddrs[i],
   147  		}
   148  		addr, err := mavryk.ParseAddress(v.Delegate)
   149  		if err != nil {
   150  			return nil, err
   151  		}
   152  		c[i].Delegate = addr
   153  		value, err := strconv.ParseInt(v.Value, 10, 64)
   154  		if err != nil {
   155  			return nil, err
   156  		}
   157  		c[i].Value = value
   158  
   159  		// script unmarshalling BSON -> JSON -> Micheline
   160  		buf, err := json.Marshal(v.Script)
   161  		if err != nil {
   162  			return nil, err
   163  		}
   164  		if err := json.Unmarshal(buf, &c[i].Script); err != nil {
   165  			return nil, err
   166  		}
   167  
   168  		// skip when this does not look like a vesting contract
   169  		isVesting := true
   170  		switch {
   171  		case !c[i].Script.Storage.IsValid():
   172  			isVesting = false
   173  		case len(c[i].Script.Storage.Args) == 0:
   174  			isVesting = false
   175  		case !c[i].Script.Storage.Args[0].IsValid():
   176  			isVesting = false
   177  		case len(c[i].Script.Storage.Args[0].Args) == 0:
   178  			isVesting = false
   179  		case !c[i].Script.Storage.Args[0].Args[1].IsValid():
   180  			isVesting = false
   181  		case len(c[i].Script.Storage.Args[0].Args[1].Args) == 0:
   182  			isVesting = false
   183  		case !c[i].Script.Storage.Args[0].Args[1].Args[0].IsValid():
   184  			isVesting = false
   185  		case len(c[i].Script.Storage.Args[0].Args[1].Args[0].Args) == 0:
   186  			isVesting = false
   187  		}
   188  
   189  		if !isVesting {
   190  			continue
   191  		}
   192  
   193  		// patch initial storage (convert strings to bytes) to circumvent tezos
   194  		// origination bug
   195  		// - replace edpk strings with byte sequences
   196  		// - replace delegate addesses with binary pkh 00 TT AAAA...
   197  
   198  		// keygroups >> signatories
   199  		for _, v := range c[i].Script.Storage.Args[0].Args[1].Args[0].Args {
   200  			for _, vv := range v.Args[0].Args {
   201  				edpk, err := mavryk.ParseKey(vv.String)
   202  				if err != nil {
   203  					return nil, fmt.Errorf("decoding signatory key %s: %v", vv.String, err)
   204  				}
   205  				vv.Type = micheline.PrimBytes
   206  				vv.Bytes = append([]byte{0}, edpk.Data...)
   207  				vv.String = ""
   208  			}
   209  		}
   210  
   211  		// only the first 8 contracts have authorizers set
   212  		if i < 8 {
   213  			// pour_dest
   214  			pair := c[i].Script.Storage.Args[1].Args[1].Args[0].Args
   215  			dest, err := mavryk.ParseAddress(pair[0].String)
   216  			if err != nil {
   217  				return nil, fmt.Errorf("decoding pour_dest %s: %v", pair[0].String, err)
   218  			}
   219  			pair[0].Type = micheline.PrimBytes
   220  			pair[0].Bytes = dest.Encode()
   221  			pair[0].String = ""
   222  
   223  			// pour_authorizer
   224  			edpk, err := mavryk.ParseKey(pair[1].String)
   225  			if err != nil {
   226  				return nil, fmt.Errorf("decoding pour_authorizer key %s: %v", pair[1].String, err)
   227  			}
   228  			// replace with byte sequence
   229  			pair[1].Type = micheline.PrimBytes
   230  			pair[1].Bytes = append([]byte{0}, edpk.Data...)
   231  			pair[1].String = ""
   232  		}
   233  	}
   234  	return c, nil
   235  }
   236  
   237  func (b *bootstrap) DecodeAccounts() ([]*X0, error) {
   238  	acc := make([]*X0, len(b.Accounts))
   239  	for i, v := range b.Accounts {
   240  		acc[i] = &X0{}
   241  		pk := v[0]
   242  		switch {
   243  		case mavryk.HasKeyPrefix(pk):
   244  			key, err := mavryk.ParseKey(pk)
   245  			if err != nil {
   246  				return nil, err
   247  			}
   248  			acc[i].Key = key
   249  			acc[i].Addr = key.Address()
   250  		case mavryk.HasAddressPrefix(pk):
   251  			addr, err := mavryk.ParseAddress(pk)
   252  			if err != nil {
   253  				return nil, err
   254  			}
   255  			acc[i].Addr = addr
   256  		}
   257  		amount, err := strconv.ParseInt(v[1], 10, 64)
   258  		if err != nil {
   259  			return nil, err
   260  		}
   261  		acc[i].Value = amount
   262  	}
   263  	return acc, nil
   264  }
   265  
   266  func (b *bootstrap) DecodeCommitments() ([]*X2, error) {
   267  	c := make([]*X2, len(b.Commitments))
   268  	for i, v := range b.Commitments {
   269  		c[i] = &X2{}
   270  		// [ $Blinded public key hash, $mumav ]
   271  		pk := v[0]
   272  		addr, err := mavryk.ParseAddress(pk)
   273  		if err != nil {
   274  			return nil, err
   275  		}
   276  		c[i].Addr = addr
   277  		amount, err := strconv.ParseInt(v[1], 10, 64)
   278  		if err != nil {
   279  			return nil, err
   280  		}
   281  		c[i].Value = amount
   282  	}
   283  	return c, nil
   284  }