2022-10-26 16:46:41 +00:00
package sidechain
import (
2023-03-05 14:06:49 +00:00
"errors"
2022-10-26 16:46:41 +00:00
"fmt"
2023-05-16 05:14:58 +00:00
"git.gammaspectra.live/P2Pool/moneroutil"
2022-10-26 16:46:41 +00:00
"git.gammaspectra.live/P2Pool/p2pool-observer/monero"
2022-11-07 22:59:52 +00:00
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
2022-10-26 16:46:41 +00:00
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
2023-05-27 12:43:22 +00:00
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
2023-04-16 17:25:24 +00:00
"log"
2022-10-26 16:46:41 +00:00
"strconv"
)
type NetworkType int
const (
NetworkInvalid NetworkType = iota
NetworkMainnet
NetworkTestnet
NetworkStagenet
)
2022-11-03 11:32:07 +00:00
const (
UncleBlockDepth = 3
)
type ConsensusProvider interface {
Consensus ( ) * Consensus
}
2022-10-26 16:46:41 +00:00
func ( n NetworkType ) String ( ) string {
switch n {
case NetworkInvalid :
return "invalid"
case NetworkMainnet :
return "mainnet"
case NetworkTestnet :
return "testnet"
case NetworkStagenet :
return "stagenet"
}
return ""
}
2023-05-16 05:14:58 +00:00
func ( n NetworkType ) AddressNetwork ( ) ( uint8 , error ) {
switch n {
case NetworkInvalid :
return 0 , errors . New ( "invalid network" )
case NetworkMainnet :
return moneroutil . MainNetwork , nil
case NetworkTestnet :
return moneroutil . TestNetwork , nil
case NetworkStagenet :
2023-05-17 10:17:38 +00:00
return moneroutil . StageNetwork , nil
2023-05-16 05:14:58 +00:00
}
return 0 , errors . New ( "unknown network" )
}
2022-10-26 16:46:41 +00:00
func ( n NetworkType ) MarshalJSON ( ) ( [ ] byte , error ) {
2023-05-27 12:43:22 +00:00
return utils . MarshalJSON ( n . String ( ) )
2022-10-26 16:46:41 +00:00
}
func ( n * NetworkType ) UnmarshalJSON ( b [ ] byte ) error {
var s string
2023-05-27 12:43:22 +00:00
if err := utils . UnmarshalJSON ( b , & s ) ; err != nil {
2022-10-26 16:46:41 +00:00
return err
}
switch s {
case "invalid" :
* n = NetworkInvalid
case "" , "mainnet" : //special case for config.json
* n = NetworkMainnet
case "testnet" :
* n = NetworkTestnet
case "stagenet" :
* n = NetworkStagenet
default :
return fmt . Errorf ( "unknown network type %s" , s )
}
return nil
}
type Consensus struct {
NetworkType NetworkType ` json:"network_type" `
PoolName string ` json:"name" `
PoolPassword string ` json:"password" `
TargetBlockTime uint64 ` json:"block_time" `
MinimumDifficulty uint64 ` json:"min_diff" `
ChainWindowSize uint64 ` json:"pplns_window" `
UnclePenalty uint64 ` json:"uncle_penalty" `
2023-04-16 17:25:24 +00:00
// HardFork optional hardfork information for p2pool
HardForks [ ] HardFork ` json:"hard_forks,omitempty" `
2022-10-26 16:46:41 +00:00
2023-04-30 19:49:25 +00:00
hasher randomx . Hasher
2022-10-26 16:46:41 +00:00
id types . Hash
}
const SmallestMinimumDifficulty = 100000
const LargestMinimumDifficulty = 1000000000
func NewConsensus ( networkType NetworkType , poolName , poolPassword string , targetBlockTime , minimumDifficulty , chainWindowSize , unclePenalty uint64 ) * Consensus {
c := & Consensus {
NetworkType : networkType ,
PoolName : poolName ,
PoolPassword : poolPassword ,
TargetBlockTime : targetBlockTime ,
MinimumDifficulty : minimumDifficulty ,
ChainWindowSize : chainWindowSize ,
UnclePenalty : unclePenalty ,
}
2023-03-05 14:06:49 +00:00
if ! c . verify ( ) {
2022-10-26 16:46:41 +00:00
return nil
}
2023-03-05 14:06:49 +00:00
return c
}
func NewConsensusFromJSON ( data [ ] byte ) ( * Consensus , error ) {
var c Consensus
2023-05-27 12:43:22 +00:00
if err := utils . UnmarshalJSON ( data , & c ) ; err != nil {
2023-03-05 14:06:49 +00:00
return nil , err
}
if ! c . verify ( ) {
return nil , errors . New ( "could not verify" )
}
return & c , nil
}
func ( c * Consensus ) verify ( ) bool {
if len ( c . PoolName ) > 128 {
return false
}
2022-10-26 16:46:41 +00:00
if len ( c . PoolPassword ) > 128 {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
if c . TargetBlockTime < 1 || c . TargetBlockTime > monero . BlockTime {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
2023-03-07 17:57:06 +00:00
if c . NetworkType == NetworkMainnet && c . MinimumDifficulty < SmallestMinimumDifficulty || c . MinimumDifficulty > LargestMinimumDifficulty {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
if c . ChainWindowSize < 60 || c . ChainWindowSize > 2160 {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
if c . UnclePenalty < 1 || c . UnclePenalty > 99 {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
var emptyHash types . Hash
c . id = c . CalculateId ( )
if c . id == emptyHash {
2023-03-05 14:06:49 +00:00
return false
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
2023-04-16 17:25:24 +00:00
if len ( c . HardForks ) == 0 {
switch c . NetworkType {
case NetworkMainnet :
c . HardForks = p2poolMainNetHardForks
case NetworkTestnet :
c . HardForks = p2poolTestNetHardForks
case NetworkStagenet :
c . HardForks = p2poolStageNetHardForks
default :
log . Panicf ( "invalid network type for determining hardfork" )
}
}
2023-03-05 14:06:49 +00:00
return true
2022-10-26 16:46:41 +00:00
}
2023-03-07 17:57:06 +00:00
func ( c * Consensus ) CalculateSideTemplateId ( share * PoolBlock ) types . Hash {
2023-05-18 03:14:03 +00:00
buf := make ( [ ] byte , 0 , share . BufferLength ( ) )
buf , _ = share . Main . SideChainHashingBlob ( buf , true )
buf , _ = share . Side . AppendBinary ( buf , share . ShareVersion ( ) )
2022-10-26 16:46:41 +00:00
2023-05-18 03:14:03 +00:00
return crypto . PooledKeccak256 ( buf , c . id [ : ] )
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) CalculateSideChainIdFromBlobs ( mainBlob , sideBlob [ ] byte ) types . Hash {
2023-03-07 17:57:06 +00:00
//TODO: handle extra nonce
2023-03-05 14:06:49 +00:00
return crypto . PooledKeccak256 ( mainBlob , sideBlob , c . id [ : ] )
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) Id ( ) types . Hash {
2022-10-26 16:46:41 +00:00
var h types . Hash
2023-03-05 14:06:49 +00:00
if c . id == h {
2022-10-26 16:46:41 +00:00
//this data race is fine
2023-03-05 14:06:49 +00:00
c . id = c . CalculateId ( )
return c . id
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
return c . id
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) IsDefault ( ) bool {
return c . id == ConsensusDefault . id
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) IsMini ( ) bool {
return c . id == ConsensusMini . id
2022-10-26 16:46:41 +00:00
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) DefaultPort ( ) uint16 {
if c . IsMini ( ) {
2022-11-03 11:32:07 +00:00
return 37888
}
return 37889
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) SeedNode ( ) string {
if c . IsMini ( ) {
2022-12-11 13:46:37 +00:00
return "seeds-mini.p2pool.io"
2023-03-05 14:06:49 +00:00
} else if c . IsDefault ( ) {
2022-12-11 13:46:37 +00:00
return "seeds.p2pool.io"
2022-12-04 14:00:05 +00:00
}
return ""
}
2023-04-30 19:49:25 +00:00
func ( c * Consensus ) InitHasher ( n int , flags ... randomx . Flag ) error {
if c . hasher != nil {
c . hasher . Close ( )
}
var err error
c . hasher , err = randomx . NewRandomX ( n , flags ... )
if err != nil {
return err
}
return nil
}
func ( c * Consensus ) GetHasher ( ) randomx . Hasher {
if c . hasher == nil {
log . Panic ( "hasher has not been initialized in consensus" )
}
return c . hasher
}
2023-03-05 14:06:49 +00:00
func ( c * Consensus ) CalculateId ( ) types . Hash {
2022-10-26 16:46:41 +00:00
var buf [ ] byte
2023-03-05 14:06:49 +00:00
buf = append ( buf , c . NetworkType . String ( ) ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , c . PoolName ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , c . PoolPassword ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , strconv . FormatUint ( c . TargetBlockTime , 10 ) ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , strconv . FormatUint ( c . MinimumDifficulty , 10 ) ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , strconv . FormatUint ( c . ChainWindowSize , 10 ) ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
2023-03-05 14:06:49 +00:00
buf = append ( buf , strconv . FormatUint ( c . UnclePenalty , 10 ) ... )
2022-10-26 16:46:41 +00:00
buf = append ( buf , 0 )
return randomx . ConsensusHash ( buf )
}
2023-04-16 17:25:24 +00:00
var ConsensusDefault = & Consensus { NetworkType : NetworkMainnet , PoolName : "mainnet test 2" , TargetBlockTime : 10 , MinimumDifficulty : 100000 , ChainWindowSize : 2160 , UnclePenalty : 20 , HardForks : p2poolMainNetHardForks , id : types . Hash { 34 , 175 , 126 , 231 , 181 , 11 , 104 , 146 , 227 , 153 , 218 , 107 , 44 , 108 , 68 , 39 , 178 , 81 , 4 , 212 , 169 , 4 , 142 , 0 , 177 , 110 , 157 , 240 , 68 , 7 , 249 , 24 } }
var ConsensusMini = & Consensus { NetworkType : NetworkMainnet , PoolName : "mini" , TargetBlockTime : 10 , MinimumDifficulty : 100000 , ChainWindowSize : 2160 , UnclePenalty : 20 , HardForks : p2poolMainNetHardForks , id : types . Hash { 57 , 130 , 201 , 26 , 149 , 174 , 199 , 250 , 66 , 80 , 189 , 18 , 108 , 216 , 194 , 220 , 136 , 23 , 63 , 24 , 64 , 113 , 221 , 44 , 219 , 86 , 39 , 163 , 53 , 24 , 126 , 196 } }