github.com/Gessiux/neatchain@v1.3.1/chain/neatchain/cross_chain.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "math/big" 8 "regexp" 9 "strings" 10 "sync" 11 "time" 12 "unicode/utf8" 13 14 "github.com/Gessiux/go-crypto" 15 dbm "github.com/Gessiux/go-db" 16 "github.com/Gessiux/neatchain/chain/consensus" 17 "github.com/Gessiux/neatchain/chain/consensus/neatcon/epoch" 18 ntcTypes "github.com/Gessiux/neatchain/chain/consensus/neatcon/types" 19 "github.com/Gessiux/neatchain/chain/core" 20 "github.com/Gessiux/neatchain/chain/core/rawdb" 21 "github.com/Gessiux/neatchain/chain/core/state" 22 "github.com/Gessiux/neatchain/chain/core/types" 23 "github.com/Gessiux/neatchain/chain/log" 24 "github.com/Gessiux/neatchain/chain/trie" 25 neatAbi "github.com/Gessiux/neatchain/neatabi/abi" 26 "github.com/Gessiux/neatchain/neatcli" 27 "github.com/Gessiux/neatchain/neatdb" 28 "github.com/Gessiux/neatchain/neatptc" 29 "github.com/Gessiux/neatchain/network/node" 30 "github.com/Gessiux/neatchain/params" 31 "github.com/Gessiux/neatchain/utilities/common" 32 "github.com/Gessiux/neatchain/utilities/common/math" 33 "github.com/Gessiux/neatchain/utilities/rlp" 34 ) 35 36 type CrossChainHelper struct { 37 mtx sync.Mutex 38 chainInfoDB dbm.DB 39 localTX3CacheDB neatdb.Database 40 //the client does only connect to main chain 41 client *neatcli.Client 42 mainChainId string 43 } 44 45 func (cch *CrossChainHelper) GetMutex() *sync.Mutex { 46 return &cch.mtx 47 } 48 49 func (cch *CrossChainHelper) GetChainInfoDB() dbm.DB { 50 return cch.chainInfoDB 51 } 52 53 func (cch *CrossChainHelper) GetClient() *neatcli.Client { 54 return cch.client 55 } 56 57 func (cch *CrossChainHelper) GetMainChainId() string { 58 return cch.mainChainId 59 } 60 61 // CanCreateSideChain check the condition before send the create side chain into the tx pool 62 func (cch *CrossChainHelper) CanCreateSideChain(from common.Address, chainId string, minValidators uint16, minDepositAmount, startupCost *big.Int, startBlock, endBlock *big.Int) error { 63 64 if chainId == "" || strings.Contains(chainId, ";") { 65 return errors.New("chainId is nil or empty, or contains ';', should be meaningful") 66 } 67 68 pass, _ := regexp.MatchString("^[a-z]+[a-z0-9_]*$", chainId) 69 if !pass { 70 return errors.New("chainId must be start with letter (a-z) and contains alphanumeric(lower case) or underscore, try use other name instead") 71 } 72 73 if utf8.RuneCountInString(chainId) > 30 { 74 return errors.New("max characters of chain id is 30, try use other name instead") 75 } 76 77 if chainId == MainChain || chainId == TestnetChain { 78 return errors.New("you can't create NeatChain as a side chain, try use other name instead") 79 } 80 81 // Check if "chainId" has been created 82 ci := core.GetChainInfo(cch.chainInfoDB, chainId) 83 if ci != nil { 84 return fmt.Errorf("Chain %s has already exist, try use other name instead", chainId) 85 } 86 87 // Check if "chainId" has been registered 88 cci := core.GetPendingSideChainData(cch.chainInfoDB, chainId) 89 if cci != nil { 90 return fmt.Errorf("Chain %s has already applied, try use other name instead", chainId) 91 } 92 93 // Check the minimum validators 94 if minValidators < core.OFFICIAL_MINIMUM_VALIDATORS { 95 return fmt.Errorf("Validators count is not meet the minimum official validator count (%v)", core.OFFICIAL_MINIMUM_VALIDATORS) 96 } 97 98 // Check the minimum deposit amount 99 officialMinimumDeposit := math.MustParseBig256(core.OFFICIAL_MINIMUM_DEPOSIT) 100 if minDepositAmount.Cmp(officialMinimumDeposit) == -1 { 101 return fmt.Errorf("Deposit amount is not meet the minimum official deposit amount (%v PI)", new(big.Int).Div(officialMinimumDeposit, big.NewInt(params.NEAT))) 102 } 103 104 // Check the startup cost 105 if startupCost.Cmp(officialMinimumDeposit) != 0 { 106 return fmt.Errorf("Startup cost is not meet the required amount (%v PI)", new(big.Int).Div(officialMinimumDeposit, big.NewInt(params.NEAT))) 107 } 108 109 // Check start/end block 110 if startBlock.Cmp(endBlock) >= 0 { 111 return errors.New("start block number must be less than end block number") 112 } 113 114 // Check End Block already passed 115 neatchain := MustGetNeatChainFromNode(chainMgr.mainChain.NeatNode) 116 currentBlock := neatchain.BlockChain().CurrentBlock() 117 if endBlock.Cmp(currentBlock.Number()) <= 0 { 118 return errors.New("end block number has already passed") 119 } 120 121 return nil 122 } 123 124 // CreateSideChain Save the Side Chain Data into the DB, the data will be used later during Block Commit Callback 125 func (cch *CrossChainHelper) CreateSideChain(from common.Address, chainId string, minValidators uint16, minDepositAmount *big.Int, startBlock, endBlock *big.Int) error { 126 log.Debug("CreateSideChain - start") 127 128 cci := &core.CoreChainInfo{ 129 Owner: from, 130 ChainId: chainId, 131 MinValidators: minValidators, 132 MinDepositAmount: minDepositAmount, 133 StartBlock: startBlock, 134 EndBlock: endBlock, 135 JoinedValidators: make([]core.JoinedValidator, 0), 136 } 137 core.CreatePendingSideChainData(cch.chainInfoDB, cci) 138 139 log.Debug("CreateSideChain - end") 140 return nil 141 } 142 143 // ValidateJoinSideChain check the criteria whether it meets the join side chain requirement 144 func (cch *CrossChainHelper) ValidateJoinSideChain(from common.Address, consensusPubkey []byte, chainId string, depositAmount *big.Int, signature []byte) error { 145 log.Debug("ValidateJoinSideChain - start") 146 147 if chainId == MainChain || chainId == TestnetChain { 148 return errors.New("you can't join NeatChain as a side chain, try use other name instead") 149 } 150 151 // Check Signature of the PubKey matched against the Address 152 if err := crypto.CheckConsensusPubKey(from, consensusPubkey, signature); err != nil { 153 return err 154 } 155 156 // Check if "chainId" has been created/registered 157 ci := core.GetPendingSideChainData(cch.chainInfoDB, chainId) 158 if ci == nil { 159 if core.GetChainInfo(cch.chainInfoDB, chainId) != nil { 160 return fmt.Errorf("chain %s has already created/started, try use other name instead", chainId) 161 } else { 162 return fmt.Errorf("side chain %s not exist, try use other name instead", chainId) 163 } 164 } 165 166 // Check if already joined the chain 167 find := false 168 for _, joined := range ci.JoinedValidators { 169 if from == joined.Address { 170 find = true 171 break 172 } 173 } 174 175 if find { 176 return errors.New(fmt.Sprintf("You have already joined the Side Chain %s", chainId)) 177 } 178 179 // Check the deposit amount 180 if !(depositAmount != nil && depositAmount.Sign() == 1) { 181 return errors.New("deposit amount must be greater than 0") 182 } 183 184 log.Debug("ValidateJoinSideChain - end") 185 return nil 186 } 187 188 // JoinSideChain Join the Side Chain 189 func (cch *CrossChainHelper) JoinSideChain(from common.Address, pubkey crypto.PubKey, chainId string, depositAmount *big.Int) error { 190 log.Debug("JoinSideChain - start") 191 192 // Load the Side Chain first 193 ci := core.GetPendingSideChainData(cch.chainInfoDB, chainId) 194 if ci == nil { 195 log.Errorf("JoinSideChain - Side Chain %s not exist, you can't join the chain", chainId) 196 return fmt.Errorf("Side Chain %s not exist, you can't join the chain", chainId) 197 } 198 199 for _, joined := range ci.JoinedValidators { 200 if from == joined.Address { 201 return nil 202 } 203 } 204 205 jv := core.JoinedValidator{ 206 PubKey: pubkey, 207 Address: from, 208 DepositAmount: depositAmount, 209 } 210 211 ci.JoinedValidators = append(ci.JoinedValidators, jv) 212 213 core.UpdatePendingSideChainData(cch.chainInfoDB, ci) 214 215 log.Debug("JoinSideChain - end") 216 return nil 217 } 218 219 func (cch *CrossChainHelper) ReadyForLaunchSideChain(height *big.Int, stateDB *state.StateDB) ([]string, []byte, []string) { 220 //log.Debug("ReadyForLaunchSideChain - start") 221 222 readyId, updateBytes, removedId := core.GetSideChainForLaunch(cch.chainInfoDB, height, stateDB) 223 if len(readyId) == 0 { 224 //log.Debugf("ReadyForLaunchSideChain - No side chain to be launch in Block %v", height) 225 } else { 226 //log.Infof("ReadyForLaunchSideChain - %v side chain(s) to be launch in Block %v. %v", len(readyId), height, readyId) 227 } 228 229 //log.Debug("ReadyForLaunchSideChain - end") 230 return readyId, updateBytes, removedId 231 } 232 233 func (cch *CrossChainHelper) ProcessPostPendingData(newPendingIdxBytes []byte, deleteSideChainIds []string) { 234 core.ProcessPostPendingData(cch.chainInfoDB, newPendingIdxBytes, deleteSideChainIds) 235 } 236 237 func (cch *CrossChainHelper) VoteNextEpoch(ep *epoch.Epoch, from common.Address, voteHash common.Hash, txHash common.Hash) error { 238 239 voteSet := ep.GetNextEpoch().GetEpochValidatorVoteSet() 240 if voteSet == nil { 241 voteSet = epoch.NewEpochValidatorVoteSet() 242 } 243 244 vote, exist := voteSet.GetVoteByAddress(from) 245 246 if exist { 247 // Overwrite the Previous Hash Vote 248 vote.VoteHash = voteHash 249 vote.TxHash = txHash 250 } else { 251 // Create a new Hash Vote 252 vote = &epoch.EpochValidatorVote{ 253 Address: from, 254 VoteHash: voteHash, 255 TxHash: txHash, 256 } 257 voteSet.StoreVote(vote) 258 } 259 // Save the VoteSet 260 epoch.SaveEpochVoteSet(ep.GetDB(), ep.GetNextEpoch().Number, voteSet) 261 return nil 262 } 263 264 func (cch *CrossChainHelper) RevealVote(ep *epoch.Epoch, from common.Address, pubkey crypto.PubKey, depositAmount *big.Int, salt string, txHash common.Hash) error { 265 266 voteSet := ep.GetNextEpoch().GetEpochValidatorVoteSet() 267 vote, exist := voteSet.GetVoteByAddress(from) 268 269 if exist { 270 // Update the Hash Vote with Real Data 271 vote.PubKey = pubkey 272 vote.Amount = depositAmount 273 vote.Salt = salt 274 vote.TxHash = txHash 275 } 276 // Save the VoteSet 277 epoch.SaveEpochVoteSet(ep.GetDB(), ep.GetNextEpoch().Number, voteSet) 278 return nil 279 } 280 281 func (cch *CrossChainHelper) UpdateNextEpoch(ep *epoch.Epoch, from common.Address, pubkey crypto.PubKey, depositAmount *big.Int, salt string, txHash common.Hash) error { 282 voteSet := ep.GetNextEpoch().GetEpochValidatorVoteSet() 283 if voteSet == nil { 284 voteSet = epoch.NewEpochValidatorVoteSet() 285 } 286 287 vote, exist := voteSet.GetVoteByAddress(from) 288 289 if exist { 290 vote.Amount = depositAmount 291 vote.TxHash = txHash 292 } else { 293 vote = &epoch.EpochValidatorVote{ 294 Address: from, 295 PubKey: pubkey, 296 Amount: depositAmount, 297 Salt: "neatchain", 298 TxHash: txHash, 299 } 300 301 voteSet.StoreVote(vote) 302 } 303 304 // Save the VoteSet 305 epoch.SaveEpochVoteSet(ep.GetDB(), ep.GetNextEpoch().Number, voteSet) 306 return nil 307 } 308 309 func (cch *CrossChainHelper) GetHeightFromMainChain() *big.Int { 310 neatchain := MustGetNeatChainFromNode(chainMgr.mainChain.NeatNode) 311 return neatchain.BlockChain().CurrentBlock().Number() 312 } 313 314 func (cch *CrossChainHelper) GetTxFromMainChain(txHash common.Hash) *types.Transaction { 315 neatchain := MustGetNeatChainFromNode(chainMgr.mainChain.NeatNode) 316 chainDb := neatchain.ChainDb() 317 318 tx, _, _, _ := rawdb.ReadTransaction(chainDb, txHash) 319 return tx 320 } 321 322 func (cch *CrossChainHelper) GetEpochFromMainChain() (string, *epoch.Epoch) { 323 neatchain := MustGetNeatChainFromNode(chainMgr.mainChain.NeatNode) 324 var ep *epoch.Epoch 325 if neatcon, ok := neatchain.Engine().(consensus.NeatCon); ok { 326 ep = neatcon.GetEpoch() 327 } 328 return neatchain.ChainConfig().NeatChainId, ep 329 } 330 331 func (cch *CrossChainHelper) ChangeValidators(chainId string) { 332 333 if chainMgr == nil { 334 return 335 } 336 337 var chain *Chain = nil 338 if chainId == MainChain || chainId == TestnetChain { 339 chain = chainMgr.mainChain 340 } else if chn, ok := chainMgr.sideChains[chainId]; ok { 341 chain = chn 342 } 343 344 if chain == nil || chain.NeatNode == nil { 345 return 346 } 347 348 if address, ok := chainMgr.getNodeValidator(chain.NeatNode); ok { 349 chainMgr.server.AddLocalValidator(chainId, address) 350 } 351 } 352 353 // verify the signature of validators who voted for the block 354 // most of the logic here is from 'VerifyHeader' 355 func (cch *CrossChainHelper) VerifySideChainProofData(bs []byte) error { 356 357 log.Debug("VerifySideChainProofData - start") 358 359 var proofData types.SideChainProofData 360 err := rlp.DecodeBytes(bs, &proofData) 361 if err != nil { 362 return err 363 } 364 365 header := proofData.Header 366 // Don't waste time checking blocks from the future 367 if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { 368 //return errors.New("block in the future") 369 } 370 371 ncExtra, err := ntcTypes.ExtractNeatConExtra(header) 372 if err != nil { 373 return err 374 } 375 376 chainId := ncExtra.ChainID 377 if chainId == "" || chainId == MainChain || chainId == TestnetChain { 378 return fmt.Errorf("invalid side chain id: %s", chainId) 379 } 380 381 if header.Nonce != (types.NeatConEmptyNonce) && !bytes.Equal(header.Nonce[:], types.NeatConNonce) { 382 return errors.New("invalid nonce") 383 } 384 385 if header.MixDigest != types.NeatConDigest { 386 return errors.New("invalid mix digest") 387 } 388 389 if header.UncleHash != types.NeatConNilUncleHash { 390 return errors.New("invalid uncle Hash") 391 } 392 393 if header.Difficulty == nil || header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 { 394 return errors.New("invalid difficulty") 395 } 396 397 // special case: epoch 0 update 398 // TODO: how to verify this block which includes epoch 0? 399 if ncExtra.EpochBytes != nil && len(ncExtra.EpochBytes) != 0 { 400 ep := epoch.FromBytes(ncExtra.EpochBytes) 401 if ep != nil && ep.Number == 0 { 402 return nil 403 } 404 } 405 406 // Bypass the validator check for official side chain 0 407 // TODO where need 408 if chainId != "side_0" { 409 ci := core.GetChainInfo(cch.chainInfoDB, chainId) 410 if ci == nil { 411 return fmt.Errorf("chain info %s not found", chainId) 412 } 413 epoch := ci.GetEpochByBlockNumber(ncExtra.Height) 414 if epoch == nil { 415 return fmt.Errorf("could not get epoch for block height %v", ncExtra.Height) 416 } 417 valSet := epoch.Validators 418 if !bytes.Equal(valSet.Hash(), ncExtra.ValidatorsHash) { 419 return errors.New("inconsistent validator set") 420 } 421 422 seenCommit := ncExtra.SeenCommit 423 if !bytes.Equal(ncExtra.SeenCommitHash, seenCommit.Hash()) { 424 return errors.New("invalid committed seals") 425 } 426 427 if err = valSet.VerifyCommit(ncExtra.ChainID, ncExtra.Height, seenCommit); err != nil { 428 return err 429 } 430 } 431 432 log.Debug("VerifySideChainProofData - end") 433 return nil 434 } 435 436 func (cch *CrossChainHelper) SaveSideChainProofDataToMainChain(bs []byte) error { 437 log.Debug("SaveSideChainProofDataToMainChain - start") 438 439 var proofData types.SideChainProofData 440 err := rlp.DecodeBytes(bs, &proofData) 441 if err != nil { 442 return err 443 } 444 445 header := proofData.Header 446 ncExtra, err := ntcTypes.ExtractNeatConExtra(header) 447 if err != nil { 448 return err 449 } 450 451 chainId := ncExtra.ChainID 452 if chainId == "" || chainId == MainChain || chainId == TestnetChain { 453 return fmt.Errorf("invalid side chain id: %s", chainId) 454 } 455 456 // here is epoch update; should be a more general mechanism 457 if len(ncExtra.EpochBytes) != 0 { 458 ep := epoch.FromBytes(ncExtra.EpochBytes) 459 if ep != nil { 460 ci := core.GetChainInfo(cch.chainInfoDB, ncExtra.ChainID) 461 // ChainInfo is nil means we need to wait for Side Chain to be launched, this could happened during catch-up scenario 462 if ci == nil { 463 for { 464 // wait for 3 sec and try again 465 time.Sleep(3 * time.Second) 466 ci = core.GetChainInfo(cch.chainInfoDB, ncExtra.ChainID) 467 if ci != nil { 468 break 469 } 470 } 471 } 472 473 futureEpoch := ep.Number > ci.EpochNumber && ncExtra.Height < ep.StartBlock 474 if futureEpoch { 475 // Future Epoch, just save the Epoch into Chain Info DB 476 core.SaveFutureEpoch(cch.chainInfoDB, ep, chainId) 477 log.Infof("Future epoch saved from chain: %s, epoch: %v", chainId, ep) 478 } else if ep.Number == 0 || ep.Number >= ci.EpochNumber { 479 // New Epoch, save or update the Epoch into Chain Info DB 480 ci.EpochNumber = ep.Number 481 ci.Epoch = ep 482 core.SaveChainInfo(cch.chainInfoDB, ci) 483 log.Infof("Epoch saved from chain: %s, epoch: %v", chainId, ep) 484 } 485 } 486 } 487 488 log.Debug("SaveSideChainProofDataToMainChain - end") 489 return nil 490 } 491 492 func (cch *CrossChainHelper) ValidateTX3ProofData(proofData *types.TX3ProofData) error { 493 log.Debug("ValidateTX3ProofData - start") 494 495 header := proofData.Header 496 // Don't waste time checking blocks from the future 497 if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { 498 //return errors.New("block in the future") 499 } 500 501 ncExtra, err := ntcTypes.ExtractNeatConExtra(header) 502 if err != nil { 503 return err 504 } 505 506 chainId := ncExtra.ChainID 507 if chainId == "" || chainId == MainChain || chainId == TestnetChain { 508 return fmt.Errorf("invalid side chain id: %s", chainId) 509 } 510 511 if header.Nonce != (types.NeatConEmptyNonce) && !bytes.Equal(header.Nonce[:], types.NeatConNonce) { 512 return errors.New("invalid nonce") 513 } 514 515 if header.MixDigest != types.NeatConDigest { 516 return errors.New("invalid mix digest") 517 } 518 519 if header.UncleHash != types.NeatConNilUncleHash { 520 return errors.New("invalid uncle Hash") 521 } 522 523 if header.Difficulty == nil || header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 { 524 return errors.New("invalid difficulty") 525 } 526 527 // special case: epoch 0 update 528 // TODO: how to verify this block which includes epoch 0? 529 if ncExtra.EpochBytes != nil && len(ncExtra.EpochBytes) != 0 { 530 ep := epoch.FromBytes(ncExtra.EpochBytes) 531 if ep != nil && ep.Number == 0 { 532 return nil 533 } 534 } 535 536 ci := core.GetChainInfo(cch.chainInfoDB, chainId) 537 if ci == nil { 538 return fmt.Errorf("chain info %s not found", chainId) 539 } 540 epoch := ci.GetEpochByBlockNumber(ncExtra.Height) 541 if epoch == nil { 542 return fmt.Errorf("could not get epoch for block height %v", ncExtra.Height) 543 } 544 valSet := epoch.Validators 545 if !bytes.Equal(valSet.Hash(), ncExtra.ValidatorsHash) { 546 return errors.New("inconsistent validator set") 547 } 548 549 seenCommit := ncExtra.SeenCommit 550 if !bytes.Equal(ncExtra.SeenCommitHash, seenCommit.Hash()) { 551 return errors.New("invalid committed seals") 552 } 553 554 if err = valSet.VerifyCommit(ncExtra.ChainID, ncExtra.Height, seenCommit); err != nil { 555 return err 556 } 557 558 // tx merkle proof verify 559 keybuf := new(bytes.Buffer) 560 for i, txIndex := range proofData.TxIndexs { 561 keybuf.Reset() 562 rlp.Encode(keybuf, uint(txIndex)) 563 _, _, err := trie.VerifyProof(header.TxHash, keybuf.Bytes(), proofData.TxProofs[i]) 564 if err != nil { 565 return err 566 } 567 } 568 569 log.Debug("ValidateTX3ProofData - end") 570 return nil 571 } 572 573 func (cch *CrossChainHelper) ValidateTX4WithInMemTX3ProofData(tx4 *types.Transaction, tx3ProofData *types.TX3ProofData) error { 574 // TX4 575 signer := types.NewEIP155Signer(tx4.ChainId()) 576 from, err := types.Sender(signer, tx4) 577 if err != nil { 578 return core.ErrInvalidSender 579 } 580 581 var args neatAbi.WithdrawFromMainChainArgs 582 583 if !neatAbi.IsNeatChainContractAddr(tx4.To()) { 584 return errors.New("invalid TX4: wrong To()") 585 } 586 587 data := tx4.Data() 588 function, err := neatAbi.FunctionTypeFromId(data[:4]) 589 if err != nil { 590 return err 591 } 592 593 if function != neatAbi.WithdrawFromMainChain { 594 return errors.New("invalid TX4: wrong function") 595 } 596 597 if err := neatAbi.ChainABI.UnpackMethodInputs(&args, neatAbi.WithdrawFromMainChain.String(), data[4:]); err != nil { 598 return err 599 } 600 601 // TX3 602 header := tx3ProofData.Header 603 if err != nil { 604 return err 605 } 606 keybuf := new(bytes.Buffer) 607 rlp.Encode(keybuf, tx3ProofData.TxIndexs[0]) 608 val, _, err := trie.VerifyProof(header.TxHash, keybuf.Bytes(), tx3ProofData.TxProofs[0]) 609 if err != nil { 610 return err 611 } 612 613 var tx3 types.Transaction 614 err = rlp.DecodeBytes(val, &tx3) 615 if err != nil { 616 return err 617 } 618 619 signer2 := types.NewEIP155Signer(tx3.ChainId()) 620 tx3From, err := types.Sender(signer2, &tx3) 621 if err != nil { 622 return core.ErrInvalidSender 623 } 624 625 var tx3Args neatAbi.WithdrawFromSideChainArgs 626 tx3Data := tx3.Data() 627 if err := neatAbi.ChainABI.UnpackMethodInputs(&tx3Args, neatAbi.WithdrawFromSideChain.String(), tx3Data[4:]); err != nil { 628 return err 629 } 630 631 // Does TX3 & TX4 Match 632 if from != tx3From || args.ChainId != tx3Args.ChainId || args.Amount.Cmp(tx3.Value()) != 0 { 633 return errors.New("params are not consistent with tx in side chain") 634 } 635 636 return nil 637 } 638 639 //SaveDataToMainV1 acceps both epoch and tx3 640 //func (cch *CrossChainHelper) VerifySideChainProofDataV1(proofData *types.SideChainProofDataV1) error { 641 // 642 // log.Debug("VerifySideChainProofDataV1 - start") 643 // 644 // header := proofData.Header 645 // // Don't waste time checking blocks from the future 646 // if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { 647 // //return errors.New("block in the future") 648 // } 649 // 650 // ncExtra, err := ntcTypes.ExtractNeatConExtra(header) 651 // if err != nil { 652 // return err 653 // } 654 // 655 // chainId := ncExtra.ChainID 656 // if chainId == "" || chainId == MainChain || chainId == TestnetChain { 657 // return fmt.Errorf("invalid side chain id: %s", chainId) 658 // } 659 // 660 // if header.Nonce != (types.NeatConEmptyNonce) && !bytes.Equal(header.Nonce[:], types.NeatConNonce) { 661 // return errors.New("invalid nonce") 662 // } 663 // 664 // if header.MixDigest != types.NeatConDigest { 665 // return errors.New("invalid mix digest") 666 // } 667 // 668 // if header.UncleHash != types.NeatConNilUncleHash { 669 // return errors.New("invalid uncle Hash") 670 // } 671 // 672 // if header.Difficulty == nil || header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 { 673 // return errors.New("invalid difficulty") 674 // } 675 // 676 // ci := core.GetChainInfo(cch.chainInfoDB, chainId) 677 // if ci == nil { 678 // return fmt.Errorf("chain info %s not found", chainId) 679 // } 680 // 681 // isSd2mc := params.IsSd2mc(cch.GetMainChainId(), cch.GetHeightFromMainChain()) 682 // // Bypass the validator check for official side chain 0 683 // if chainId != "side_0" || isSd2mc { 684 // 685 // getValidatorsFromChainInfo := false 686 // if ncExtra.EpochBytes != nil && len(ncExtra.EpochBytes) != 0 { 687 // ep := epoch.FromBytes(ncExtra.EpochBytes) 688 // if ep != nil && ep.Number == 0 { 689 // //Side chain just created and save the epoch info, get validators from chain info 690 // getValidatorsFromChainInfo = true 691 // } 692 // } 693 // 694 // var valSet *ntcTypes.ValidatorSet = nil 695 // if !getValidatorsFromChainInfo { 696 // ep := ci.GetEpochByBlockNumber(ncExtra.Height) 697 // if ep == nil { 698 // return fmt.Errorf("could not get epoch for block height %v", ncExtra.Height) 699 // } 700 // valSet = ep.Validators 701 // } else { 702 // _, ntcGenesis := core.LoadChainGenesis(cch.chainInfoDB, chainId) 703 // if ntcGenesis == nil { 704 // return errors.New(fmt.Sprintf("unable to retrieve the genesis file for side chain %s", chainId)) 705 // } 706 // coreGenesis, err := ntcTypes.GenesisDocFromJSON(ntcGenesis) 707 // if err != nil { 708 // return err 709 // } 710 // 711 // ep := epoch.MakeOneEpoch(nil, &coreGenesis.CurrentEpoch, nil) 712 // if ep == nil { 713 // return fmt.Errorf("could not get epoch for genesis information") 714 // } 715 // valSet = ep.Validators 716 // } 717 // 718 // if !bytes.Equal(valSet.Hash(), ncExtra.ValidatorsHash) { 719 // return errors.New("inconsistent validator set") 720 // } 721 // 722 // seenCommit := ncExtra.SeenCommit 723 // if !bytes.Equal(ncExtra.SeenCommitHash, seenCommit.Hash()) { 724 // return errors.New("invalid committed seals") 725 // } 726 // 727 // if err = valSet.VerifyCommit(ncExtra.ChainID, ncExtra.Height, seenCommit); err != nil { 728 // return err 729 // } 730 // } 731 // 732 // //Verify Tx3 733 // // tx merkle proof verify 734 // keybuf := new(bytes.Buffer) 735 // for i, txIndex := range proofData.TxIndexs { 736 // keybuf.Reset() 737 // rlp.Encode(keybuf, uint(txIndex)) 738 // _, _, err := trie.VerifyProof(header.TxHash, keybuf.Bytes(), proofData.TxProofs[i]) 739 // if err != nil { 740 // return err 741 // } 742 // } 743 // 744 // log.Debug("VerifySideChainProofDataV1 - end") 745 // return nil 746 //} 747 // 748 //func (cch *CrossChainHelper) SaveSideChainProofDataToMainChainV1(proofData *types.SideChainProofDataV1) error { 749 // log.Info("SaveSideChainProofDataToMainChainV1 - start") 750 // 751 // header := proofData.Header 752 // ncExtra, err := ntcTypes.ExtractNeatConExtra(header) 753 // if err != nil { 754 // return err 755 // } 756 // 757 // chainId := ncExtra.ChainID 758 // if chainId == "" || chainId == MainChain || chainId == TestnetChain { 759 // return fmt.Errorf("invalid side chain id: %s", chainId) 760 // } 761 // 762 // // here is epoch update; should be a more general mechanism 763 // if len(ncExtra.EpochBytes) != 0 { 764 // log.Info("SaveSideChainProofDataToMainChainV1 - Save Epoch") 765 // ep := epoch.FromBytes(ncExtra.EpochBytes) 766 // if ep != nil { 767 // ci := core.GetChainInfo(cch.chainInfoDB, ncExtra.ChainID) 768 // // ChainInfo is nil means we need to wait for Side Chain to be launched, this could happened during catch-up scenario 769 // if ci == nil { 770 // return fmt.Errorf("not possible to pass verification") 771 // } 772 // 773 // futureEpoch := ep.Number > ci.EpochNumber && ncExtra.Height < ep.StartBlock 774 // if futureEpoch { 775 // // Future Epoch, just save the Epoch into Chain Info DB 776 // core.SaveFutureEpoch(cch.chainInfoDB, ep, chainId) 777 // } else if ep.Number == 0 || ep.Number >= ci.EpochNumber { 778 // // New Epoch, save or update the Epoch into Chain Info DB 779 // ci.EpochNumber = ep.Number 780 // ci.Epoch = ep 781 // core.SaveChainInfo(cch.chainInfoDB, ci) 782 // log.Infof("Epoch saved from chain: %s, epoch: %v", chainId, ep) 783 // } 784 // } 785 // } 786 // 787 // // Write the TX3ProofData 788 // if len(proofData.TxIndexs) != 0 { 789 // 790 // log.Infof("SaveSideChainProofDataToMainChainV1 - Save Tx3, count is %v", len(proofData.TxIndexs)) 791 // tx3ProofData := &types.TX3ProofData{ 792 // Header: proofData.Header, 793 // TxIndexs: proofData.TxIndexs, 794 // TxProofs: proofData.TxProofs, 795 // } 796 // if err := cch.WriteTX3ProofData(tx3ProofData); err != nil { 797 // log.Error("TX3ProofDataMsg write error", "error", err) 798 // } 799 // } 800 // 801 // log.Info("SaveSideChainProofDataToMainChainV1 - end") 802 // return nil 803 //} 804 805 // TX3LocalCache start 806 func (cch *CrossChainHelper) GetTX3(chainId string, txHash common.Hash) *types.Transaction { 807 return rawdb.GetTX3(cch.localTX3CacheDB, chainId, txHash) 808 } 809 810 func (cch *CrossChainHelper) DeleteTX3(chainId string, txHash common.Hash) { 811 rawdb.DeleteTX3(cch.localTX3CacheDB, chainId, txHash) 812 } 813 814 func (cch *CrossChainHelper) WriteTX3ProofData(proofData *types.TX3ProofData) error { 815 return rawdb.WriteTX3ProofData(cch.localTX3CacheDB, proofData) 816 } 817 818 func (cch *CrossChainHelper) GetTX3ProofData(chainId string, txHash common.Hash) *types.TX3ProofData { 819 return rawdb.GetTX3ProofData(cch.localTX3CacheDB, chainId, txHash) 820 } 821 822 func (cch *CrossChainHelper) GetAllTX3ProofData() []*types.TX3ProofData { 823 return rawdb.GetAllTX3ProofData(cch.localTX3CacheDB) 824 } 825 826 // TX3LocalCache end 827 828 func MustGetNeatChainFromNode(node *node.Node) *neatptc.NeatChain { 829 neatChain, err := getNeatChainFromNode(node) 830 if err != nil { 831 panic("getNeatChainFromNode error: " + err.Error()) 832 } 833 return neatChain 834 } 835 836 func getNeatChainFromNode(node *node.Node) (*neatptc.NeatChain, error) { 837 var neatChain *neatptc.NeatChain 838 if err := node.Service(&neatChain); err != nil { 839 return nil, err 840 } 841 842 return neatChain, nil 843 }