diff --git a/common/config/config.go b/common/config/config.go index f8b8be9b2..bfa2c6632 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -272,7 +272,7 @@ func GetDefaultParams() *Configuration { HistoryStartHeight: uint32(0), NeedSave: true, }, - MemoryPoolTxMaximumStayHeight: 10, + MemoryPoolTxMaximumStayHeight: 10, // todo complete me } } diff --git a/core/transaction/dposv2claimrewardtransaction.go b/core/transaction/dposv2claimrewardtransaction.go index 0d952e282..9432baf20 100644 --- a/core/transaction/dposv2claimrewardtransaction.go +++ b/core/transaction/dposv2claimrewardtransaction.go @@ -74,7 +74,7 @@ func (t *DPoSV2ClaimRewardTransaction) SpecialContextCheck() (elaerr.ELAError, b return elaerr.Simple(elaerr.ErrTxPayload, errors.New("invalid payload version")), true } - addr, err := utils.GetAddressByCode(code) + addr, err := utils.GetStakeAddressByCode(code) if err != nil { return elaerr.Simple(elaerr.ErrTxPayload, errors.New("Programs code to address error")), true } diff --git a/core/transaction/dposv2claimrewardtransaction_test.go b/core/transaction/dposv2claimrewardtransaction_test.go index 7de8f5b82..ef0ee05f4 100644 --- a/core/transaction/dposv2claimrewardtransaction_test.go +++ b/core/transaction/dposv2claimrewardtransaction_test.go @@ -72,8 +72,12 @@ func (s *txValidatorTestSuite) TestCreateClaimDposV2Transaction() { err, _ = tx.SpecialContextCheck() s.EqualError(err.(errors.ELAError).InnerError(), "no reward to claim for such address") + addr, _ := common.Uint168FromAddress("ERyUmNH51roR9qfru37Kqkaok2NghR7L5U") + addr[0] = byte(contract.PrefixDPoSV2) + stakeAddr, _ := addr.ToAddress() + bc := s.Chain - bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 100 + bc.GetState().DPoSV2RewardInfo[stakeAddr] = 100 tx.DefaultChecker.SetParameters(&TransactionParameters{ BlockChain: bc, Config: param, @@ -84,7 +88,7 @@ func (s *txValidatorTestSuite) TestCreateClaimDposV2Transaction() { s.EqualError(err.(errors.ELAError).InnerError(), "claim reward exceeded , max claim reward 0.00000100") bc = s.Chain - bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 10000000000 + bc.GetState().DPoSV2RewardInfo[stakeAddr] = 10000000000 tx.DefaultChecker.SetParameters(&TransactionParameters{ BlockChain: bc, Config: param, diff --git a/core/transaction/inactivearbitratorstransaction.go b/core/transaction/inactivearbitratorstransaction.go index 65dc4a9f4..f3012945e 100644 --- a/core/transaction/inactivearbitratorstransaction.go +++ b/core/transaction/inactivearbitratorstransaction.go @@ -134,6 +134,7 @@ func checkCRCArbitratorsSignatures(program *program.Program) error { code := program.Code // Get N parameter + // todo check n := int(code[len(code)-2]) - crypto.PUSH1 + 1 // Get M parameter m := int(code[0]) - crypto.PUSH1 + 1 diff --git a/core/transaction/registercrtransaction.go b/core/transaction/registercrtransaction.go index e9e5a1dc3..4649c592b 100644 --- a/core/transaction/registercrtransaction.go +++ b/core/transaction/registercrtransaction.go @@ -112,6 +112,7 @@ func (t *RegisterCRTransaction) SpecialContextCheck() (elaerr.ELAError, bool) { var pk []byte if contract.IsSchnorr(code) { pk = code[2:] + // todo check } else if code[len(code)-1] == vm.CHECKSIG { pk = code[1 : len(code)-1] } else if code[len(code)-1] == vm.CHECKMULTISIG { diff --git a/core/transaction/registerproducertransaction.go b/core/transaction/registerproducertransaction.go index d333093de..6c7a157a1 100644 --- a/core/transaction/registerproducertransaction.go +++ b/core/transaction/registerproducertransaction.go @@ -164,17 +164,11 @@ func (t *RegisterProducerTransaction) SpecialContextCheck() (elaerr.ELAError, bo if err != nil { return elaerr.Simple(elaerr.ErrTxPayload, errors.New("invalid public key")), true } - addr, _ := hash.ToAddress() - log.Debugf("#### hash.ToAddress", addr) - if t.PayloadVersion() == payload.ProducerInfoVersion { // check deposit coin var depositCount int for _, output := range t.Outputs() { if contract.GetPrefixType(output.ProgramHash) == contract.PrefixDeposit { - addr, _ := output.ProgramHash.ToAddress() - - log.Debugf("#### register producer 1.0 ", addr) depositCount++ if !output.ProgramHash.IsEqual(*hash) { return elaerr.Simple(elaerr.ErrTxPayload, errors.New("deposit"+ @@ -199,9 +193,6 @@ func (t *RegisterProducerTransaction) SpecialContextCheck() (elaerr.ELAError, bo var depositCount int for _, output := range t.Outputs() { if contract.GetPrefixType(output.ProgramHash) == contract.PrefixDeposit { - addr, _ := output.ProgramHash.ToAddress() - - log.Debugf("#### register producer 2.o ", addr) depositCount++ if !output.ProgramHash.IsEqual(*hash) { return elaerr.Simple(elaerr.ErrTxPayload, errors.New("deposit address does not match the public key in payload")), true diff --git a/core/types/payload/nftdestroyfromsidechain.go b/core/types/payload/nftdestroyfromsidechain.go index 801b5c125..6448faa7e 100644 --- a/core/types/payload/nftdestroyfromsidechain.go +++ b/core/types/payload/nftdestroyfromsidechain.go @@ -16,8 +16,10 @@ import ( const NFTDestroyFromSideChainVersion byte = 0x00 type NFTDestroyFromSideChain struct { - IDs []common.Uint256 //detail votes info referkey - OwnerStakeAddresses []common.Uint168 //owner OwnerStakeAddresses + //detail votes info referkey + IDs []common.Uint256 + //owner OwnerStakeAddresses + OwnerStakeAddresses []common.Uint168 // genesis block hash of side chain. GenesisBlockHash common.Uint256 } diff --git a/core/types/payload/voting.go b/core/types/payload/voting.go index 519828c43..55241f782 100644 --- a/core/types/payload/voting.go +++ b/core/types/payload/voting.go @@ -297,7 +297,6 @@ type DetailedVoteInfo struct { PayloadVersion byte VoteType outputpayload.VoteType Info []VotesWithLockTime - PrefixType byte } func (v *DetailedVoteInfo) bytes() []byte { @@ -343,9 +342,6 @@ func (v *DetailedVoteInfo) Serialize(w io.Writer) error { return err } } - if err := common.WriteUint8(w, v.PrefixType); err != nil { - return err - } return nil } @@ -390,9 +386,5 @@ func (v *DetailedVoteInfo) Deserialize(r io.Reader) error { } v.Info[i] = info } - v.PrefixType, err = common.ReadUint8(r) - if err != nil { - return err - } return nil } diff --git a/dpos/state/arbitrators.go b/dpos/state/arbitrators.go index ff4789a4b..cae18b880 100644 --- a/dpos/state/arbitrators.go +++ b/dpos/state/arbitrators.go @@ -704,7 +704,9 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte, for _, cr := range a.CurrentCRCArbitersMap { if bytes.Equal(sponsor, cr.GetNodePublicKey()) { ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(cr.GetOwnerPublicKey()) - ownerAddr, _ := ownerProgramHash.ToAddress() + stakeProgramHash := common.Uint168FromCodeHash( + byte(contract.PrefixDPoSV2), ownerProgramHash.ToCodeHash()) + ownerAddr, _ := stakeProgramHash.ToAddress() rewards[ownerAddr] += dposReward isCR = true break @@ -721,37 +723,32 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte, return } ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(producer.OwnerPublicKey()) - ownerAddr, _ := ownerProgramHash.ToAddress() + stakeProgramHash := common.Uint168FromCodeHash( + byte(contract.PrefixDPoSV2), ownerProgramHash.ToCodeHash()) + ownerAddr, _ := stakeProgramHash.ToAddress() producersN := make(map[common.Uint168]float64) - stakeAddrPreTypeMgr := make(map[common.Uint168]byte) var totalNI float64 for sVoteAddr, sVoteDetail := range producer.detailedDPoSV2Votes { if len(sVoteDetail) == 0 { continue } - prefixType := byte(contract.PrefixStandard) var totalN float64 for _, votes := range sVoteDetail { weightF := math.Log10(float64(votes.Info[0].LockTime-votes.BlockHeight) / 7200 * 10) N := common.Fixed64(float64(votes.Info[0].Votes) * weightF) totalN += float64(N) - prefixType = votes.PrefixType } if totalN == 0 { continue } producersN[sVoteAddr] = totalN - stakeAddrPreTypeMgr[sVoteAddr] = prefixType totalNI += totalN } for sVoteAddr, N := range producersN { - b := sVoteAddr.Bytes() - b[0] = stakeAddrPreTypeMgr[sVoteAddr] - standardUint168, _ := common.Uint168FromBytes(b) - addr, _ := standardUint168.ToAddress() + addr, _ := sVoteAddr.ToAddress() p := N / totalNI * float64(votesReward) rewards[addr] += common.Fixed64(p) log.Debugf("getDPoSV2Rewards addr:%s, p:%s, reward:%s \n", addr, common.Fixed64(p), rewards[addr]) @@ -771,76 +768,6 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte, return rewards } -func (a *Arbiters) getDPoSV2RewardsV1(dposReward common.Fixed64, sponsor []byte) (rewards map[string]common.Fixed64) { - log.Debugf("accumulateReward dposReward %v", dposReward) - ownerPubKeyStr := a.getProducerKey(sponsor) - ownerPubKeyBytes, _ := hex.DecodeString(ownerPubKeyStr) - ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(ownerPubKeyBytes) - ownerAddr, _ := ownerProgramHash.ToAddress() - - rewards = make(map[string]common.Fixed64) - if _, ok := a.CurrentCRCArbitersMap[*ownerProgramHash]; ok { // crc - // all reward to DPoS node owner - rewards[ownerAddr] += dposReward - } else { - - // DPoS votes reward is: reward * 3 /4 - votesReward := dposReward * 3 / 4 - - producer := a.getProducer(sponsor) - if producer == nil { - log.Error("v1 accumulateReward Sponsor not exist ", hex.EncodeToString(sponsor)) - return - } - producersN := make(map[common.Uint168]float64) - stakeAddrPreTypeMgr := make(map[common.Uint168]byte) - - var totalNI float64 - for sVoteAddr, sVoteDetail := range producer.detailedDPoSV2Votes { - if len(sVoteDetail) == 0 { - continue - } - prefixType := byte(contract.PrefixStandard) - var totalN float64 - for _, votes := range sVoteDetail { - weightF := math.Log10(float64(votes.Info[0].LockTime-votes.BlockHeight) / 7200 * 10) - N := common.Fixed64(float64(votes.Info[0].Votes) * weightF) - totalN += float64(N) - prefixType = votes.PrefixType - } - if totalN == 0 { - continue - } - producersN[sVoteAddr] = totalN - stakeAddrPreTypeMgr[sVoteAddr] = prefixType - totalNI += totalN - } - - for sVoteAddr, N := range producersN { - b := sVoteAddr.Bytes() - b[0] = stakeAddrPreTypeMgr[sVoteAddr] - standardUint168, _ := common.Uint168FromBytes(b) - addr, _ := standardUint168.ToAddress() - p := N / totalNI * float64(votesReward) - rewards[addr] += common.Fixed64(p) - log.Debugf("getDPoSV2Rewards addr:%s, p:%s, reward:%s \n", addr, common.Fixed64(p), rewards[addr]) - } - - var totalUsedVotesReward common.Fixed64 - for _, v := range rewards { - totalUsedVotesReward += v - } - - // DPoS node reward is: reward - totalUsedVotesReward - dposNodeReward := dposReward - totalUsedVotesReward - rewards[ownerAddr] += dposNodeReward - log.Debugf("getDPoSV2Rewards totalUsedVotesReward %s dposNodeReward %s, \n", totalUsedVotesReward, dposNodeReward) - - } - - return rewards -} - func (a *Arbiters) accumulateReward(block *types.Block, confirm *payload.Confirm) { if block.Height < a.ChainParams.PublicDPOSHeight { oriDutyIndex := a.DutyIndex @@ -867,11 +794,7 @@ func (a *Arbiters) accumulateReward(block *types.Block, confirm *payload.Confirm var rewards map[string]common.Fixed64 if confirm != nil { - if block.Height > a.ChainParams.DPoSV2StartHeight { - rewards = a.getDPoSV2RewardsV2(dposReward, confirm.Proposal.Sponsor, block.Height) - } else { - rewards = a.getDPoSV2RewardsV1(dposReward, confirm.Proposal.Sponsor) - } + rewards = a.getDPoSV2RewardsV2(dposReward, confirm.Proposal.Sponsor, block.Height) } a.History.Append(block.Height, func() { diff --git a/dpos/state/keyframe.go b/dpos/state/keyframe.go index 03c25b0e7..f963964ab 100644 --- a/dpos/state/keyframe.go +++ b/dpos/state/keyframe.go @@ -1107,7 +1107,6 @@ func copyReferKeyInfoMap(src map[common.Uint256]payload.DetailedVoteInfo) (dst m PayloadVersion: a.PayloadVersion, VoteType: a.VoteType, Info: a.Info, - PrefixType: a.PrefixType, } } return diff --git a/dpos/state/state.go b/dpos/state/state.go index 4cd6fd1f5..028753ed5 100644 --- a/dpos/state/state.go +++ b/dpos/state/state.go @@ -24,14 +24,12 @@ import ( "github.com/elastos/Elastos.ELA/core/types/outputpayload" "github.com/elastos/Elastos.ELA/core/types/payload" "github.com/elastos/Elastos.ELA/cr/state" - "github.com/elastos/Elastos.ELA/crypto" msg2 "github.com/elastos/Elastos.ELA/dpos/p2p/msg" elaerr "github.com/elastos/Elastos.ELA/errors" "github.com/elastos/Elastos.ELA/events" "github.com/elastos/Elastos.ELA/p2p" "github.com/elastos/Elastos.ELA/p2p/msg" "github.com/elastos/Elastos.ELA/utils" - "github.com/elastos/Elastos.ELA/vm" ) // ProducerState represents the state of a producer. @@ -1996,14 +1994,6 @@ func (s *State) processVoting(tx interfaces.Transaction, height uint32) { func (s *State) processVotingContent(tx interfaces.Transaction, height uint32) { // get stake address(program hash) code := tx.Programs()[0].Code - signType, _ := crypto.GetScriptType(code) - var prefixType byte - if signType == vm.CHECKSIG { - prefixType = byte(contract.PrefixStandard) - } else if signType == vm.CHECKMULTISIG { - prefixType = byte(contract.PrefixMultiSig) - } - ct, _ := contract.CreateStakeContractByCode(code) stakeAddress := ct.ToProgramHash() pld := tx.Payload().(*payload.Voting) @@ -2075,7 +2065,6 @@ func (s *State) processVotingContent(tx interfaces.Transaction, height uint32) { PayloadVersion: tx.PayloadVersion(), VoteType: content.VoteType, Info: []payload.VotesWithLockTime{voteInfo}, - PrefixType: prefixType, } s.History.Append(height, func() { if producer.detailedDPoSV2Votes == nil { @@ -2110,14 +2099,6 @@ func (s *State) processRenewalVotingContent(tx interfaces.Transaction, height ui code := tx.Programs()[0].Code ct, _ := contract.CreateStakeContractByCode(code) stakeAddress := ct.ToProgramHash() - signType, _ := crypto.GetScriptType(code) - var prefixType byte - if signType == vm.CHECKSIG { - prefixType = byte(contract.PrefixStandard) - } else if signType == vm.CHECKMULTISIG { - prefixType = byte(contract.PrefixMultiSig) - } - pld := tx.Payload().(*payload.Voting) for _, cont := range pld.RenewalContents { content := cont @@ -2137,7 +2118,6 @@ func (s *State) processRenewalVotingContent(tx interfaces.Transaction, height ui PayloadVersion: voteInfo.PayloadVersion, VoteType: outputpayload.DposV2, Info: []payload.VotesWithLockTime{content.VotesInfo}, - PrefixType: prefixType, } s.LastRenewalDPoSV2Votes[content.ReferKey] = struct{}{} @@ -2555,7 +2535,8 @@ func (s *State) processDposV2ClaimReward(tx interfaces.Transaction, height uint3 } programHash, _ := utils.GetProgramHashByCode(code) - addr, _ := programHash.ToAddress() + stakeProgramHash := common.Uint168FromCodeHash(byte(contract.PrefixDPoSV2), programHash.ToCodeHash()) + addr, _ := stakeProgramHash.ToAddress() s.History.Append(height, func() { s.DPoSV2RewardInfo[addr] -= pld.Value s.DposV2RewardClaimingInfo[addr] += pld.Value diff --git a/elanet/netsync/manager.go b/elanet/netsync/manager.go index a26608c0b..bae07a6b1 100644 --- a/elanet/netsync/manager.go +++ b/elanet/netsync/manager.go @@ -900,10 +900,10 @@ func (sm *SyncManager) handleBlockchainEvents(event *events.Event) { iv := msg.NewInvVect(msg.InvTypeTx, &txHash) sm.peerNotifier.RelayInventory(iv, tx) } - case events.ETResendOutdatedTxToTxPool: + case events.ETOutdatedTxRelay: txs, ok := event.Data.([]interfaces.Transaction) if !ok { - log.Error("ETResendOutdatedTxToTxPool event is not a tx list") + log.Error("ETOutdatedTxRelay event is not a tx list") } for _, tx := range txs { txHash := tx.Hash() diff --git a/events/events.go b/events/events.go index 61d37b15b..d68aea450 100644 --- a/events/events.go +++ b/events/events.go @@ -71,8 +71,8 @@ const ( //chain transaction ETSmallCrossChainNeedRelay - //ETResendOutdatedTxToTxPool indicates that need to resend outdate tx to tx pool - ETResendOutdatedTxToTxPool + //ETOutdatedTxRelay indicates that need to resend outdate tx to tx pool + ETOutdatedTxRelay ) // notificationTypeStrings is a map of notification types back to their constant @@ -92,7 +92,7 @@ var notificationTypeStrings = map[EventType]string{ ETAppendTxToTxPoolWithoutRelay: "ETAppendTxToTxPoolWithoutRelay", ETCRCChangeCommittee: "ETCRCChangeCommittee", ETSmallCrossChainNeedRelay: "ETSmallCrossChainNeedRelay", - ETResendOutdatedTxToTxPool: "ETResendOutdatedTxToTxPool", + ETOutdatedTxRelay: "ETOutdatedTxRelay", } // String returns the EventType in human-readable form. diff --git a/mempool/txpool.go b/mempool/txpool.go index 13b328f3b..619dd001e 100644 --- a/mempool/txpool.go +++ b/mempool/txpool.go @@ -217,7 +217,7 @@ func (mp *TxPool) ResendOutdatedTransactions(block *Block) { } if len(txs) != 0 { - go events.Notify(events.ETResendOutdatedTxToTxPool, txs) + go events.Notify(events.ETOutdatedTxRelay, txs) } mp.Unlock() } diff --git a/servers/interfaces.go b/servers/interfaces.go index e7c97c5b4..dca0afd31 100644 --- a/servers/interfaces.go +++ b/servers/interfaces.go @@ -2303,9 +2303,27 @@ type RPCDPosV2Info struct { func DposV2RewardInfo(param Params) map[string]interface{} { addr, ok := param.String("address") if ok { - claimable := Chain.GetState().DPoSV2RewardInfo[addr] - claiming := Chain.GetState().DposV2RewardClaimingInfo[addr] - claimed := Chain.GetState().DposV2RewardClaimedInfo[addr] + // need to get claimable reward from Standard or Multi-sign address, + // also need to get claimable reward from Stake address. + address, err := common.Uint168FromAddress(addr) + if err != nil { + return ResponsePack(InternalError, "invalid address") + } + // check prefix, if the prefix is not PrefixDPoSV2, we need to change it + // to PrefixDPoSV2. + stakeAddress := addr + if address[0] != byte(contract.PrefixDPoSV2) { + address[0] = byte(contract.PrefixDPoSV2) + // create stake address from Standard or Multi-sign address. + stakeAddress, err = address.ToAddress() + if err != nil { + return ResponsePack(InternalError, "invalid stake address") + } + } + + claimable := Chain.GetState().DPoSV2RewardInfo[stakeAddress] + claiming := Chain.GetState().DposV2RewardClaimingInfo[stakeAddress] + claimed := Chain.GetState().DposV2RewardClaimedInfo[stakeAddress] result := RPCDposV2RewardInfo{ Address: addr, Claimable: claimable.String(), diff --git a/test/unit/txvalidator_test.go b/test/unit/txvalidator_test.go index 010d5dc91..f91f6cfa1 100644 --- a/test/unit/txvalidator_test.go +++ b/test/unit/txvalidator_test.go @@ -7487,8 +7487,12 @@ func (s *txValidatorTestSuite) TestCreateCRClaimDposV2Transaction() { err, _ = tx.SpecialContextCheck() s.EqualError(err.(errors.ELAError).InnerError(), "no reward to claim for such address") + addr, _ := common.Uint168FromAddress("ERyUmNH51roR9qfru37Kqkaok2NghR7L5U") + addr[0] = byte(contract.PrefixDPoSV2) + stakeAddr, _ := addr.ToAddress() + bc := s.Chain - bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 100 + bc.GetState().DPoSV2RewardInfo[stakeAddr] = 100 tx.DefaultChecker.SetParameters(&transaction.TransactionParameters{ BlockChain: bc, Config: param, @@ -7499,7 +7503,7 @@ func (s *txValidatorTestSuite) TestCreateCRClaimDposV2Transaction() { s.EqualError(err.(errors.ELAError).InnerError(), "claim reward exceeded , max claim reward 0.00000100") bc = s.Chain - bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 10000000000 + bc.GetState().DPoSV2RewardInfo[stakeAddr] = 10000000000 tx.DefaultChecker.SetParameters(&transaction.TransactionParameters{ BlockChain: bc, Config: param, @@ -7724,7 +7728,10 @@ func (s *txValidatorTestSuite) TestArbitersAccumulateReward() { //CurrentCRCArbitersMap a.AccumulateReward(tt.args.block, tt.args.confirm) a.History.Commit(tt.args.block.Height) - if a.State.DPoSV2RewardInfo["ET54cpnGG4JHeRatvPij6hGV6zN18eVSSj"] != 102 { + addr, _ := common.Uint168FromAddress("ET54cpnGG4JHeRatvPij6hGV6zN18eVSSj") + addr[0] = byte(contract.PrefixDPoSV2) + stakeAddr, _ := addr.ToAddress() + if a.State.DPoSV2RewardInfo[stakeAddr] != 102 { t.Errorf("DPoSV2RewardInfo() addr %v, want %v", "ET54cpnGG4JHeRatvPij6hGV6zN18eVSSj", 102) } }) diff --git a/utils/common.go b/utils/common.go index d8661119a..38b466e5f 100644 --- a/utils/common.go +++ b/utils/common.go @@ -162,6 +162,20 @@ func DeserializeStringSet(r io.Reader) (vmap map[string]struct{}, err error) { return } +func GetStakeAddressByCode(code []byte) (string, error) { + programHash, err := GetProgramHashByCode(code) + if err != nil { + return "", err + } + stakeProgramHash := common.Uint168FromCodeHash( + byte(contract.PrefixDPoSV2), programHash.ToCodeHash()) + address, err := stakeProgramHash.ToAddress() + if err != nil { + return "", err + } + return address, nil +} + func GetAddressByCode(code []byte) (string, error) { programHash, err := GetProgramHashByCode(code) if err != nil { @@ -195,6 +209,7 @@ func GetProgramHashByCode(code []byte) (*common.Uint168, error) { } else { return nil, errors.New("invalid code type") } + // todo support schnorr } // checkHost check the host or IP address is valid and available.