github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/internal/fakechain/fakechain.go (about) 1 package fakechain 2 3 import ( 4 "errors" 5 "math/big" 6 "sync/atomic" 7 8 "github.com/nspcc-dev/neo-go/pkg/config" 9 "github.com/nspcc-dev/neo-go/pkg/config/netmode" 10 "github.com/nspcc-dev/neo-go/pkg/core/block" 11 "github.com/nspcc-dev/neo-go/pkg/core/interop" 12 "github.com/nspcc-dev/neo-go/pkg/core/mempool" 13 "github.com/nspcc-dev/neo-go/pkg/core/mpt" 14 "github.com/nspcc-dev/neo-go/pkg/core/native" 15 "github.com/nspcc-dev/neo-go/pkg/core/state" 16 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 17 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 18 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 19 "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" 20 "github.com/nspcc-dev/neo-go/pkg/util" 21 ) 22 23 // FakeChain implements the Blockchainer interface, but does not provide real functionality. 24 type FakeChain struct { 25 config.Blockchain 26 *mempool.Pool 27 blocksCh []chan *block.Block 28 Blockheight atomic.Uint32 29 PoolTxF func(*transaction.Transaction) error 30 poolTxWithData func(*transaction.Transaction, any, *mempool.Pool) error 31 blocks map[util.Uint256]*block.Block 32 hdrHashes map[uint32]util.Uint256 33 txs map[util.Uint256]*transaction.Transaction 34 VerifyWitnessF func() (int64, error) 35 MaxVerificationGAS int64 36 NotaryContractScriptHash util.Uint160 37 NotaryDepositExpiration uint32 38 PostBlock []func(func(*transaction.Transaction, *mempool.Pool, bool) bool, *mempool.Pool, *block.Block) 39 UtilityTokenBalance *big.Int 40 } 41 42 // FakeStateSync implements the StateSync interface. 43 type FakeStateSync struct { 44 IsActiveFlag atomic.Bool 45 IsInitializedFlag atomic.Bool 46 RequestHeaders atomic.Bool 47 InitFunc func(h uint32) error 48 TraverseFunc func(root util.Uint256, process func(node mpt.Node, nodeBytes []byte) bool) error 49 AddMPTNodesFunc func(nodes [][]byte) error 50 } 51 52 // NewFakeChain returns a new FakeChain structure. 53 func NewFakeChain() *FakeChain { 54 return NewFakeChainWithCustomCfg(nil) 55 } 56 57 // NewFakeChainWithCustomCfg returns a new FakeChain structure with the specified protocol configuration. 58 func NewFakeChainWithCustomCfg(protocolCfg func(c *config.Blockchain)) *FakeChain { 59 cfg := config.Blockchain{ProtocolConfiguration: config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10}} 60 if protocolCfg != nil { 61 protocolCfg(&cfg) 62 } 63 return &FakeChain{ 64 Pool: mempool.New(10, 0, false, nil), 65 PoolTxF: func(*transaction.Transaction) error { return nil }, 66 poolTxWithData: func(*transaction.Transaction, any, *mempool.Pool) error { return nil }, 67 blocks: make(map[util.Uint256]*block.Block), 68 hdrHashes: make(map[uint32]util.Uint256), 69 txs: make(map[util.Uint256]*transaction.Transaction), 70 Blockchain: cfg, 71 } 72 } 73 74 // PutBlock implements the Blockchainer interface. 75 func (chain *FakeChain) PutBlock(b *block.Block) { 76 chain.blocks[b.Hash()] = b 77 chain.hdrHashes[b.Index] = b.Hash() 78 chain.Blockheight.Store(b.Index) 79 } 80 81 // PutHeader implements the Blockchainer interface. 82 func (chain *FakeChain) PutHeader(b *block.Block) { 83 chain.hdrHashes[b.Index] = b.Hash() 84 } 85 86 // PutTx implements the Blockchainer interface. 87 func (chain *FakeChain) PutTx(tx *transaction.Transaction) { 88 chain.txs[tx.Hash()] = tx 89 } 90 91 // InitVerificationContext initializes context for witness check. 92 func (chain *FakeChain) InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error { 93 panic("TODO") 94 } 95 96 // IsExtensibleAllowed implements the Blockchainer interface. 97 func (*FakeChain) IsExtensibleAllowed(uint160 util.Uint160) bool { 98 return true 99 } 100 101 // GetNatives implements the blockchainer.Blockchainer interface. 102 func (*FakeChain) GetNatives() []state.Contract { 103 panic("TODO") 104 } 105 106 // GetNotaryDepositExpiration implements the Blockchainer interface. 107 func (chain *FakeChain) GetNotaryDepositExpiration(acc util.Uint160) uint32 { 108 if chain.NotaryDepositExpiration != 0 { 109 return chain.NotaryDepositExpiration 110 } 111 panic("TODO") 112 } 113 114 // GetNotaryContractScriptHash implements the Blockchainer interface. 115 func (chain *FakeChain) GetNotaryContractScriptHash() util.Uint160 { 116 if !chain.NotaryContractScriptHash.Equals(util.Uint160{}) { 117 return chain.NotaryContractScriptHash 118 } 119 panic("TODO") 120 } 121 122 // GetNotaryBalance implements the Blockchainer interface. 123 func (chain *FakeChain) GetNotaryBalance(acc util.Uint160) *big.Int { 124 panic("TODO") 125 } 126 127 // GetNotaryServiceFeePerKey implements the Blockchainer interface. 128 func (chain *FakeChain) GetNotaryServiceFeePerKey() int64 { 129 panic("TODO") 130 } 131 132 // GetBaseExecFee implements the Policer interface. 133 func (chain *FakeChain) GetBaseExecFee() int64 { 134 return interop.DefaultBaseExecFee 135 } 136 137 // GetStoragePrice implements the Policer interface. 138 func (chain *FakeChain) GetStoragePrice() int64 { 139 return native.DefaultStoragePrice 140 } 141 142 // GetMaxVerificationGAS implements the Policer interface. 143 func (chain *FakeChain) GetMaxVerificationGAS() int64 { 144 if chain.MaxVerificationGAS != 0 { 145 return chain.MaxVerificationGAS 146 } 147 panic("TODO") 148 } 149 150 // PoolTxWithData implements the Blockchainer interface. 151 func (chain *FakeChain) PoolTxWithData(t *transaction.Transaction, data any, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(t *transaction.Transaction, data any) error) error { 152 return chain.poolTxWithData(t, data, mp) 153 } 154 155 // RegisterPostBlock implements the Blockchainer interface. 156 func (chain *FakeChain) RegisterPostBlock(f func(func(*transaction.Transaction, *mempool.Pool, bool) bool, *mempool.Pool, *block.Block)) { 157 chain.PostBlock = append(chain.PostBlock, f) 158 } 159 160 // GetConfig implements the Blockchainer interface. 161 func (chain *FakeChain) GetConfig() config.Blockchain { 162 return chain.Blockchain 163 } 164 165 // CalculateClaimable implements the Blockchainer interface. 166 func (chain *FakeChain) CalculateClaimable(util.Uint160, uint32) (*big.Int, error) { 167 panic("TODO") 168 } 169 170 // FeePerByte implements Feer interface. 171 func (chain *FakeChain) FeePerByte() int64 { 172 panic("TODO") 173 } 174 175 // P2PSigExtensionsEnabled implements Feer interface. 176 func (chain *FakeChain) P2PSigExtensionsEnabled() bool { 177 return true 178 } 179 180 // AddHeaders implements the Blockchainer interface. 181 func (chain *FakeChain) AddHeaders(...*block.Header) error { 182 panic("TODO") 183 } 184 185 // AddBlock implements the Blockchainer interface. 186 func (chain *FakeChain) AddBlock(block *block.Block) error { 187 if block.Index == chain.Blockheight.Load()+1 { 188 chain.PutBlock(block) 189 } 190 return nil 191 } 192 193 // BlockHeight implements the Feer interface. 194 func (chain *FakeChain) BlockHeight() uint32 { 195 return chain.Blockheight.Load() 196 } 197 198 // HeaderHeight implements the Blockchainer interface. 199 func (chain *FakeChain) HeaderHeight() uint32 { 200 return chain.Blockheight.Load() 201 } 202 203 // GetAppExecResults implements the Blockchainer interface. 204 func (chain *FakeChain) GetAppExecResults(hash util.Uint256, trig trigger.Type) ([]state.AppExecResult, error) { 205 panic("TODO") 206 } 207 208 // GetBlock implements the Blockchainer interface. 209 func (chain *FakeChain) GetBlock(hash util.Uint256) (*block.Block, error) { 210 if b, ok := chain.blocks[hash]; ok { 211 return b, nil 212 } 213 return nil, errors.New("not found") 214 } 215 216 // GetCommittee implements the Blockchainer interface. 217 func (chain *FakeChain) GetCommittee() (keys.PublicKeys, error) { 218 panic("TODO") 219 } 220 221 // GetContractState implements the Blockchainer interface. 222 func (chain *FakeChain) GetContractState(hash util.Uint160) *state.Contract { 223 panic("TODO") 224 } 225 226 // GetContractScriptHash implements the Blockchainer interface. 227 func (chain *FakeChain) GetContractScriptHash(id int32) (util.Uint160, error) { 228 panic("TODO") 229 } 230 231 // GetNativeContractScriptHash implements the Blockchainer interface. 232 func (chain *FakeChain) GetNativeContractScriptHash(name string) (util.Uint160, error) { 233 panic("TODO") 234 } 235 236 // GetHeaderHash implements the Blockchainer interface. 237 func (chain *FakeChain) GetHeaderHash(n uint32) util.Uint256 { 238 return chain.hdrHashes[n] 239 } 240 241 // GetHeader implements the Blockchainer interface. 242 func (chain *FakeChain) GetHeader(hash util.Uint256) (*block.Header, error) { 243 b, err := chain.GetBlock(hash) 244 if err != nil { 245 return nil, err 246 } 247 return &b.Header, nil 248 } 249 250 // GetNextBlockValidators implements the Blockchainer interface. 251 func (chain *FakeChain) GetNextBlockValidators() ([]*keys.PublicKey, error) { 252 panic("TODO") 253 } 254 255 // GetNEP17Contracts implements the Blockchainer interface. 256 func (chain *FakeChain) GetNEP11Contracts() []util.Uint160 { 257 panic("TODO") 258 } 259 260 // GetNEP17Contracts implements the Blockchainer interface. 261 func (chain *FakeChain) GetNEP17Contracts() []util.Uint160 { 262 panic("TODO") 263 } 264 265 // GetNEP17LastUpdated implements the Blockchainer interface. 266 func (chain *FakeChain) GetTokenLastUpdated(acc util.Uint160) (map[int32]uint32, error) { 267 panic("TODO") 268 } 269 270 // ForEachNEP17Transfer implements the Blockchainer interface. 271 func (chain *FakeChain) ForEachNEP11Transfer(util.Uint160, uint64, func(*state.NEP11Transfer) (bool, error)) error { 272 panic("TODO") 273 } 274 275 // ForEachNEP17Transfer implements the Blockchainer interface. 276 func (chain *FakeChain) ForEachNEP17Transfer(util.Uint160, uint64, func(*state.NEP17Transfer) (bool, error)) error { 277 panic("TODO") 278 } 279 280 // GetValidators implements the Blockchainer interface. 281 func (chain *FakeChain) GetValidators() ([]*keys.PublicKey, error) { 282 panic("TODO") 283 } 284 285 // GetEnrollments implements the Blockchainer interface. 286 func (chain *FakeChain) GetEnrollments() ([]state.Validator, error) { 287 panic("TODO") 288 } 289 290 // GetStorageItem implements the Blockchainer interface. 291 func (chain *FakeChain) GetStorageItem(id int32, key []byte) state.StorageItem { 292 panic("TODO") 293 } 294 295 // GetTestVM implements the Blockchainer interface. 296 func (chain *FakeChain) GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) (*interop.Context, error) { 297 panic("TODO") 298 } 299 300 // CurrentBlockHash implements the Blockchainer interface. 301 func (chain *FakeChain) CurrentBlockHash() util.Uint256 { 302 return util.Uint256{} 303 } 304 305 // HasBlock implements the Blockchainer interface. 306 func (chain *FakeChain) HasBlock(h util.Uint256) bool { 307 _, ok := chain.blocks[h] 308 return ok 309 } 310 311 // HasTransaction implements the Blockchainer interface. 312 func (chain *FakeChain) HasTransaction(h util.Uint256) bool { 313 _, ok := chain.txs[h] 314 return ok 315 } 316 317 // GetTransaction implements the Blockchainer interface. 318 func (chain *FakeChain) GetTransaction(h util.Uint256) (*transaction.Transaction, uint32, error) { 319 if tx, ok := chain.txs[h]; ok { 320 return tx, 1, nil 321 } 322 return nil, 0, errors.New("not found") 323 } 324 325 // GetMemPool implements the Blockchainer interface. 326 func (chain *FakeChain) GetMemPool() *mempool.Pool { 327 return chain.Pool 328 } 329 330 // GetGoverningTokenBalance implements the Blockchainer interface. 331 func (chain *FakeChain) GetGoverningTokenBalance(acc util.Uint160) (*big.Int, uint32) { 332 panic("TODO") 333 } 334 335 // GetUtilityTokenBalance implements Feer interface. 336 func (chain *FakeChain) GetUtilityTokenBalance(uint160 util.Uint160) *big.Int { 337 if chain.UtilityTokenBalance != nil { 338 return chain.UtilityTokenBalance 339 } 340 panic("TODO") 341 } 342 343 // PoolTx implements the Blockchainer interface. 344 func (chain *FakeChain) PoolTx(tx *transaction.Transaction, _ ...*mempool.Pool) error { 345 return chain.PoolTxF(tx) 346 } 347 348 // SubscribeForBlocks implements the Blockchainer interface. 349 func (chain *FakeChain) SubscribeForBlocks(ch chan *block.Block) { 350 chain.blocksCh = append(chain.blocksCh, ch) 351 } 352 353 // SubscribeForExecutions implements the Blockchainer interface. 354 func (chain *FakeChain) SubscribeForExecutions(ch chan *state.AppExecResult) { 355 panic("TODO") 356 } 357 358 // SubscribeForNotifications implements the Blockchainer interface. 359 func (chain *FakeChain) SubscribeForNotifications(ch chan *state.ContainedNotificationEvent) { 360 panic("TODO") 361 } 362 363 // SubscribeForTransactions implements the Blockchainer interface. 364 func (chain *FakeChain) SubscribeForTransactions(ch chan *transaction.Transaction) { 365 panic("TODO") 366 } 367 368 // VerifyTx implements the Blockchainer interface. 369 func (chain *FakeChain) VerifyTx(*transaction.Transaction) error { 370 panic("TODO") 371 } 372 373 // VerifyWitness implements the Blockchainer interface. 374 func (chain *FakeChain) VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) (int64, error) { 375 if chain.VerifyWitnessF != nil { 376 return chain.VerifyWitnessF() 377 } 378 panic("TODO") 379 } 380 381 // UnsubscribeFromBlocks implements the Blockchainer interface. 382 func (chain *FakeChain) UnsubscribeFromBlocks(ch chan *block.Block) { 383 for i, c := range chain.blocksCh { 384 if c == ch { 385 if i < len(chain.blocksCh) { 386 copy(chain.blocksCh[i:], chain.blocksCh[i+1:]) 387 } 388 chain.blocksCh = chain.blocksCh[:len(chain.blocksCh)] 389 } 390 } 391 } 392 393 // UnsubscribeFromExecutions implements the Blockchainer interface. 394 func (chain *FakeChain) UnsubscribeFromExecutions(ch chan *state.AppExecResult) { 395 panic("TODO") 396 } 397 398 // UnsubscribeFromNotifications implements the Blockchainer interface. 399 func (chain *FakeChain) UnsubscribeFromNotifications(ch chan *state.ContainedNotificationEvent) { 400 panic("TODO") 401 } 402 403 // UnsubscribeFromTransactions implements the Blockchainer interface. 404 func (chain *FakeChain) UnsubscribeFromTransactions(ch chan *transaction.Transaction) { 405 panic("TODO") 406 } 407 408 // AddBlock implements the StateSync interface. 409 func (s *FakeStateSync) AddBlock(block *block.Block) error { 410 panic("TODO") 411 } 412 413 // AddHeaders implements the StateSync interface. 414 func (s *FakeStateSync) AddHeaders(...*block.Header) error { 415 panic("TODO") 416 } 417 418 // AddMPTNodes implements the StateSync interface. 419 func (s *FakeStateSync) AddMPTNodes(nodes [][]byte) error { 420 if s.AddMPTNodesFunc != nil { 421 return s.AddMPTNodesFunc(nodes) 422 } 423 panic("TODO") 424 } 425 426 // BlockHeight implements the StateSync interface. 427 func (s *FakeStateSync) BlockHeight() uint32 { 428 return 0 429 } 430 431 // IsActive implements the StateSync interface. 432 func (s *FakeStateSync) IsActive() bool { return s.IsActiveFlag.Load() } 433 434 // IsInitialized implements the StateSync interface. 435 func (s *FakeStateSync) IsInitialized() bool { 436 return s.IsInitializedFlag.Load() 437 } 438 439 // Init implements the StateSync interface. 440 func (s *FakeStateSync) Init(currChainHeight uint32) error { 441 if s.InitFunc != nil { 442 return s.InitFunc(currChainHeight) 443 } 444 panic("TODO") 445 } 446 447 // NeedHeaders implements the StateSync interface. 448 func (s *FakeStateSync) NeedHeaders() bool { return s.RequestHeaders.Load() } 449 450 // NeedMPTNodes implements the StateSync interface. 451 func (s *FakeStateSync) NeedMPTNodes() bool { 452 panic("TODO") 453 } 454 455 // Traverse implements the StateSync interface. 456 func (s *FakeStateSync) Traverse(root util.Uint256, process func(node mpt.Node, nodeBytes []byte) bool) error { 457 if s.TraverseFunc != nil { 458 return s.TraverseFunc(root, process) 459 } 460 panic("TODO") 461 } 462 463 // GetUnknownMPTNodesBatch implements the StateSync interface. 464 func (s *FakeStateSync) GetUnknownMPTNodesBatch(limit int) []util.Uint256 { 465 panic("TODO") 466 }