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

     1  // Copyright (c) 2020-2024 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package mavryk
     5  
     6  import (
     7  	"time"
     8  )
     9  
    10  var (
    11  	// DefaultParams defines the blockchain configuration for Mainnet under the latest
    12  	// protocol. It is used to generate compliant transaction encodings. To change,
    13  	// either overwrite this default or set custom params per operation using
    14  	// op.WithParams().
    15  	DefaultParams = (&Params{
    16  		MinimalBlockDelay:            10 * time.Second,
    17  		CostPerByte:                  250,
    18  		OriginationSize:              257,
    19  		HardGasLimitPerOperation:     1040000,
    20  		HardGasLimitPerBlock:         1733333,
    21  		HardStorageLimitPerOperation: 60000,
    22  		MaxOperationDataLength:       32768,
    23  		MaxOperationsTTL:             360,
    24  	}).
    25  		WithChainId(Mainnet).
    26  		WithDeployment(Deployments[Mainnet].AtProtocol(ProtoV002))
    27  
    28  	// BasenetParams defines the blockchain configuration for Basenet testnet.
    29  	// To produce compliant transactions, use these defaults in op.WithParams().
    30  	BasenetParams = (&Params{
    31  		MinimalBlockDelay:            8 * time.Second,
    32  		CostPerByte:                  250,
    33  		OriginationSize:              257,
    34  		HardGasLimitPerOperation:     1040000,
    35  		HardGasLimitPerBlock:         1733333,
    36  		HardStorageLimitPerOperation: 60000,
    37  		MaxOperationDataLength:       32768,
    38  		MaxOperationsTTL:             360,
    39  	}).
    40  		WithChainId(Basenet).
    41  		WithDeployment(Deployments[Basenet].AtProtocol(ProtoV002))
    42  
    43  	// AtlasnetParams defines the blockchain configuration for Atlas testnet.
    44  	// To produce compliant transactions, use these defaults in op.WithParams().
    45  	AtlasnetParams = (&Params{
    46  		MinimalBlockDelay:            8 * time.Second,
    47  		CostPerByte:                  250,
    48  		OriginationSize:              257,
    49  		HardGasLimitPerOperation:     1040000,
    50  		HardGasLimitPerBlock:         1733333,
    51  		HardStorageLimitPerOperation: 60000,
    52  		MaxOperationDataLength:       32768,
    53  		MaxOperationsTTL:             360,
    54  	}).
    55  		WithChainId(Atlasnet).
    56  		WithDeployment(Deployments[Atlasnet].AtProtocol(ProtoV001))
    57  
    58  	// BoreasnetParams defines the blockchain configuration for Paris testnet.
    59  	// To produce compliant transactions, use these defaults in op.WithParams().
    60  	BoreasnetParams = (&Params{
    61  		MinimalBlockDelay:            5 * time.Second,
    62  		CostPerByte:                  250,
    63  		OriginationSize:              257,
    64  		HardGasLimitPerOperation:     1040000,
    65  		HardGasLimitPerBlock:         1733333,
    66  		HardStorageLimitPerOperation: 60000,
    67  		MaxOperationDataLength:       32768,
    68  		MaxOperationsTTL:             360,
    69  	}).
    70  		WithChainId(Boreasnet).
    71  		WithDeployment(Deployments[Boreasnet].AtProtocol(ProtoV002))
    72  )
    73  
    74  // Params contains a subset of protocol configuration settings that are relevant
    75  // for dapps and most indexers. For additional protocol data, call rpc.GetCustomConstants()
    76  // with a custom data struct.
    77  type Params struct {
    78  	// identity
    79  	Network  string       `json:"network,omitempty"`
    80  	ChainId  ChainIdHash  `json:"chain_id"`
    81  	Protocol ProtocolHash `json:"protocol"`
    82  	Version  int          `json:"version"`
    83  
    84  	// timing
    85  	MinimalBlockDelay time.Duration `json:"minimal_block_delay"`
    86  
    87  	// costs
    88  	CostPerByte     int64 `json:"cost_per_byte"`
    89  	OriginationSize int64 `json:"origination_size"`
    90  
    91  	// limits
    92  	BlocksPerCycle               int64 `json:"blocks_per_cycle"`
    93  	ConsensusRightsDelay         int64 `json:"consensus_rights_delay"`
    94  	BlocksPerSnapshot            int64 `json:"blocks_per_snapshot"`
    95  	HardGasLimitPerOperation     int64 `json:"hard_gas_limit_per_operation"`
    96  	HardGasLimitPerBlock         int64 `json:"hard_gas_limit_per_block"`
    97  	HardStorageLimitPerOperation int64 `json:"hard_storage_limit_per_operation"`
    98  	MaxOperationDataLength       int   `json:"max_operation_data_length"`
    99  	MaxOperationsTTL             int64 `json:"max_operations_ttl"`
   100  
   101  	// extra features to follow protocol upgrades
   102  	OperationTagsVersion int   `json:"operation_tags_version,omitempty"` // 1: v5..v11, 2: v12..v18, 3:v19+
   103  	StartHeight          int64 `json:"start_height"`                     // protocol start (may be != cycle start!!)
   104  	EndHeight            int64 `json:"end_height"`                       // protocol end (may be != cycle end!!)
   105  	StartOffset          int64 `json:"start_offset"`                     // correction for cycle start
   106  	StartCycle           int64 `json:"start_cycle"`                      // correction cycle length
   107  }
   108  
   109  func NewParams() *Params {
   110  	return &Params{
   111  		Network:     "unknown",
   112  		StartHeight: 1<<63 - 1,
   113  	}
   114  }
   115  
   116  func (p Params) Clone() *Params {
   117  	np := p
   118  	return &np
   119  }
   120  
   121  func (p *Params) WithChainId(id ChainIdHash) *Params {
   122  	p.ChainId = id
   123  	if p.Network == "unknown" || p.Network == "" {
   124  		switch id {
   125  		case Mainnet:
   126  			p.Network = "Mainnet"
   127  		case Basenet:
   128  			p.Network = "Basenet"
   129  		case Atlasnet:
   130  			p.Network = "Atlasnet"
   131  		case Boreasnet:
   132  			p.Network = "Boreasnet"
   133  		}
   134  	}
   135  	return p
   136  }
   137  
   138  func (p *Params) WithProtocol(h ProtocolHash) *Params {
   139  	var ok bool
   140  	p.Protocol = h
   141  	versionsMtx.RLock()
   142  	p.Version, ok = Versions[h]
   143  	versionsMtx.RUnlock()
   144  	if !ok {
   145  		var max int
   146  		for _, v := range Versions {
   147  			if v < max {
   148  				continue
   149  			}
   150  			max = v
   151  		}
   152  		p.Version = max + 1
   153  		versionsMtx.Lock()
   154  		defer versionsMtx.Unlock()
   155  		Versions[h] = p.Version
   156  	}
   157  	switch {
   158  	case p.Version > 18:
   159  		p.OperationTagsVersion = 3
   160  	case p.Version > 11:
   161  		p.OperationTagsVersion = 2
   162  	case p.Version > 4:
   163  		p.OperationTagsVersion = 1
   164  	}
   165  	return p
   166  }
   167  
   168  func (p *Params) WithNetwork(n string) *Params {
   169  	if p.Network == "unknown" || p.Network == "" {
   170  		p.Network = n
   171  	}
   172  	return p
   173  }
   174  
   175  func (p *Params) WithDeployment(d Deployment) *Params {
   176  	if d.BlocksPerCycle > 0 {
   177  		p.WithProtocol(d.Protocol)
   178  		p.StartOffset = d.StartOffset
   179  		p.StartHeight = d.StartHeight
   180  		p.EndHeight = d.EndHeight
   181  		p.StartCycle = d.StartCycle
   182  		p.ConsensusRightsDelay = d.ConsensusRightsDelay
   183  		p.BlocksPerCycle = d.BlocksPerCycle
   184  		p.BlocksPerSnapshot = d.BlocksPerSnapshot
   185  	}
   186  	return p
   187  }
   188  
   189  func (p *Params) WithBlock(height int64) *Params {
   190  	d := Deployments[p.ChainId].AtBlock(height)
   191  	p.StartOffset = d.StartOffset
   192  	p.StartHeight = d.StartHeight
   193  	p.EndHeight = d.EndHeight
   194  	p.StartCycle = d.StartCycle
   195  	return p
   196  }
   197  
   198  func (p *Params) AtBlock(height int64) *Params {
   199  	if p.ContainsHeight(height) {
   200  		return p
   201  	}
   202  	return p.Clone().WithDeployment(Deployments[p.ChainId].AtBlock(height))
   203  }
   204  
   205  func (p *Params) AtCycle(cycle int64) *Params {
   206  	if p.ContainsCycle(cycle) {
   207  		return p
   208  	}
   209  	return p.Clone().WithDeployment(Deployments[p.ChainId].AtCycle(cycle))
   210  }
   211  
   212  func (p Params) SnapshotBaseCycle(cycle int64) int64 {
   213  	var offset int64 = 2
   214  	if p.Version >= 12 {
   215  		offset = 1
   216  	}
   217  	return cycle - (p.ConsensusRightsDelay + offset)
   218  }
   219  
   220  func (p Params) IsMainnet() bool {
   221  	return p.ChainId.Equal(Mainnet)
   222  }
   223  
   224  // Note: functions below require StartHeight, EndHeight and/or StartCycle!
   225  func (p Params) ContainsHeight(height int64) bool {
   226  	// treat -1 as special height query that matches open interval params only
   227  	return (height < 0 && p.EndHeight < 0) ||
   228  		(p.StartHeight <= height && (p.EndHeight < 0 || p.EndHeight >= height))
   229  }
   230  
   231  func (p Params) ContainsCycle(c int64) bool {
   232  	// FIX granada early start
   233  	s := p.StartCycle
   234  	if c == 387 && p.IsMainnet() {
   235  		s--
   236  	}
   237  	return s <= c
   238  }
   239  
   240  func (p *Params) CycleFromHeight(height int64) int64 {
   241  	// adjust to target height
   242  	at := p.AtBlock(height)
   243  
   244  	// FIX granada early start
   245  	s := at.StartCycle
   246  	if height == 1589248 && at.IsMainnet() {
   247  		s--
   248  	}
   249  	return s + (height-(at.StartHeight-at.StartOffset))/at.BlocksPerCycle
   250  }
   251  
   252  func (p *Params) CycleStartHeight(c int64) int64 {
   253  	// adjust to target cycle
   254  	at := p.AtCycle(c)
   255  	res := at.StartHeight - at.StartOffset + (c-at.StartCycle)*at.BlocksPerCycle
   256  	return res
   257  }
   258  
   259  func (p *Params) CycleEndHeight(c int64) int64 {
   260  	// adjust to target cycle
   261  	at := p.AtCycle(c)
   262  	return at.CycleStartHeight(c) + at.BlocksPerCycle - 1
   263  }
   264  
   265  func (p *Params) CyclePosition(height int64) int64 {
   266  	// adjust to target height
   267  	at := p.AtBlock(height)
   268  	pos := (height - (at.StartHeight - at.StartOffset)) % at.BlocksPerCycle
   269  	if pos < 0 {
   270  		pos += at.BlocksPerCycle
   271  	}
   272  	return pos
   273  }
   274  
   275  func (p *Params) IsCycleStart(height int64) bool {
   276  	return height > 0 && (height == 1 || p.CyclePosition(height) == 0)
   277  }
   278  
   279  func (p *Params) IsCycleEnd(height int64) bool {
   280  	// adjust to target height
   281  	at := p.AtBlock(height)
   282  	return at.CyclePosition(height)+1 == at.BlocksPerCycle
   283  }
   284  
   285  func (p *Params) IsSnapshotBlock(height int64) bool {
   286  	// no more snapshots in Paris
   287  	if p.Version > 18 && p.IsCycleEnd(height) {
   288  		return true
   289  	}
   290  
   291  	// adjust to target height
   292  	at := p.AtBlock(height)
   293  	pos := at.CyclePosition(height) + 1
   294  	return pos > 0 && pos%at.BlocksPerSnapshot == 0
   295  }
   296  
   297  func (p *Params) SnapshotBlock(cycle int64, index int) int64 {
   298  	// adjust to target cycle
   299  	at := p.AtCycle(cycle)
   300  	base := at.SnapshotBaseCycle(cycle)
   301  	if base < 0 {
   302  		return 0
   303  	}
   304  	offset := int64(index+1) * at.BlocksPerSnapshot
   305  	if offset > at.BlocksPerCycle {
   306  		offset = at.BlocksPerCycle
   307  	}
   308  	return at.CycleStartHeight(base) + offset - 1
   309  }
   310  
   311  func (p *Params) SnapshotIndex(height int64) int {
   312  	// no more snapshots in Paris
   313  	if p.Version > 18 {
   314  		return 15
   315  	}
   316  	// FIX granada early start
   317  	if height == 1589248 && p.IsMainnet() {
   318  		return 15
   319  	}
   320  	// adjust to target height
   321  	at := p.AtBlock(height)
   322  	return int((at.CyclePosition(height)+1)/at.BlocksPerSnapshot) - 1
   323  }