diff --git a/Makefile b/Makefile index 440004d985..f66ba6917b 100644 --- a/Makefile +++ b/Makefile @@ -63,32 +63,13 @@ all-cross: ontology-cross tools-cross abi format: $(GOFMT) -w main.go -docker/payload: docker/build/bin/ontology docker/Dockerfile - @echo "Building ontology payload" - @mkdir -p $@ - @cp docker/Dockerfile $@ - @cp docker/build/bin/ontology $@ - @touch $@ - -docker/build/bin/%: Makefile - @echo "Building ontology in docker" - @mkdir -p docker/build/bin docker/build/pkg - @$(DRUN) --rm \ - -v $(abspath docker/build/bin):/go/bin \ - -v $(abspath docker/build/pkg):/go/pkg \ - -v $(GOPATH)/src:/go/src \ - -w /go/src/github.com/ontio/ontology \ - golang:1.9.5-stretch \ - $(GC) $(BUILD_NODE_PAR) -o docker/build/bin/ontology main.go - @touch $@ -docker: Makefile docker/payload docker/Dockerfile +docker: Makefile @echo "Building ontology docker" - @$(DBUILD) -t $(DOCKER_NS)/ontology docker/payload - @docker tag $(DOCKER_NS)/ontology $(DOCKER_NS)/ontology:$(DOCKER_TAG) + @$(DBUILD) --no-cache -t $(DOCKER_NS)/ontology:$(DOCKER_TAG) - < docker/Dockerfile @touch $@ clean: rm -rf *.8 *.o *.out *.6 *exe coverage - rm -rf ontology ontology-* tools docker/payload docker/build + rm -rf ontology ontology-* tools diff --git a/cmd/abi/native_abi_script/governance.json b/cmd/abi/native_abi_script/governance.json index e3b8725af9..ea5c04dd01 100644 --- a/cmd/abi/native_abi_script/governance.json +++ b/cmd/abi/native_abi_script/governance.json @@ -443,6 +443,29 @@ ], "returnType":"Bool" }, + { + "name":"setFeePercentage", + "parameters": + [ + { + "name":"PeerPubkey", + "type":"String" + }, + { + "name":"Address", + "type":"Address" + }, + { + "name":"PeerCost", + "type":"Int" + }, + { + "name":"StakeCost", + "type":"Int" + } + ], + "returnType":"Bool" + }, { "name":"withdrawFee", "parameters": @@ -556,38 +579,9 @@ } ], "returnType":"Bool" - }, - { - "name":"getPeerPool", - "parameters": - [ - ], - "returnType":"ByteArray" - }, - { - "name":"getPeerInfo", - "parameters": - [ - { - "name":"PeerPublicKey", - "type":"String" - } - ], - "returnType":"ByteArray" - }, - { - "name":"getPeerPoolByAddress", - "parameters": - [ - { - "name":"Address", - "type":"Address" - } - ], - "returnType":"ByteArray" } ], "events": [ ] -} +} \ No newline at end of file diff --git a/cmd/account.go b/cmd/account.go index fac1818216..d9aa660574 100644 --- a/cmd/account.go +++ b/cmd/account.go @@ -108,7 +108,7 @@ var schemeMap = map[string]schemeInfo{ // wait for user to choose options func chooseKeyType(reader *bufio.Reader) string { common.PrintNotice("key type") - for true { + for { tmp, _ := reader.ReadString('\n') tmp = strings.TrimSpace(tmp) _, ok := keyTypeMap[tmp] @@ -123,7 +123,7 @@ func chooseKeyType(reader *bufio.Reader) string { } func chooseScheme(reader *bufio.Reader) string { common.PrintNotice("signature-scheme") - for true { + for { tmp, _ := reader.ReadString('\n') tmp = strings.TrimSpace(tmp) @@ -139,7 +139,7 @@ func chooseScheme(reader *bufio.Reader) string { } func chooseCurve(reader *bufio.Reader) string { common.PrintNotice("curve") - for true { + for { tmp, _ := reader.ReadString('\n') tmp = strings.TrimSpace(tmp) _, ok := curveMap[tmp] @@ -217,15 +217,12 @@ func checkCurve(ctx *cli.Context, reader *bufio.Reader, t *string) string { } else { c = chooseCurve(reader) } - break case "sm2": fmt.Println("Use curve sm2p256v1 with key length of 256 bits.") c = "SM2P256V1" - break case "ed25519": fmt.Println("Use curve 25519 with key length of 256 bits.") c = "ED25519" - break default: return "" } @@ -247,15 +244,12 @@ func checkScheme(ctx *cli.Context, reader *bufio.Reader, t *string) string { } else { sch = chooseScheme(reader) } - break case "sm2": fmt.Println("Use SM3withSM2 as the signature scheme.") sch = "SM3withSM2" - break case "ed25519": fmt.Println("Use SHA512withEdDSA as the signature scheme.") sch = "SHA512withEdDSA" - break default: return "" } diff --git a/cmd/common/notice.go b/cmd/common/notice.go index f50f731fb9..1f5ac08ad0 100644 --- a/cmd/common/notice.go +++ b/cmd/common/notice.go @@ -32,7 +32,6 @@ Select a signature algorithm from the following: 3 Ed25519 [default is 1]: `) - break case "curve": fmt.Printf(` @@ -46,7 +45,6 @@ Select a curve from the following: 4 | P-521 | 521 This determines the length of the private key [default is 2]: `) - break case "signature-scheme": fmt.Printf(` @@ -63,7 +61,6 @@ Select a signature scheme from the following: 9 RIPEMD160withECDSA This can be changed later [default is 2]: `) - break default: } diff --git a/cmd/contract_cmd.go b/cmd/contract_cmd.go index 03a8d483ea..1fd76127d2 100644 --- a/cmd/contract_cmd.go +++ b/cmd/contract_cmd.go @@ -156,7 +156,7 @@ func deployContract(ctx *cli.Context) error { gasPrice = 0 } - cversion := fmt.Sprintf("%s", version) + cversion := version if ctx.IsSet(utils.GetFlagName(utils.ContractPrepareDeployFlag)) { preResult, err := utils.PrepareDeployContract(vmtype, code, name, cversion, author, email, desc) diff --git a/cmd/sig_tx_cmd.go b/cmd/sig_tx_cmd.go index b8ea22eb8c..14c6718308 100644 --- a/cmd/sig_tx_cmd.go +++ b/cmd/sig_tx_cmd.go @@ -93,6 +93,9 @@ func genMultiSigAddress(ctx *cli.Context) error { continue } data, err := hex.DecodeString(pk) + if err != nil { + return err + } pubKey, err := keypair.DeserializePublicKey(data) if err != nil { return fmt.Errorf("invalid pub key:%s", pk) @@ -141,6 +144,9 @@ func multiSigToTx(ctx *cli.Context) error { continue } data, err := hex.DecodeString(pk) + if err != nil { + return err + } pubKey, err := keypair.DeserializePublicKey(data) if err != nil { return fmt.Errorf("invalid pub key:%s", pk) diff --git a/cmd/tx_cmd.go b/cmd/tx_cmd.go index df2bb7356b..60163a6b8f 100644 --- a/cmd/tx_cmd.go +++ b/cmd/tx_cmd.go @@ -205,10 +205,10 @@ func transferTx(ctx *cli.Context) error { switch strings.ToLower(asset) { case "ont": amount = utils.ParseOnt(amountStr) - amountStr = utils.FormatOnt(amount) + // amountStr = utils.FormatOnt(amount) case "ong": amount = utils.ParseOng(amountStr) - amountStr = utils.FormatOng(amount) + // amountStr = utils.FormatOng(amount) default: return fmt.Errorf("unsupport asset:%s", asset) } @@ -277,10 +277,10 @@ func approveTx(ctx *cli.Context) error { switch strings.ToLower(asset) { case "ont": amount = utils.ParseOnt(amountStr) - amountStr = utils.FormatOnt(amount) + // amountStr = utils.FormatOnt(amount) case "ong": amount = utils.ParseOng(amountStr) - amountStr = utils.FormatOng(amount) + // amountStr = utils.FormatOng(amount) default: return fmt.Errorf("unsupport asset:%s", asset) } @@ -363,10 +363,9 @@ func transferFromTx(ctx *cli.Context) error { switch strings.ToLower(asset) { case "ont": amount = utils.ParseOnt(amountStr) - amountStr = utils.FormatOnt(amount) case "ong": amount = utils.ParseOng(amountStr) - amountStr = utils.FormatOng(amount) + // amountStr = utils.FormatOng(amount) default: return fmt.Errorf("unsupport asset:%s", asset) } @@ -425,13 +424,13 @@ func withdrawONGTx(ctx *cli.Context) error { if amount <= 0 { return fmt.Errorf("haven't unbound ong") } - amountStr = utils.FormatOng(amount) + // amountStr = utils.FormatOng(amount) } else { amount = utils.ParseOng(amountStr) if amount <= 0 { return fmt.Errorf("haven't unbound ong") } - amountStr = utils.FormatOng(amount) + // amountStr = utils.FormatOng(amount) } var payer common.Address diff --git a/cmd/utils/ont.go b/cmd/utils/ont.go index 2aba7b5b67..cda40a90cf 100644 --- a/cmd/utils/ont.go +++ b/cmd/utils/ont.go @@ -41,7 +41,6 @@ import ( "github.com/ontio/ontology/core/types" cutils "github.com/ontio/ontology/core/utils" httpcom "github.com/ontio/ontology/http/base/common" - rpccommon "github.com/ontio/ontology/http/base/common" "github.com/ontio/ontology/smartcontract/service/native/ont" "github.com/ontio/ontology/smartcontract/service/native/utils" ) @@ -454,12 +453,12 @@ func SendRawTransactionData(txData string) (string, error) { return hexHash, nil } -func PrepareSendRawTransaction(txData string) (*rpccommon.PreExecuteResult, error) { +func PrepareSendRawTransaction(txData string) (*httpcom.PreExecuteResult, error) { data, ontErr := sendRpcRequest("sendrawtransaction", []interface{}{txData, 1}) if ontErr != nil { return nil, ontErr.Error } - preResult := &rpccommon.PreExecuteResult{} + preResult := &httpcom.PreExecuteResult{} err := json.Unmarshal(data, &preResult) if err != nil { return nil, fmt.Errorf("json.Unmarshal PreExecResult:%s error:%s", data, err) @@ -468,7 +467,7 @@ func PrepareSendRawTransaction(txData string) (*rpccommon.PreExecuteResult, erro } //GetSmartContractEvent return smart contract event execute by invoke transaction by hex string code -func GetSmartContractEvent(txHash string) (*rpccommon.ExecuteNotify, error) { +func GetSmartContractEvent(txHash string) (*httpcom.ExecuteNotify, error) { data, ontErr := sendRpcRequest("getsmartcodeevent", []interface{}{txHash}) if ontErr != nil { switch ontErr.ErrorCode { @@ -477,7 +476,7 @@ func GetSmartContractEvent(txHash string) (*rpccommon.ExecuteNotify, error) { } return nil, ontErr.Error } - notifies := &rpccommon.ExecuteNotify{} + notifies := &httpcom.ExecuteNotify{} err := json.Unmarshal(data, ¬ifies) if err != nil { return nil, fmt.Errorf("json.Unmarshal SmartContactEvent:%s error:%s", data, err) @@ -714,7 +713,7 @@ func InvokeSmartContract(signer *account.Account, tx *types.MutableTransaction) func PrepareInvokeNeoVMContract( contractAddress common.Address, params []interface{}, -) (*rpccommon.PreExecuteResult, error) { +) (*httpcom.PreExecuteResult, error) { mutable, err := httpcom.NewNeovmInvokeTransaction(0, 0, contractAddress, params) if err != nil { return nil, err @@ -729,7 +728,7 @@ func PrepareInvokeNeoVMContract( return PrepareSendRawTransaction(txData) } -func PrepareInvokeCodeNeoVMContract(code []byte) (*rpccommon.PreExecuteResult, error) { +func PrepareInvokeCodeNeoVMContract(code []byte) (*httpcom.PreExecuteResult, error) { mutable, err := httpcom.NewSmartContractTransaction(0, 0, code) if err != nil { return nil, err @@ -743,7 +742,7 @@ func PrepareInvokeCodeNeoVMContract(code []byte) (*rpccommon.PreExecuteResult, e } //prepare invoke wasm -func PrepareInvokeWasmVMContract(contractAddress common.Address, params []interface{}) (*rpccommon.PreExecuteResult, error) { +func PrepareInvokeWasmVMContract(contractAddress common.Address, params []interface{}) (*httpcom.PreExecuteResult, error) { mutable, err := cutils.NewWasmVMInvokeTransaction(0, 0, contractAddress, params) if err != nil { return nil, err diff --git a/common/config/config.go b/common/config/config.go index 4af797fe44..9809a1d441 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -731,6 +731,9 @@ func (this *OntologyConfig) GetBookkeepers() ([]keypair.PublicKey, error) { pubKeys := make([]keypair.PublicKey, 0, len(bookKeepers)) for _, key := range bookKeepers { pubKey, err := hex.DecodeString(key) + if err != nil { + return nil, err + } k, err := keypair.DeserializePublicKey(pubKey) if err != nil { return nil, fmt.Errorf("Incorrectly book keepers key:%s", key) diff --git a/common/constants/constants.go b/common/constants/constants.go index 87356efbb7..18ece8c507 100644 --- a/common/constants/constants.go +++ b/common/constants/constants.go @@ -94,4 +94,4 @@ const BLOCKHEIGHT_CC_POLARIS = 13130000 //new node cost height const BLOCKHEIGHT_NEW_PEER_COST_MAINNET = 9400000 -const BLOCKHEIGHT_NEW_PEER_COST_POLARIS = 13360000 +const BLOCKHEIGHT_NEW_PEER_COST_POLARIS = 13400000 diff --git a/consensus/dbft/block_signatures.go b/consensus/dbft/block_signatures.go index 96cff06b96..21ba4001b8 100644 --- a/consensus/dbft/block_signatures.go +++ b/consensus/dbft/block_signatures.go @@ -62,6 +62,10 @@ func (self *BlockSignatures) Deserialization(source *common.ZeroCopySource) erro sig := SignaturesData{} sig.Signature, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } diff --git a/consensus/dbft/consensus_message.go b/consensus/dbft/consensus_message.go index 1833512dac..363d0e6bfc 100644 --- a/consensus/dbft/consensus_message.go +++ b/consensus/dbft/consensus_message.go @@ -98,6 +98,10 @@ func (cd *ConsensusMessageData) Deserialization(source *common.ZeroCopySource) e var eof bool var temp byte temp, eof = source.NextByte() + if eof { + return io.ErrUnexpectedEOF + } + cd.Type = ConsensusMessageType(temp) cd.ViewNumber, eof = source.NextByte() if eof { diff --git a/consensus/dbft/dbft_service.go b/consensus/dbft/dbft_service.go index 4acdd5cb02..42a0dea775 100644 --- a/consensus/dbft/dbft_service.go +++ b/consensus/dbft/dbft_service.go @@ -96,7 +96,7 @@ func NewDbftService(bkAccount *account.Account, txpool *actor.PID, p2p p2p.P2P) } func (this *DbftService) Receive(context actor.Context) { - if _, ok := context.Message().(*actorTypes.StartConsensus); this.started == false && ok == false { + if _, ok := context.Message().(*actorTypes.StartConsensus); !this.started && !ok { return } @@ -359,22 +359,18 @@ func (ds *DbftService) NewConsensusPayload(payload *p2pmsg.ConsensusPayload) { if cv, ok := message.(*ChangeView); ok { ds.ChangeViewReceived(payload, cv) } - break case PrepareRequestMsg: if pr, ok := message.(*PrepareRequest); ok { ds.PrepareRequestReceived(payload, pr) } - break case PrepareResponseMsg: if pres, ok := message.(*PrepareResponse); ok { ds.PrepareResponseReceived(payload, pres) } - break case BlockSignaturesMsg: if blockSigs, ok := message.(*BlockSignatures); ok { ds.BlockSignaturesReceived(payload, blockSigs) } - break default: log.Warn("unknown consensus message type") } diff --git a/consensus/dbft/prepare_request.go b/consensus/dbft/prepare_request.go index 28caed11f3..ec45b40ca2 100644 --- a/consensus/dbft/prepare_request.go +++ b/consensus/dbft/prepare_request.go @@ -62,9 +62,16 @@ func (pr *PrepareRequest) Deserialization(source *common.ZeroCopySource) error { } pr.Nonce = nonce pr.NextBookkeeper, eof = source.NextAddress() + if eof { + return io.ErrUnexpectedEOF + } var length uint64 length, _, irregular, eof = source.NextVarUint() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } diff --git a/consensus/vbft/block_pool.go b/consensus/vbft/block_pool.go index 1a990928b1..6a8651d295 100644 --- a/consensus/vbft/block_pool.go +++ b/consensus/vbft/block_pool.go @@ -111,9 +111,9 @@ func (pool *BlockPool) clean() { func (pool *BlockPool) getCandidateInfoLocked(blkNum uint32) *CandidateInfo { // NOTE: call this function only when pool.lock locked - if candidate, present := pool.candidateBlocks[blkNum]; !present { + if _, present := pool.candidateBlocks[blkNum]; !present { // new candiateInfo for blockNum - candidate = &CandidateInfo{ + candidate := &CandidateInfo{ Proposals: make([]*blockProposalMsg, 0), CommitMsgs: make([]*blockCommitMsg, 0), EndorseSigs: make(map[uint32][]*CandidateEndorseSigInfo), @@ -137,7 +137,7 @@ func (pool *BlockPool) newBlockProposal(msg *blockProposalMsg) error { // check dup-proposal from same proposer for _, p := range candidate.Proposals { if p.Block.getProposer() == msg.Block.getProposer() { - if bytes.Compare(p.BlockProposerSig, msg.BlockProposerSig) == 0 { + if bytes.Equal(p.BlockProposerSig, msg.BlockProposerSig) { return nil } return errDupProposal @@ -287,7 +287,6 @@ func (pool *BlockPool) addBlockEndorsementLocked(blkNum uint32, endorser uint32, } else { candidate.EndorseSigs[endorser] = []*CandidateEndorseSigInfo{eSig} } - return } // diff --git a/consensus/vbft/chain_store.go b/consensus/vbft/chain_store.go index 59fcd65d1f..c9c3a44db6 100644 --- a/consensus/vbft/chain_store.go +++ b/consensus/vbft/chain_store.go @@ -176,14 +176,12 @@ func (self *ChainStore) submitBlock(blkNum uint32) error { if blkNum == 0 { return nil } - if submitBlk, present := self.pendingBlocks[blkNum]; submitBlk != nil && submitBlk.hasSubmitted == false && present { + if submitBlk, present := self.pendingBlocks[blkNum]; submitBlk != nil && !submitBlk.hasSubmitted && present { err := self.db.SubmitBlock(submitBlk.block.Block, submitBlk.block.CrossChainMsg, *submitBlk.execResult) if err != nil { return fmt.Errorf("ledger add submitBlk (%d, %d, %d) failed: %s", blkNum, self.GetChainedBlockNum(), self.db.GetCurrentBlockHeight(), err) } - if _, present := self.pendingBlocks[blkNum-1]; present { - delete(self.pendingBlocks, blkNum-1) - } + delete(self.pendingBlocks, blkNum-1) submitBlk.hasSubmitted = true } return nil diff --git a/consensus/vbft/node_sync.go b/consensus/vbft/node_sync.go index ec9b7de690..fc739bad5e 100644 --- a/consensus/vbft/node_sync.go +++ b/consensus/vbft/node_sync.go @@ -153,9 +153,9 @@ func (self *Syncer) run() { // report err p.msgC <- nil } - } else { - // report error - } + } // else { + // // report error + // } case blkMsgFromPeer := <-self.blockFromPeerC: blkNum := blkMsgFromPeer.block.getBlockNum() @@ -312,12 +312,7 @@ func (self *Syncer) onNewBlockSyncReq(req *BlockSyncReq) { self.nextReqBlkNum = req.startBlockNum } self.targetBlkNum = req.targetBlockNum - peers := req.targetPeers - if len(peers) == 0 { - for p := range self.peers { - peers = append(peers, p) - } - } + // } for _, peerIdx := range req.targetPeers { if p, present := self.peers[peerIdx]; !present || !p.active { @@ -434,7 +429,7 @@ func (self *PeerSyncer) requestBlock(blkNum uint32) (*Block, error) { case BlockFetchRespMessage: pMsg, ok := msg.(*BlockFetchRespMsg) if !ok { - // log error + return nil, fmt.Errorf("expect request type: BlockFetchMessage") } return pMsg.BlockData, nil } @@ -465,7 +460,7 @@ func (self *PeerSyncer) requestBlockInfo(startBlkNum uint32) ([]*BlockInfo_, err case BlockInfoFetchRespMessage: pMsg, ok := msg.(*BlockInfoFetchRespMsg) if !ok { - // log error + return nil, fmt.Errorf("expect request type: BlockInfoFetchRespMessage") } return pMsg.Blocks, nil } diff --git a/consensus/vbft/node_utils.go b/consensus/vbft/node_utils.go index cc48064210..7988c3d597 100644 --- a/consensus/vbft/node_utils.go +++ b/consensus/vbft/node_utils.go @@ -149,19 +149,9 @@ func (self *Server) isEndorser(blockNum uint32, peerIdx uint32) bool { self.metaLock.RLock() defer self.metaLock.RUnlock() - // the first 2C+1 active endorsers - var activeN uint32 - { - for _, id := range self.currentParticipantConfig.Endorsers { - if id == peerIdx { - return true - } - if self.isPeerActive(id, blockNum) { - activeN++ - if activeN > self.config.C*2 { - break - } - } + for _, id := range self.currentParticipantConfig.Endorsers { + if id == peerIdx { + return true } } @@ -172,19 +162,9 @@ func (self *Server) isCommitter(blockNum uint32, peerIdx uint32) bool { self.metaLock.RLock() defer self.metaLock.RUnlock() - // the first 2C+1 active committers - var activeN uint32 - { - for _, id := range self.currentParticipantConfig.Committers { - if id == peerIdx { - return true - } - if self.isPeerActive(id, blockNum) { - activeN++ - if activeN > self.config.C*2 { - break - } - } + for _, id := range self.currentParticipantConfig.Committers { + if id == peerIdx { + return true } } diff --git a/consensus/vbft/service.go b/consensus/vbft/service.go index 089de9d072..628f5c7118 100644 --- a/consensus/vbft/service.go +++ b/consensus/vbft/service.go @@ -485,8 +485,8 @@ func (self *Server) initialize() error { go self.msgSendLoop() go self.timerLoop() go self.actionLoop() + self.quitWg.Add(1) go func() { - self.quitWg.Add(1) defer self.quitWg.Done() for { @@ -1226,9 +1226,9 @@ func (self *Server) processMsgEvent() error { if msgBlkNum == self.GetCurrentBlockNo() { // add proposal to block-pool if err := self.blockPool.newBlockProposal(pMsg); err != nil { - if err == errDupProposal { - // TODO: faulty proposer detected - } + // if err == errDupProposal { + // // TODO: faulty proposer detected + // } log.Errorf("failed to add block proposal (%d): %s", msgBlkNum, err) return nil } @@ -1263,13 +1263,13 @@ func (self *Server) processMsgEvent() error { } // makeProposalTimeout handles non-leader proposals } - } else { - // process new proposal when - // 1. we have endorsed for current BlockNum - // 2. proposal is from next potential-leader + } // else { + // // process new proposal when + // // 1. we have endorsed for current BlockNum + // // 2. proposal is from next potential-leader - // TODO - } + // // TODO + // } case BlockEndorseMessage: pMsg := msg.(*blockEndorseMsg) @@ -1314,12 +1314,12 @@ func (self *Server) processMsgEvent() error { return nil } } - } else { - // wait until endorse timeout - } - } else { - // makeEndorsementTimeout handles non-endorser endorsements - } + } // else { + // // wait until endorse timeout + // } + } // else { + // // makeEndorsementTimeout handles non-endorser endorsements + // } if self.blockPool.endorseFailed(msgBlkNum, self.GetChainConfig().C) { // endorse failed, start empty endorsing self.timer.C <- &TimerEvent{ @@ -1327,11 +1327,11 @@ func (self *Server) processMsgEvent() error { blockNum: msgBlkNum, } } - } else { - // process new endorsement when - // 1. we have committed for current BlockNum - // 2. endorsed proposal is from next potential-leader - } + } // else { + // // process new endorsement when + // // 1. we have committed for current BlockNum + // // 2. endorsed proposal is from next potential-leader + // } case BlockCommitMessage: pMsg := msg.(*blockCommitMsg) @@ -1376,15 +1376,15 @@ func (self *Server) processMsgEvent() error { if err := self.makeSealed(proposal, forEmpty); err != nil { log.Errorf("failed to seal block %d, err: %s", msgBlkNum, err) } - } else { - // wait commit timeout, nothing to do - } + } // else { + // // wait commit timeout, nothing to do + // } - } else { - // nothing to do besides adding to msg pool + } // else { + // // nothing to do besides adding to msg pool - // FIXME: add msg from msg-pool to block-pool when starting new block-round - } + // // FIXME: add msg from msg-pool to block-pool when starting new block-round + // } } case <-self.quitC: @@ -2212,8 +2212,7 @@ func (self *Server) makeProposal(blkNum uint32, forEmpty bool) error { userTxs := make([]*types.Transaction, 0) //check need upate chainconfig - cfg := &vconfig.ChainConfig{} - cfg = nil + var cfg *vconfig.ChainConfig if self.checkNeedUpdateChainConfig(blkNum) || self.checkUpdateChainConfig(blkNum) { chainconfig, err := getChainConfig(self.blockPool.getExecWriteSet(blkNum-1), blkNum) if err != nil { diff --git a/consensus/vbft/utils.go b/consensus/vbft/utils.go index 1d819889f5..bbcdc0ad37 100644 --- a/consensus/vbft/utils.go +++ b/consensus/vbft/utils.go @@ -146,7 +146,7 @@ func GetVbftConfigInfo(memdb *overlaydb.MemDB) (*config.VBFTConfig, error) { } } - chainconfig := new(config.VBFTConfig) + var chainconfig *config.VBFTConfig if preCfg.SetView == goveranceview.View { chainconfig = &config.VBFTConfig{ N: uint32(preCfg.Configuration.N), diff --git a/core/payload/deploy_code.go b/core/payload/deploy_code.go index baaa6fe68c..40212ec243 100644 --- a/core/payload/deploy_code.go +++ b/core/payload/deploy_code.go @@ -140,27 +140,51 @@ func (dc *DeployCode) Serialization(sink *common.ZeroCopySink) { func (dc *DeployCode) Deserialization(source *common.ZeroCopySource) error { var eof, irregular bool dc.code, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } dc.vmFlags, eof = source.NextByte() + if eof { + return io.ErrUnexpectedEOF + } + dc.Name, _, irregular, eof = source.NextString() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } dc.Version, _, irregular, eof = source.NextString() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } dc.Author, _, irregular, eof = source.NextString() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } dc.Email, _, irregular, eof = source.NextString() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } diff --git a/core/program/program.go b/core/program/program.go index 5c148e904b..8b8a2815d6 100644 --- a/core/program/program.go +++ b/core/program/program.go @@ -356,7 +356,7 @@ func GetParamInfo(program []byte) ([][]byte, error) { parser := programParser{source: common.NewZeroCopySource(program)} var signatures [][]byte - for parser.IsEOF() == false { + for !parser.IsEOF() { sig, err := parser.ReadBytes() if err != nil { return nil, err diff --git a/core/signature/signature.go b/core/signature/signature.go index 46be381364..3f60e73205 100644 --- a/core/signature/signature.go +++ b/core/signature/signature.go @@ -76,7 +76,7 @@ func VerifyMultiSignature(data []byte, keys []keypair.PublicKey, m int, sigs [][ } } - if valid == false { + if !valid { return errors.New("multi-signature verification failed") } } diff --git a/core/store/ledgerstore/ledger_store.go b/core/store/ledgerstore/ledger_store.go index b2838f5812..cac164c7b1 100644 --- a/core/store/ledgerstore/ledger_store.go +++ b/core/store/ledgerstore/ledger_store.go @@ -385,7 +385,6 @@ func (this *LedgerStoreImp) setCurrentBlock(height uint32, blockHash common.Uint defer this.lock.Unlock() this.currBlockHash = blockHash this.currBlockHeight = height - return } //GetCurrentBlock return the current block height, and block hash. diff --git a/core/store/ledgerstore/state_store.go b/core/store/ledgerstore/state_store.go index 40fa169d96..62dc053338 100644 --- a/core/store/ledgerstore/state_store.go +++ b/core/store/ledgerstore/state_store.go @@ -176,6 +176,9 @@ func (self *StateStore) GetStateMerkleRoot(height uint32) (result common.Uint256 } source := common.NewZeroCopySource(value) _, eof := source.NextHash() + if eof { + err = io.ErrUnexpectedEOF + } result, eof = source.NextHash() if eof { err = io.ErrUnexpectedEOF diff --git a/core/store/overlaydb/iterator.go b/core/store/overlaydb/iterator.go index f04325e7d8..09c5587f64 100644 --- a/core/store/overlaydb/iterator.go +++ b/core/store/overlaydb/iterator.go @@ -50,11 +50,11 @@ func NewJoinIter(memIter, backendIter common.StoreIterator) *JoinIter { func (iter *JoinIter) First() bool { f := iter.first() - if f == false { + if !f { return false } for len(iter.value) == 0 { - if iter.next() == false { + if !iter.next() { return false } } @@ -73,7 +73,7 @@ func (iter *JoinIter) first() bool { if back { bkey = iter.backend.Key() bval = iter.backend.Value() - if mem == false { + if !mem { iter.key = bkey iter.value = bval iter.keyOrigin = FromBack @@ -117,12 +117,12 @@ func (iter *JoinIter) Value() []byte { func (iter *JoinIter) Next() bool { f := iter.next() - if f == false { + if !f { return false } for len(iter.value) == 0 { - if iter.next() == false { + if !iter.next() { return false } } @@ -131,10 +131,10 @@ func (iter *JoinIter) Next() bool { } func (iter *JoinIter) next() bool { - if (iter.keyOrigin == FromMem || iter.keyOrigin == FromBoth) && iter.nextMemEnd == false { + if (iter.keyOrigin == FromMem || iter.keyOrigin == FromBoth) && !iter.nextMemEnd { iter.nextMemEnd = !iter.memdb.Next() } - if (iter.keyOrigin == FromBack || iter.keyOrigin == FromBoth) && iter.nextBackEnd == false { + if (iter.keyOrigin == FromBack || iter.keyOrigin == FromBoth) && !iter.nextBackEnd { iter.nextBackEnd = !iter.backend.Next() } diff --git a/core/store/overlaydb/memdb.go b/core/store/overlaydb/memdb.go index ed305e9afc..f2cebf7c77 100644 --- a/core/store/overlaydb/memdb.go +++ b/core/store/overlaydb/memdb.go @@ -312,7 +312,6 @@ func (p *MemDB) Put(key []byte, value []byte) { p.kvSize += len(key) + len(value) p.n++ - return } // Delete deletes the value for the given key. diff --git a/core/store/overlaydb/overlaydb.go b/core/store/overlaydb/overlaydb.go index 06f989279b..a0eceab21a 100644 --- a/core/store/overlaydb/overlaydb.go +++ b/core/store/overlaydb/overlaydb.go @@ -58,7 +58,7 @@ func (self *OverlayDB) SetError(err error) { func (self *OverlayDB) Get(key []byte) (value []byte, err error) { var unknown bool value, unknown = self.memdb.Get(key) - if unknown == false { + if !unknown { return value, nil } diff --git a/core/types/header.go b/core/types/header.go index 3f96880011..97845a5e54 100644 --- a/core/types/header.go +++ b/core/types/header.go @@ -93,6 +93,10 @@ func (self *RawHeader) deserializationUnsigned(source *common.ZeroCopySource) er source.Skip(8) // ConsensusPayload _, _, irregular, eof := source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } @@ -224,14 +228,43 @@ func (bd *Header) deserializationUnsigned(source *common.ZeroCopySource) error { var irregular, eof bool bd.Version, eof = source.NextUint32() + if eof { + return io.ErrUnexpectedEOF + } bd.PrevBlockHash, eof = source.NextHash() + if eof { + return io.ErrUnexpectedEOF + } bd.TransactionsRoot, eof = source.NextHash() + if eof { + return io.ErrUnexpectedEOF + } + bd.BlockRoot, eof = source.NextHash() + if eof { + return io.ErrUnexpectedEOF + } + bd.Timestamp, eof = source.NextUint32() + if eof { + return io.ErrUnexpectedEOF + } + bd.Height, eof = source.NextUint32() + if eof { + return io.ErrUnexpectedEOF + } + bd.ConsensusData, eof = source.NextUint64() + if eof { + return io.ErrUnexpectedEOF + } bd.ConsensusPayload, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } + if irregular { return common.ErrIrregularData } diff --git a/core/types/transaction.go b/core/types/transaction.go index d1aa28ddaf..3dc64d4641 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -47,8 +47,9 @@ type Transaction struct { Raw []byte // raw transaction data - hash common.Uint256 - SignedAddr []common.Address // this is assigned when passed signature verification + hashUnsigned common.Uint256 + hash common.Uint256 + SignedAddr []common.Address // this is assigned when passed signature verification nonDirectConstracted bool // used to check literal construction like `tx := &Transaction{...}` } @@ -78,8 +79,8 @@ func (tx *Transaction) Deserialization(source *common.ZeroCopySource) error { lenUnsigned := pos - pstart source.BackUp(lenUnsigned) rawUnsigned, _ := source.NextBytes(lenUnsigned) - temp := sha256.Sum256(rawUnsigned) - tx.hash = common.Uint256(sha256.Sum256(temp[:])) + tx.hashUnsigned = sha256.Sum256(rawUnsigned) + tx.hash = common.Uint256(sha256.Sum256(tx.hashUnsigned[:])) // tx sigs length, _, irregular, eof := source.NextVarUint() @@ -142,12 +143,27 @@ func (tx *Transaction) IntoMutable() (*MutableTransaction, error) { func (tx *Transaction) deserializationUnsigned(source *common.ZeroCopySource) error { var irregular, eof bool tx.Version, eof = source.NextByte() + if eof { + return io.ErrUnexpectedEOF + } var txtype byte txtype, eof = source.NextByte() + if eof { + return io.ErrUnexpectedEOF + } tx.TxType = TransactionType(txtype) tx.Nonce, eof = source.NextUint32() + if eof { + return io.ErrUnexpectedEOF + } tx.GasPrice, eof = source.NextUint64() + if eof { + return io.ErrUnexpectedEOF + } tx.GasLimit, eof = source.NextUint64() + if eof { + return io.ErrUnexpectedEOF + } var buf []byte buf, eof = source.NextBytes(common.ADDR_LEN) if eof { @@ -205,10 +221,16 @@ func (self *RawSig) Serialization(sink *common.ZeroCopySink) error { func (self *RawSig) Deserialization(source *common.ZeroCopySource) error { var eof, irregular bool self.Invoke, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } if irregular { return common.ErrIrregularData } self.Verify, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } if irregular { return common.ErrIrregularData } @@ -307,7 +329,7 @@ type Payload interface { } func (tx *Transaction) Serialization(sink *common.ZeroCopySink) { - if tx.nonDirectConstracted == false || len(tx.Raw) == 0 { + if !tx.nonDirectConstracted || len(tx.Raw) == 0 { panic("wrong constructed transaction") } sink.WriteBytes(tx.Raw) @@ -321,7 +343,14 @@ func (tx *Transaction) Hash() common.Uint256 { return tx.hash } -func (tx *Transaction) Verify() error { - panic("unimplemented ") - return nil +// calculate a hash for another chain to sign. +// and take the chain id of ontology as 0. +func (tx *Transaction) SigHashForChain(id uint32) common.Uint256 { + sink := common.NewZeroCopySink(nil) + sink.WriteHash(tx.hashUnsigned) + if id != 0 { + sink.WriteUint32(id) + } + + return common.Uint256(sha256.Sum256(sink.Bytes())) } diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go new file mode 100644 index 0000000000..1cb830cf97 --- /dev/null +++ b/core/types/transaction_test.go @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package types + +import ( + "math" + "testing" + + "github.com/ontio/ontology/core/payload" + "github.com/stretchr/testify/assert" +) + +func TestTransaction_SigHashForChain(t *testing.T) { + mutable := &MutableTransaction{ + TxType: InvokeNeo, + Payload: &payload.InvokeCode{}, + } + + tx, err := mutable.IntoImmutable() + assert.Nil(t, err) + + assert.Equal(t, tx.Hash(), tx.SigHashForChain(0)) + assert.NotEqual(t, tx.Hash(), tx.SigHashForChain(1)) + assert.NotEqual(t, tx.Hash(), tx.SigHashForChain(math.MaxUint32)) +} diff --git a/core/validation/block_validator.go b/core/validation/block_validator.go index 210e758bc6..49155105df 100644 --- a/core/validation/block_validator.go +++ b/core/validation/block_validator.go @@ -66,11 +66,11 @@ func VerifyBlock(block *types.Block, ld *ledger.Ledger, completely bool) error { */ for _, txVerify := range block.Transactions { if errCode := VerifyTransaction(txVerify); errCode != ontErrors.ErrNoError { - return errors.New(fmt.Sprintf("VerifyTransaction failed when verifiy block")) + return errors.New("VerifyTransaction failed when verifiy block") } if errCode := VerifyTransactionWithLedger(txVerify, ld); errCode != ontErrors.ErrNoError { - return errors.New(fmt.Sprintf("VerifyTransaction failed when verifiy block")) + return errors.New("VerifyTransaction failed when verifiy block") } } } diff --git a/core/validation/transaction_validator.go b/core/validation/transaction_validator.go index e7b3b0ceee..66a39f19b7 100644 --- a/core/validation/transaction_validator.go +++ b/core/validation/transaction_validator.go @@ -98,7 +98,7 @@ func checkTransactionSignatures(tx *types.Transaction) error { } // check payer in address - if address[tx.Payer] == false { + if !address[tx.Payer] { return errors.New("signature missing for payer: " + tx.Payer.ToBase58()) } diff --git a/docker/Dockerfile b/docker/Dockerfile index 3f94ca85c5..1e4747cdac 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,9 +1,17 @@ +# 1. Stage one: build ontology +FROM golang:1.13 AS build +WORKDIR /app +RUN git clone https://github.com/ontio/ontology.git && \ + cd ontology && \ + make + +# 2. Stage two: copy compiled binary from prev builded container(referenced by name build) +FROM ubuntu:18.04 +WORKDIR /app +COPY --from=build /app/ontology/ontology ontology -FROM tianon/ubuntu-core:14.04 -ENV ONTOLOGY_PATH /var/ontology -RUN mkdir -p $ONTOLOGY_PATH -COPY ontology $ONTOLOGY_PATH -EXPOSE 20334 20335 20336 20337 20338 20339 -WORKDIR $ONTOLOGY_PATH -ENTRYPOINT ["./ontology"] +EXPOSE 20334 20335 20336 20337 20338 20339 +#NOTE! we highly recommand that you put data dir to a mounted volume, e.g. --data-dir /data/Chain +#write data to docker image is *not* a best practice +CMD ["/app/ontology"] diff --git a/errors/callstack.go b/errors/callstack.go index 7b55e58b27..0f59e69066 100644 --- a/errors/callstack.go +++ b/errors/callstack.go @@ -42,7 +42,7 @@ func GetCallStacks(err error) *CallStack { func CallStacksString(call *CallStack) string { buf := bytes.Buffer{} if call == nil { - return fmt.Sprintf("No call stack available") + return "No call stack available" } for _, stack := range call.Stacks { diff --git a/go.mod b/go.mod index 07b455ec29..55fc4b2205 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/blang/semver v3.5.1+incompatible github.com/emirpasic/gods v1.12.0 // indirect github.com/ethereum/go-ethereum v1.9.13 - github.com/gogo/protobuf v1.3.1 // indirect github.com/gorilla/websocket v1.4.1 github.com/gosuri/uilive v0.0.3 // indirect github.com/gosuri/uiprogress v0.0.1 diff --git a/go.sum b/go.sum index 0e9c55686c..027004bb5e 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= diff --git a/http/base/common/common.go b/http/base/common/common.go index cc9683d8ff..d838bda8ab 100644 --- a/http/base/common/common.go +++ b/http/base/common/common.go @@ -54,6 +54,16 @@ type BalanceOfRsp struct { Height string `json:"height"` } +type Oep4BalanceOfRsp struct { + Oep4 []Oep4Balance `json:"oep4"` + Height string `json:"height"` +} + +type Oep4Balance struct { + Addr string `json:"addr"` + Balance string `json:"balance"` +} + type MerkleProof struct { Type string TransactionsRoot string @@ -312,6 +322,24 @@ func GetBalance(address common.Address) (*BalanceOfRsp, error) { }, nil } +func GetOep4Balance(contractAddress common.Address, addrs []common.Address) (*Oep4BalanceOfRsp, error) { + balances, height, err := GetOep4ContractBalance(contractAddress, addrs, true) + if err != nil { + return nil, fmt.Errorf("get ont balance error:%s", err) + } + res := make([]Oep4Balance, len(addrs)) + for i, addr := range addrs { + res[i] = Oep4Balance{ + Addr: addr.ToBase58(), + Balance: balances[i], + } + } + return &Oep4BalanceOfRsp{ + Oep4: res, + Height: fmt.Sprintf("%d", height), + }, nil +} + func GetGrantOng(addr common.Address) (string, error) { key := append([]byte(ont.UNBOUND_TIME_OFFSET), addr[:]...) value, err := ledger.DefLedger.GetStorageItem(utils.OntContractAddress, key) @@ -355,6 +383,7 @@ func GetContractBalance(cVersion byte, contractAddres []common.Address, accAddr if err != nil { return nil, 0, fmt.Errorf("NewNativeInvokeTransaction error:%s", err) } + tx, err := mutable.IntoImmutable() if err != nil { return nil, 0, err @@ -384,6 +413,45 @@ func GetContractBalance(cVersion byte, contractAddres []common.Address, accAddr return balances, height, nil } +func GetOep4ContractBalance(contractAddr common.Address, accAddr []common.Address, atomic bool) ([]string, uint32, error) { + txes := make([]*types.Transaction, 0, len(accAddr)) + var mutable *types.MutableTransaction + var err error + for _, userAcc := range accAddr { + mutable, err = NewNeovmInvokeTransaction(0, 0, contractAddr, []interface{}{"balanceOf", []interface{}{userAcc}}) + if err != nil { + return nil, 0, fmt.Errorf("NewNeovmInvokeTransaction error:%s", err) + } + + tx, err := mutable.IntoImmutable() + if err != nil { + return nil, 0, err + } + + txes = append(txes, tx) + } + + results, height, err := bactor.PreExecuteContractBatch(txes, atomic) + if err != nil { + return nil, 0, fmt.Errorf("PrepareInvokeContract error:%s", err) + } + balances := make([]string, 0, len(contractAddr)) + for _, result := range results { + if result.State == 0 { + return nil, 0, fmt.Errorf("prepare invoke failed") + } + data, err := hex.DecodeString(result.Result.(string)) + if err != nil { + return nil, 0, fmt.Errorf("hex.DecodeString error:%s", err) + } + + balance := common.BigIntFromNeoBytes(data) + balances = append(balances, balance.String()) + } + + return balances, height, nil +} + func GetContractAllowance(cVersion byte, contractAddr, fromAddr, toAddr common.Address) (uint64, error) { type allowanceStruct struct { From common.Address diff --git a/http/base/rpc/result.go b/http/base/rpc/result.go index 89d7e66854..b091d13383 100644 --- a/http/base/rpc/result.go +++ b/http/base/rpc/result.go @@ -22,10 +22,10 @@ import ( Err "github.com/ontio/ontology/http/base/error" ) -func responseSuccess(result interface{}) map[string]interface{} { - return responsePack(Err.SUCCESS, result) +func ResponseSuccess(result interface{}) map[string]interface{} { + return ResponsePack(Err.SUCCESS, result) } -func responsePack(errcode int64, result interface{}) map[string]interface{} { +func ResponsePack(errcode int64, result interface{}) map[string]interface{} { resp := map[string]interface{}{ "error": errcode, "desc": Err.ErrMap[errcode], diff --git a/http/base/rpc/rpc.go b/http/base/rpc/rpc.go index 491d16c5c1..f59dcb1a02 100644 --- a/http/base/rpc/rpc.go +++ b/http/base/rpc/rpc.go @@ -30,10 +30,11 @@ import ( "sync" "github.com/ontio/ontology/common/log" - "github.com/ontio/ontology/http/base/common" berr "github.com/ontio/ontology/http/base/error" ) +const MAX_REQUEST_BODY_SIZE = 1 << 20 + func init() { mainMux.m = make(map[string]func([]interface{}) map[string]interface{}) } @@ -95,7 +96,7 @@ func Handle(w http.ResponseWriter, r *http.Request) { } request := make(map[string]interface{}) defer r.Body.Close() - decoder := json.NewDecoder(io.LimitReader(r.Body, common.MAX_REQUEST_BODY_SIZE)) + decoder := json.NewDecoder(io.LimitReader(r.Body, MAX_REQUEST_BODY_SIZE)) err := decoder.Decode(&request) if err != nil { log.Error("HTTP JSON RPC Handle - json.Unmarshal: ", err) diff --git a/http/base/rpc/interfaces.go b/http/jsonrpc/interfaces.go similarity index 62% rename from http/base/rpc/interfaces.go rename to http/jsonrpc/interfaces.go index 1ab41efec4..344aaed1ac 100644 --- a/http/base/rpc/interfaces.go +++ b/http/jsonrpc/interfaces.go @@ -16,7 +16,7 @@ * along with The ontology. If not, see . */ -package rpc +package jsonrpc import ( "encoding/hex" @@ -31,13 +31,14 @@ import ( bactor "github.com/ontio/ontology/http/base/actor" bcomn "github.com/ontio/ontology/http/base/common" berr "github.com/ontio/ontology/http/base/error" + "github.com/ontio/ontology/http/base/rpc" "github.com/ontio/ontology/smartcontract/service/native/utils" ) //get best block hash func GetBestBlockHash(params []interface{}) map[string]interface{} { hash := bactor.CurrentBlockHash() - return responseSuccess(hash.ToHexString()) + return rpc.ResponseSuccess(hash.ToHexString()) } // get block by height or hash @@ -46,7 +47,7 @@ func GetBestBlockHash(params []interface{}) map[string]interface{} { // {"jsonrpc": "2.0", "method": "getblock", "params": ["aabbcc.."], "id": 0} func GetBlock(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } var err error var hash common.Uint256 @@ -56,40 +57,40 @@ func GetBlock(params []interface{}) map[string]interface{} { index := uint32(params[0].(float64)) hash = bactor.GetBlockHashFromStore(index) if hash == common.UINT256_EMPTY { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } // block hash case string: str := params[0].(string) hash, err = common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } block, err := bactor.GetBlockFromStore(hash) if err != nil { - return responsePack(berr.UNKNOWN_BLOCK, "unknown block") + return rpc.ResponsePack(berr.UNKNOWN_BLOCK, "unknown block") } if len(params) >= 2 { switch (params[1]).(type) { case float64: json := uint32(params[1].(float64)) if json == 1 { - return responseSuccess(bcomn.GetBlockInfo(block)) + return rpc.ResponseSuccess(bcomn.GetBlockInfo(block)) } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } - return responseSuccess(common.ToHexString(block.ToArray())) + return rpc.ResponseSuccess(common.ToHexString(block.ToArray())) } //get block height func GetBlockCount(params []interface{}) map[string]interface{} { height := bactor.GetCurrentBlockHeight() - return responseSuccess(height + 1) + return rpc.ResponseSuccess(height + 1) } //get block hash @@ -97,25 +98,25 @@ func GetBlockCount(params []interface{}) map[string]interface{} { // {"jsonrpc": "2.0", "method": "getblockhash", "params": [1], "id": 0} func GetBlockHash(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } switch params[0].(type) { case float64: height := uint32(params[0].(float64)) hash := bactor.GetBlockHashFromStore(height) if hash == common.UINT256_EMPTY { - return responsePack(berr.UNKNOWN_BLOCK, "") + return rpc.ResponsePack(berr.UNKNOWN_BLOCK, "") } - return responseSuccess(hash.ToHexString()) + return rpc.ResponseSuccess(hash.ToHexString()) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } //get node connection count func GetConnectionCount(params []interface{}) map[string]interface{} { count := bactor.GetConnectionCnt() - return responseSuccess(count) + return rpc.ResponseSuccess(count) } //get node connection most height @@ -123,10 +124,10 @@ func GetSyncStatus(params []interface{}) map[string]interface{} { status, err := bcomn.GetSyncStatus() if err != nil { log.Errorf("GetSyncStatus error:%s", err) - return responsePack(berr.INTERNAL_ERROR, false) + return rpc.ResponsePack(berr.INTERNAL_ERROR, false) } - return responseSuccess(status) + return rpc.ResponseSuccess(status) } func GetRawMemPool(params []interface{}) map[string]interface{} { @@ -136,53 +137,53 @@ func GetRawMemPool(params []interface{}) map[string]interface{} { txs = append(txs, bcomn.TransArryByteToHexString(t)) } if len(txs) == 0 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } - return responseSuccess(txs) + return rpc.ResponseSuccess(txs) } //get memory pool transaction count func GetMemPoolTxCount(params []interface{}) map[string]interface{} { count, err := bactor.GetTxnCount() if err != nil { - return responsePack(berr.INTERNAL_ERROR, nil) + return rpc.ResponsePack(berr.INTERNAL_ERROR, nil) } - return responseSuccess(count) + return rpc.ResponseSuccess(count) } //get memory pool transaction hash func GetMemPoolTxHashList(params []interface{}) map[string]interface{} { txHashList, err := bactor.GetTxnHashList() if err != nil { - return responsePack(berr.INTERNAL_ERROR, nil) + return rpc.ResponsePack(berr.INTERNAL_ERROR, nil) } - return responseSuccess(txHashList) + return rpc.ResponseSuccess(txHashList) } //get memory pool transaction state func GetMemPoolTxState(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } switch params[0].(type) { case string: str := params[0].(string) hash, err := common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } txEntry, err := bactor.GetTxFromPool(hash) if err != nil { - return responsePack(berr.UNKNOWN_TRANSACTION, "unknown transaction") + return rpc.ResponsePack(berr.UNKNOWN_TRANSACTION, "unknown transaction") } - attrs := []bcomn.TXNAttrInfo{} + var attrs []bcomn.TXNAttrInfo for _, t := range txEntry.Attrs { attrs = append(attrs, bcomn.TXNAttrInfo{t.Height, int(t.Type), int(t.ErrCode)}) } info := bcomn.TXNEntryInfo{attrs} - return responseSuccess(info) + return rpc.ResponseSuccess(info) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } @@ -191,7 +192,7 @@ func GetMemPoolTxState(params []interface{}) map[string]interface{} { // {"jsonrpc": "2.0", "method": "getrawtransaction", "params": ["transactioin hash in hex"], "id": 0} func GetRawTransaction(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } var tx *types.Transaction var height uint32 @@ -200,16 +201,16 @@ func GetRawTransaction(params []interface{}) map[string]interface{} { str := params[0].(string) hash, err := common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } h, t, err := bactor.GetTxnWithHeightByTxHash(hash) if err != nil { - return responsePack(berr.UNKNOWN_TRANSACTION, "unknown transaction") + return rpc.ResponsePack(berr.UNKNOWN_TRANSACTION, "unknown transaction") } height = h tx = t default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } if len(params) >= 2 { @@ -219,21 +220,21 @@ func GetRawTransaction(params []interface{}) map[string]interface{} { if json == 1 { txinfo := bcomn.TransArryByteToHexString(tx) txinfo.Height = height - return responseSuccess(txinfo) + return rpc.ResponseSuccess(txinfo) } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } - return responseSuccess(common.ToHexString(common.SerializeToBytes(tx))) + return rpc.ResponseSuccess(common.ToHexString(common.SerializeToBytes(tx))) } //get storage from contract // {"jsonrpc": "2.0", "method": "getstorage", "params": ["code hash", "key"], "id": 0} func GetStorage(params []interface{}) map[string]interface{} { if len(params) < 2 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } var address common.Address @@ -244,10 +245,10 @@ func GetStorage(params []interface{}) map[string]interface{} { var err error address, err = bcomn.GetAddress(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } switch params[1].(type) { @@ -255,20 +256,20 @@ func GetStorage(params []interface{}) map[string]interface{} { str := params[1].(string) hex, err := hex.DecodeString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } key = hex default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } value, err := bactor.GetStorageItem(address, key) if err != nil { if err == scom.ErrNotFound { - return responseSuccess(nil) + return rpc.ResponseSuccess(nil) } - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(common.ToHexString(value)) + return rpc.ResponseSuccess(common.ToHexString(value)) } //send raw transaction @@ -276,7 +277,7 @@ func GetStorage(params []interface{}) map[string]interface{} { // {"jsonrpc": "2.0", "method": "sendrawtransaction", "params": ["raw transactioin in hex"], "id": 0} func SendRawTransaction(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } var hash common.Uint256 switch params[0].(type) { @@ -284,11 +285,11 @@ func SendRawTransaction(params []interface{}) map[string]interface{} { str := params[0].(string) raw, err := common.HexToBytes(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } txn, err := types.TransactionFromRawBytes(raw) if err != nil { - return responsePack(berr.INVALID_TRANSACTION, "") + return rpc.ResponsePack(berr.INVALID_TRANSACTION, "") } hash = txn.Hash() log.Debugf("SendRawTransaction recv %s", hash.ToHexString()) @@ -299,9 +300,9 @@ func SendRawTransaction(params []interface{}) map[string]interface{} { result, err := bactor.PreExecuteContract(txn) if err != nil { log.Infof("PreExec: ", err) - return responsePack(berr.SMARTCODE_ERROR, err.Error()) + return rpc.ResponsePack(berr.SMARTCODE_ERROR, err.Error()) } - return responseSuccess(bcomn.ConvertPreExecuteResult(result)) + return rpc.ResponseSuccess(bcomn.ConvertPreExecuteResult(result)) } } } @@ -309,29 +310,29 @@ func SendRawTransaction(params []interface{}) map[string]interface{} { log.Debugf("SendRawTransaction send to txpool %s", hash.ToHexString()) if errCode, desc := bcomn.SendTxToPool(txn); errCode != ontErrors.ErrNoError { log.Warnf("SendRawTransaction verified %s error: %s", hash.ToHexString(), desc) - return responsePack(int64(errCode), desc) + return rpc.ResponsePack(int64(errCode), desc) } log.Debugf("SendRawTransaction verified %s", hash.ToHexString()) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(hash.ToHexString()) + return rpc.ResponseSuccess(hash.ToHexString()) } //get node version func GetNodeVersion(params []interface{}) map[string]interface{} { - return responseSuccess(config.Version) + return rpc.ResponseSuccess(config.Version) } // get networkid func GetNetworkId(params []interface{}) map[string]interface{} { - return responseSuccess(config.DefConfig.P2PNode.NetworkId) + return rpc.ResponseSuccess(config.DefConfig.P2PNode.NetworkId) } //get contract state func GetContractState(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } var contract *payload.DeployCode switch params[0].(type) { @@ -339,39 +340,39 @@ func GetContractState(params []interface{}) map[string]interface{} { str := params[0].(string) address, err := bcomn.GetAddress(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } c, err := bactor.GetContractStateFromStore(address) if err != nil { - return responsePack(berr.UNKNOWN_CONTRACT, berr.ErrMap[berr.UNKNOWN_CONTRACT]) + return rpc.ResponsePack(berr.UNKNOWN_CONTRACT, berr.ErrMap[berr.UNKNOWN_CONTRACT]) } contract = c default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } if len(params) >= 2 { switch (params[1]).(type) { case float64: json := uint32(params[1].(float64)) if json == 1 { - return responseSuccess(bcomn.TransPayloadToHex(contract)) + return rpc.ResponseSuccess(bcomn.TransPayloadToHex(contract)) } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } sink := common.NewZeroCopySink(nil) contract.Serialization(sink) - return responseSuccess(common.ToHexString(sink.Bytes())) + return rpc.ResponseSuccess(common.ToHexString(sink.Bytes())) } //get smartconstract event func GetSmartCodeEvent(params []interface{}) map[string]interface{} { if !config.DefConfig.Common.EnableEventLog { - return responsePack(berr.INVALID_METHOD, "") + return rpc.ResponsePack(berr.INVALID_METHOD, "") } if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } switch (params[0]).(type) { @@ -381,42 +382,42 @@ func GetSmartCodeEvent(params []interface{}) map[string]interface{} { eventInfos, err := bactor.GetEventNotifyByHeight(height) if err != nil { if err == scom.ErrNotFound { - return responseSuccess(nil) + return rpc.ResponseSuccess(nil) } - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } eInfos := make([]*bcomn.ExecuteNotify, 0, len(eventInfos)) for _, eventInfo := range eventInfos { _, notify := bcomn.GetExecuteNotify(eventInfo) eInfos = append(eInfos, ¬ify) } - return responseSuccess(eInfos) + return rpc.ResponseSuccess(eInfos) //txhash case string: str := params[0].(string) hash, err := common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } eventInfo, err := bactor.GetEventNotifyByTxHash(hash) if err != nil { if scom.ErrNotFound == err { - return responseSuccess(nil) + return rpc.ResponseSuccess(nil) } - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } _, notify := bcomn.GetExecuteNotify(eventInfo) - return responseSuccess(notify) + return rpc.ResponseSuccess(notify) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } //get block height by transaction hash func GetBlockHeightByTxHash(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } switch (params[0]).(type) { @@ -425,129 +426,166 @@ func GetBlockHeightByTxHash(params []interface{}) map[string]interface{} { str := params[0].(string) hash, err := common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } height, _, err := bactor.GetTxnWithHeightByTxHash(hash) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(height) + return rpc.ResponseSuccess(height) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } //get balance of address func GetBalance(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } addrBase58, ok := params[0].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } address, err := common.AddressFromBase58(addrBase58) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } rsp, err := bcomn.GetBalance(address) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(rsp) + return rpc.ResponseSuccess(rsp) +} + +//get balance of address +func GetOep4Balance(params []interface{}) map[string]interface{} { + if len(params) < 2 { + return rpc.ResponsePack(berr.INVALID_PARAMS, "") + } + + contractAddrHex, ok := params[0].(string) + if !ok { + return rpc.ResponsePack(berr.INVALID_PARAMS, "") + } + contractAddr, err := common.AddressFromHexString(contractAddrHex) + if err != nil { + return rpc.ResponsePack(berr.INVALID_PARAMS, "") + } + addrs, err := parseAddressParam(params[1].([]interface{})) + if err != nil { + return rpc.ResponsePack(berr.INVALID_PARAMS, "") + } + rsp, err := bcomn.GetOep4Balance(contractAddr, addrs) + if err != nil { + return rpc.ResponsePack(berr.INVALID_PARAMS, "") + } + return rpc.ResponseSuccess(rsp) +} + +func parseAddressParam(params []interface{}) ([]common.Address, error) { + res := make([]common.Address, len(params)) + var err error + for i, param := range params { + res[i], err = common.AddressFromBase58(param.(string)) + if err != nil { + return nil, err + } + } + return res, nil } //get allowance func GetAllowance(params []interface{}) map[string]interface{} { if len(params) < 3 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } asset, ok := params[0].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } fromAddrStr, ok := params[1].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } fromAddr, err := bcomn.GetAddress(fromAddrStr) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } toAddrStr, ok := params[2].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } toAddr, err := bcomn.GetAddress(toAddrStr) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } rsp, err := bcomn.GetAllowance(asset, fromAddr, toAddr) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(rsp) + return rpc.ResponseSuccess(rsp) } //get merkle proof by transaction hash func GetMerkleProof(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } str, ok := params[0].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } hash, err := common.Uint256FromHexString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } height, _, err := bactor.GetTxnWithHeightByTxHash(hash) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } header, err := bactor.GetHeaderByHeight(height) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } curHeight := bactor.GetCurrentBlockHeight() curHeader, err := bactor.GetHeaderByHeight(curHeight) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } proof, err := bactor.GetMerkleProof(uint32(height), uint32(curHeight)) if err != nil { - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } var hashes []string for _, v := range proof { hashes = append(hashes, v.ToHexString()) } - return responseSuccess(bcomn.MerkleProof{"MerkleProof", header.TransactionsRoot.ToHexString(), height, + return rpc.ResponseSuccess(bcomn.MerkleProof{"MerkleProof", header.TransactionsRoot.ToHexString(), height, curHeader.BlockRoot.ToHexString(), curHeight, hashes}) } //get block transactions by height func GetBlockTxsByHeight(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } switch params[0].(type) { case float64: height := uint32(params[0].(float64)) hash := bactor.GetBlockHashFromStore(height) if hash == common.UINT256_EMPTY { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } block, err := bactor.GetBlockFromStore(hash) if err != nil { - return responsePack(berr.UNKNOWN_BLOCK, "") + return rpc.ResponsePack(berr.UNKNOWN_BLOCK, "") } - return responseSuccess(bcomn.GetBlockTransactions(block)) + return rpc.ResponseSuccess(bcomn.GetBlockTransactions(block)) default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } } @@ -555,95 +593,95 @@ func GetBlockTxsByHeight(params []interface{}) map[string]interface{} { func GetGasPrice(params []interface{}) map[string]interface{} { result, err := bcomn.GetGasPrice() if err != nil { - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } - return responseSuccess(result) + return rpc.ResponseSuccess(result) } // get unbound ong of address func GetUnboundOng(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } str, ok := params[0].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } toAddr, err := common.AddressFromBase58(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } fromAddr := utils.OntContractAddress rsp, err := bcomn.GetAllowance("ong", fromAddr, toAddr) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responseSuccess(rsp) + return rpc.ResponseSuccess(rsp) } // get grant ong of address func GetGrantOng(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } str, ok := params[0].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } toAddr, err := common.AddressFromBase58(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } rsp, err := bcomn.GetGrantOng(toAddr) if err != nil { - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } - return responseSuccess(rsp) + return rpc.ResponseSuccess(rsp) } //get cross chain message by height func GetCrossChainMsg(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } height, ok := (params[0]).(float64) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } msg, err := bactor.GetCrossChainMsg(uint32(height)) if err != nil { log.Errorf("GetCrossChainMsg, get cross chain msg from db error:%s", err) - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } header, err := bactor.GetHeaderByHeight(uint32(height) + 1) if err != nil { log.Errorf("GetCrossChainMsg, get block by height from db error:%s", err) - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } - return responseSuccess(bcomn.TransferCrossChainMsg(msg, header.Bookkeepers)) + return rpc.ResponseSuccess(bcomn.TransferCrossChainMsg(msg, header.Bookkeepers)) } //get cross chain state proof func GetCrossStatesProof(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, nil) + return rpc.ResponsePack(berr.INVALID_PARAMS, nil) } height, ok := params[0].(float64) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } str, ok := params[1].(string) if !ok { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } key, err := hex.DecodeString(str) if err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } proof, err := bactor.GetCrossStatesProof(uint32(height), key) if err != nil { log.Errorf("GetCrossStatesProof, bactor.GetCrossStatesProof error:%s", err) - return responsePack(berr.INTERNAL_ERROR, "") + return rpc.ResponsePack(berr.INTERNAL_ERROR, "") } - return responseSuccess(bcomn.CrossStatesProof{"CrossStatesProof", hex.EncodeToString(proof)}) + return rpc.ResponseSuccess(bcomn.CrossStatesProof{"CrossStatesProof", hex.EncodeToString(proof)}) } diff --git a/http/jsonrpc/rpc_server.go b/http/jsonrpc/rpc_server.go index be207087fb..89f3b988bd 100644 --- a/http/jsonrpc/rpc_server.go +++ b/http/jsonrpc/rpc_server.go @@ -32,37 +32,38 @@ import ( func StartRPCServer() error { log.Debug() http.HandleFunc("/", rpc.Handle) - rpc.HandleFunc("getbestblockhash", rpc.GetBestBlockHash) - rpc.HandleFunc("getblock", rpc.GetBlock) - rpc.HandleFunc("getblockcount", rpc.GetBlockCount) - rpc.HandleFunc("getblockhash", rpc.GetBlockHash) - rpc.HandleFunc("getconnectioncount", rpc.GetConnectionCount) - rpc.HandleFunc("getsyncstatus", rpc.GetSyncStatus) + rpc.HandleFunc("getbestblockhash", GetBestBlockHash) + rpc.HandleFunc("getblock", GetBlock) + rpc.HandleFunc("getblockcount", GetBlockCount) + rpc.HandleFunc("getblockhash", GetBlockHash) + rpc.HandleFunc("getconnectioncount", GetConnectionCount) + rpc.HandleFunc("getsyncstatus", GetSyncStatus) //HandleFunc("getrawmempool", GetRawMemPool) - rpc.HandleFunc("getrawtransaction", rpc.GetRawTransaction) - rpc.HandleFunc("sendrawtransaction", rpc.SendRawTransaction) - rpc.HandleFunc("getstorage", rpc.GetStorage) - rpc.HandleFunc("getversion", rpc.GetNodeVersion) - rpc.HandleFunc("getnetworkid", rpc.GetNetworkId) + rpc.HandleFunc("getrawtransaction", GetRawTransaction) + rpc.HandleFunc("sendrawtransaction", SendRawTransaction) + rpc.HandleFunc("getstorage", GetStorage) + rpc.HandleFunc("getversion", GetNodeVersion) + rpc.HandleFunc("getnetworkid", GetNetworkId) - rpc.HandleFunc("getcontractstate", rpc.GetContractState) - rpc.HandleFunc("getmempooltxcount", rpc.GetMemPoolTxCount) - rpc.HandleFunc("getmempooltxstate", rpc.GetMemPoolTxState) - rpc.HandleFunc("getmempooltxhashlist", rpc.GetMemPoolTxHashList) - rpc.HandleFunc("getsmartcodeevent", rpc.GetSmartCodeEvent) - rpc.HandleFunc("getblockheightbytxhash", rpc.GetBlockHeightByTxHash) + rpc.HandleFunc("getcontractstate", GetContractState) + rpc.HandleFunc("getmempooltxcount", GetMemPoolTxCount) + rpc.HandleFunc("getmempooltxstate", GetMemPoolTxState) + rpc.HandleFunc("getmempooltxhashlist", GetMemPoolTxHashList) + rpc.HandleFunc("getsmartcodeevent", GetSmartCodeEvent) + rpc.HandleFunc("getblockheightbytxhash", GetBlockHeightByTxHash) - rpc.HandleFunc("getbalance", rpc.GetBalance) - rpc.HandleFunc("getallowance", rpc.GetAllowance) - rpc.HandleFunc("getmerkleproof", rpc.GetMerkleProof) - rpc.HandleFunc("getblocktxsbyheight", rpc.GetBlockTxsByHeight) - rpc.HandleFunc("getgasprice", rpc.GetGasPrice) - rpc.HandleFunc("getunboundong", rpc.GetUnboundOng) - rpc.HandleFunc("getgrantong", rpc.GetGrantOng) + rpc.HandleFunc("getbalance", GetBalance) + rpc.HandleFunc("getoep4balance", GetOep4Balance) + rpc.HandleFunc("getallowance", GetAllowance) + rpc.HandleFunc("getmerkleproof", GetMerkleProof) + rpc.HandleFunc("getblocktxsbyheight", GetBlockTxsByHeight) + rpc.HandleFunc("getgasprice", GetGasPrice) + rpc.HandleFunc("getunboundong", GetUnboundOng) + rpc.HandleFunc("getgrantong", GetGrantOng) - rpc.HandleFunc("getcrosschainmsg", rpc.GetCrossChainMsg) - rpc.HandleFunc("getcrossstatesproof", rpc.GetCrossStatesProof) + rpc.HandleFunc("getcrosschainmsg", GetCrossChainMsg) + rpc.HandleFunc("getcrossstatesproof", GetCrossStatesProof) err := http.ListenAndServe(":"+strconv.Itoa(int(cfg.DefConfig.Rpc.HttpJsonPort)), nil) if err != nil { diff --git a/http/base/rpc/local_interfaces.go b/http/localrpc/local_interfaces.go similarity index 75% rename from http/base/rpc/local_interfaces.go rename to http/localrpc/local_interfaces.go index 5b23dceaa8..652f660b15 100644 --- a/http/base/rpc/local_interfaces.go +++ b/http/localrpc/local_interfaces.go @@ -16,34 +16,21 @@ * along with The ontology. If not, see . */ -package rpc +package localrpc import ( - "os" - "path/filepath" "time" "github.com/ontio/ontology/common/log" bactor "github.com/ontio/ontology/http/base/actor" "github.com/ontio/ontology/http/base/common" berr "github.com/ontio/ontology/http/base/error" + "github.com/ontio/ontology/http/base/rpc" ) -const ( - RANDBYTELEN = 4 -) - -func getCurrentDirectory() string { - dir, err := filepath.Abs(filepath.Dir(os.Args[0])) - if err != nil { - log.Fatal(err) - } - return dir -} - func GetNeighbor(params []interface{}) map[string]interface{} { addr := bactor.GetNeighborAddrs() - return responseSuccess(addr) + return rpc.ResponseSuccess(addr) } func GetNodeState(params []interface{}) map[string]interface{} { @@ -56,7 +43,7 @@ func GetNodeState(params []interface{}) map[string]interface{} { height := bactor.GetCurrentBlockHeight() txnCnt, err := bactor.GetTxnCount() if err != nil { - return responsePack(berr.INTERNAL_ERROR, false) + return rpc.ResponsePack(berr.INTERNAL_ERROR, false) } n := common.NodeInfo{ NodeTime: t, @@ -68,35 +55,35 @@ func GetNodeState(params []interface{}) map[string]interface{} { Height: height, TxnCnt: txnCnt, } - return responseSuccess(n) + return rpc.ResponseSuccess(n) } func StartConsensus(params []interface{}) map[string]interface{} { if err := bactor.ConsensusSrvStart(); err != nil { - return responsePack(berr.INTERNAL_ERROR, false) + return rpc.ResponsePack(berr.INTERNAL_ERROR, false) } - return responsePack(berr.SUCCESS, true) + return rpc.ResponsePack(berr.SUCCESS, true) } func StopConsensus(params []interface{}) map[string]interface{} { if err := bactor.ConsensusSrvHalt(); err != nil { - return responsePack(berr.INTERNAL_ERROR, false) + return rpc.ResponsePack(berr.INTERNAL_ERROR, false) } - return responsePack(berr.SUCCESS, true) + return rpc.ResponsePack(berr.SUCCESS, true) } func SetDebugInfo(params []interface{}) map[string]interface{} { if len(params) < 1 { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } switch params[0].(type) { case float64: level := params[0].(float64) if err := log.Log().SetDebugLevel(int(level)); err != nil { - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } default: - return responsePack(berr.INVALID_PARAMS, "") + return rpc.ResponsePack(berr.INVALID_PARAMS, "") } - return responsePack(berr.SUCCESS, true) + return rpc.ResponsePack(berr.SUCCESS, true) } diff --git a/http/localrpc/local_server.go b/http/localrpc/local_server.go index 9e93f3cf95..246232c635 100644 --- a/http/localrpc/local_server.go +++ b/http/localrpc/local_server.go @@ -38,11 +38,11 @@ func StartLocalServer() error { log.Debug() http.HandleFunc(LOCAL_DIR, rpc.Handle) - rpc.HandleFunc("getneighbor", rpc.GetNeighbor) - rpc.HandleFunc("getnodestate", rpc.GetNodeState) - rpc.HandleFunc("startconsensus", rpc.StartConsensus) - rpc.HandleFunc("stopconsensus", rpc.StopConsensus) - rpc.HandleFunc("setdebuginfo", rpc.SetDebugInfo) + rpc.HandleFunc("getneighbor", GetNeighbor) + rpc.HandleFunc("getnodestate", GetNodeState) + rpc.HandleFunc("startconsensus", StartConsensus) + rpc.HandleFunc("stopconsensus", StopConsensus) + rpc.HandleFunc("setdebuginfo", SetDebugInfo) // TODO: only listen to local host err := http.ListenAndServe(LOCAL_HOST+":"+strconv.Itoa(int(cfg.DefConfig.Rpc.HttpLocalPort)), nil) diff --git a/http/restful/restful/router.go b/http/restful/restful/router.go index 6a14ad1447..3d5266e8a6 100644 --- a/http/restful/restful/router.go +++ b/http/restful/restful/router.go @@ -48,7 +48,7 @@ func (this *Router) Try(path string, method string) (http.HandlerFunc, paramsMap for _, route := range this.routes { if route.Method == method { match := route.Path.MatchString(path) - if match == false { + if !match { continue } params := paramsMap{} @@ -71,11 +71,9 @@ func (this *Router) add(method string, path string, handler http.HandlerFunc) { if strings.Contains(path, ":") { matches := regexp.MustCompile(`:(\w+)`).FindAllStringSubmatch(path, -1) - if matches != nil { - for _, v := range matches { - route.Params = append(route.Params, v[1]) - path = strings.Replace(path, v[0], `(\w+)`, 1) - } + for _, v := range matches { + route.Params = append(route.Params, v[1]) + path = strings.Replace(path, v[0], `(\w+)`, 1) } } compiledPath, err := regexp.Compile(path) @@ -138,6 +136,6 @@ func parseParams(route *Route, path string) paramsMap { func getParam(r *http.Request, key string) string { ctx := r.Context() params := ctx.Value("params").(paramsMap) - val, _ := params[key] + val := params[key] return val } diff --git a/main.go b/main.go index ec4aeb3d28..863784c639 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,6 @@ import ( "github.com/ontio/ontology/core/ledger" "github.com/ontio/ontology/events" bactor "github.com/ontio/ontology/http/base/actor" - hserver "github.com/ontio/ontology/http/base/actor" "github.com/ontio/ontology/http/jsonrpc" "github.com/ontio/ontology/http/localrpc" "github.com/ontio/ontology/http/nodeinfo" @@ -292,8 +291,8 @@ func initTxPool(ctx *cli.Context) (*proc.TXPoolServer, error) { stfValidator, _ := stateful.NewValidator("stateful_validator") stfValidator.Register(txPoolServer.GetPID(tc.VerifyRspActor)) - hserver.SetTxnPoolPid(txPoolServer.GetPID(tc.TxPoolActor)) - hserver.SetTxPid(txPoolServer.GetPID(tc.TxActor)) + bactor.SetTxnPoolPid(txPoolServer.GetPID(tc.TxPoolActor)) + bactor.SetTxPid(txPoolServer.GetPID(tc.TxActor)) log.Infof("TxPool init success") return txPoolServer, nil @@ -314,7 +313,7 @@ func initP2PNode(ctx *cli.Context, txpoolSvr *proc.TXPoolServer, acct *account.A } netreqactor.SetTxnPoolPid(txpoolSvr.GetPID(tc.TxActor)) txpoolSvr.Net = p2p.GetNetwork() - hserver.SetNetServer(p2p.GetNetwork()) + bactor.SetNetServer(p2p.GetNetwork()) p2p.WaitForPeersStart() log.Infof("P2P init success") return p2p, p2p.GetNetwork(), nil @@ -334,7 +333,7 @@ func initConsensus(ctx *cli.Context, net p2p.P2P, txpoolSvr *proc.TXPoolServer, consensusService.Start() netreqactor.SetConsensusPid(consensusService.GetPID()) - hserver.SetConsensusPid(consensusService.GetPID()) + bactor.SetConsensusPid(consensusService.GetPID()) log.Infof("Consensus init success") return consensusService, nil @@ -408,7 +407,8 @@ func initWs(ctx *cli.Context) { } func initNodeInfo(ctx *cli.Context, p2pSvr *p2pserver.P2PServer) { - if config.DefConfig.P2PNode.HttpInfoPort == 0 { + // testmode has no p2pserver(see function initP2PNode for detail), simply ignore httpInfoPort in testmode + if ctx.Bool(utils.GetFlagName(utils.EnableTestModeFlag)) || config.DefConfig.P2PNode.HttpInfoPort == 0 { return } go nodeinfo.StartServer(p2pSvr.GetNetwork()) diff --git a/merkle/merkle_tree.go b/merkle/merkle_tree.go index 80a275298f..2850260c49 100644 --- a/merkle/merkle_tree.go +++ b/merkle/merkle_tree.go @@ -274,7 +274,7 @@ func (self *CompactMerkleTree) subproof(m, n uint32, b bool) []common.Uint256 { } //assert m == n - if b == false { + if !b { pos := getSubTreePos(n) //assert len(pos) == 1 if len(pos) != 1 { diff --git a/p2pserver/common/p2p_common.go b/p2pserver/common/p2p_common.go index 1adb2b8ce8..8a3e2880c5 100644 --- a/p2pserver/common/p2p_common.go +++ b/p2pserver/common/p2p_common.go @@ -117,6 +117,7 @@ const ( GET_SUBNET_MEMBERS_TYPE = "getmembers" // request subnet members SUBNET_MEMBERS_TYPE = "members" // response subnet members + SUBNET_OFFLINE_TYPE = "offline" // offline witness message ) //ParseIPAddr return ip address diff --git a/p2pserver/message/types/message.go b/p2pserver/message/types/message.go index ad16055650..3cc9279977 100644 --- a/p2pserver/message/types/message.go +++ b/p2pserver/message/types/message.go @@ -201,6 +201,8 @@ func makeEmptyMessage(cmdType string) Message { return &SubnetMembersRequest{} case common.SUBNET_MEMBERS_TYPE: return &SubnetMembers{} + case common.SUBNET_OFFLINE_TYPE: + return &OfflineWitnessMsg{} default: return &UnknownMessage{Cmd: cmdType} } diff --git a/p2pserver/message/types/offline_witness.go b/p2pserver/message/types/offline_witness.go new file mode 100644 index 0000000000..d45949b4e2 --- /dev/null +++ b/p2pserver/message/types/offline_witness.go @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package types + +import ( + "crypto/sha256" + "errors" + "math" + + "github.com/ontio/ontology/account" + "github.com/ontio/ontology/common" + vconfig "github.com/ontio/ontology/consensus/vbft/config" + "github.com/ontio/ontology/core/signature" + common2 "github.com/ontio/ontology/p2pserver/common" +) + +type OfflineWitnessMsg struct { + Timestamp uint32 `json:"timestamp"` + View uint32 `json:"view"` + NodePubKeys []string `json:"nodePubKeys"` + Proposer string `json:"proposer"` + + ProposerSig []byte `json:"proposerSig"` + + Voters []VoterMsg `json:"voters"` +} + +type VoterMsg struct { + OfflineIndex []uint8 `json:"offlineIndex"` + PubKey string `json:"pubKey"` + Sig []byte `json:"sig"` +} + +func (this *OfflineWitnessMsg) CmdType() string { + return common2.SUBNET_OFFLINE_TYPE +} + +func (self *OfflineWitnessMsg) Serialization(sink *common.ZeroCopySink) { + self.serializeUnsigned(sink) + sink.WriteVarBytes(self.ProposerSig) + + sink.WriteUint32(uint32(len(self.Voters))) + for _, val := range self.Voters { + sink.WriteVarBytes(val.OfflineIndex) + sink.WriteString(val.PubKey) + sink.WriteVarBytes(val.Sig) + } +} + +func (self *OfflineWitnessMsg) Deserialization(source *common.ZeroCopySource) (err error) { + self.Timestamp, err = source.ReadUint32() + if err != nil { + return err + } + self.View, err = source.ReadUint32() + if err != nil { + return err + } + lenPubKeys, err := source.ReadUint32() + if err != nil { + return err + } + if lenPubKeys > math.MaxUint8 { + return errors.New("too many node keys") + } + for i := uint32(0); i < lenPubKeys; i++ { + key, err := source.ReadString() + if err != nil { + return err + } + self.NodePubKeys = append(self.NodePubKeys, key) + } + + self.Proposer, err = source.ReadString() + if err != nil { + return err + } + + lenVoters, err := source.ReadUint32() + if err != nil { + return err + } + + for i := uint32(0); i < lenVoters; i++ { + index, err := source.ReadVarBytes() + if err != nil { + return err + } + for _, idx := range index { + if int(idx) >= len(self.NodePubKeys) { + return errors.New("vote index out of range") + } + } + pubKey, err := source.ReadString() + if err != nil { + return err + } + sig, err := source.ReadVarBytes() + if err != nil { + return err + } + + self.Voters = append(self.Voters, VoterMsg{OfflineIndex: index, PubKey: pubKey, Sig: sig}) + } + + return self.VerifySigs() +} + +func (self *OfflineWitnessMsg) serializeUnsigned(sink *common.ZeroCopySink) { + sink.WriteUint32(self.Timestamp) + sink.WriteUint32(self.View) + sink.WriteUint32(uint32(len(self.NodePubKeys))) + for _, key := range self.NodePubKeys { + sink.WriteString(key) + } + sink.WriteString(self.Proposer) +} + +func (self *OfflineWitnessMsg) Hash() common.Uint256 { + sink := common.NewZeroCopySink(nil) + self.serializeUnsigned(sink) + hash := common.Uint256(sha256.Sum256(sink.Bytes())) + + return hash +} + +func (self *OfflineWitnessMsg) AddProposeSig(acct *account.Account) error { + hash := self.Hash() + sig, err := signature.Sign(acct, hash[:]) + if err != nil { + return err + } + self.ProposerSig = sig + + return nil +} + +func (self *OfflineWitnessMsg) VoteFor(acct *account.Account, index []uint8) error { + sink := common.NewZeroCopySink(nil) + self.serializeUnsigned(sink) + sink.WriteVarBytes(index) + hash := common.Uint256(sha256.Sum256(sink.Bytes())) + sig, err := signature.Sign(acct, hash[:]) + if err != nil { + return err + } + pubkey := vconfig.PubkeyID(acct.PublicKey) + self.Voters = append(self.Voters, VoterMsg{OfflineIndex: index, PubKey: pubkey, Sig: sig}) + + return nil +} + +func (self *OfflineWitnessMsg) VerifySigs() error { + sink := common.NewZeroCopySink(nil) + self.serializeUnsigned(sink) + unsign := sink.Bytes() + data := sha256.Sum256(unsign) + prop, err := vconfig.Pubkey(self.Proposer) + if err != nil { + return err + } + + err = signature.Verify(prop, data[:], self.ProposerSig) + if err != nil { + return err + } + + for _, vote := range self.Voters { + sink = common.NewZeroCopySink(unsign) + sink.WriteVarBytes(vote.OfflineIndex) + data = sha256.Sum256(sink.Bytes()) + key, err := vconfig.Pubkey(vote.PubKey) + if err != nil { + return err + } + err = signature.Verify(key, data[:], vote.Sig) + if err != nil { + return err + } + } + + return nil +} diff --git a/p2pserver/mock/subnet_test.go b/p2pserver/mock/subnet_test.go index 2c1b03aa3b..97ac7ca48c 100644 --- a/p2pserver/mock/subnet_test.go +++ b/p2pserver/mock/subnet_test.go @@ -65,7 +65,7 @@ func TestSubnetAllGovAreSeed(t *testing.T) { net := NewNetwork() var nodes []*netserver.NetServer for i := 0; i < SG; i++ { - seedNode := NewSubnetNode(acct[0], seedList[i], seedList, gov, net, nil, "seedgov") + seedNode := NewSubnetNode(acct[i], seedList[i], seedList, gov, net, nil, "seedgov") go seedNode.Start() nodes = append(nodes, seedNode) } @@ -85,7 +85,7 @@ func TestSubnetAllGovAreSeed(t *testing.T) { //need some time for seed node detected it's identity time.Sleep(time.Second * 20) for i := 0; i < SG; i++ { - assert.Equal(t, len(getSubnetMemberInfo(nodes[i].Protocol())), SG, i) + assert.Equal(t, SG, len(getSubnetMemberInfo(nodes[i].Protocol())), i) } for i := 0; i < T; i++ { assert.Equal(t, uint32(T)-1, nodes[i].GetConnectionCnt(), i) @@ -123,7 +123,7 @@ func TestSubnet(t *testing.T) { net := NewNetwork() var nodes []*netserver.NetServer for i := 0; i < S; i++ { - seedNode := NewSubnetNode(acct[0], seedList[i], seedList, gov, net, nil, "seed") + seedNode := NewSubnetNode(acct[i], seedList[i], seedList, gov, net, nil, "seed") go seedNode.Start() nodes = append(nodes, seedNode) } diff --git a/p2pserver/net/netserver/nbr_peers.go b/p2pserver/net/netserver/nbr_peers.go index cb09bde876..a4250bfe8e 100644 --- a/p2pserver/net/netserver/nbr_peers.go +++ b/p2pserver/net/netserver/nbr_peers.go @@ -92,7 +92,7 @@ func (this *NbrPeers) Broadcast(msg types.Message) { defer this.RUnlock() for _, node := range this.List { if node.Peer.GetRelay() { - go node.Peer.SendRaw(msg.CmdType(), sink.Bytes()) + go node.Peer.SendRaw(sink.Bytes()) } } } diff --git a/p2pserver/peer/peer.go b/p2pserver/peer/peer.go index 260952eaf2..6b42b53969 100644 --- a/p2pserver/peer/peer.go +++ b/p2pserver/peer/peer.go @@ -140,7 +140,7 @@ func (this *Peer) GetPort() uint16 { } //SendTo call sync link to send buffer -func (this *Peer) SendRaw(msgType string, msgPayload []byte) error { +func (this *Peer) SendRaw(msgPayload []byte) error { return this.Link.SendRaw(msgPayload) } @@ -208,7 +208,7 @@ func (this *Peer) Send(msg types.Message) error { sink := comm.NewZeroCopySink(nil) types.WriteMessage(sink, msg) - return this.SendRaw(msg.CmdType(), sink.Bytes()) + return this.SendRaw(sink.Bytes()) } //GetHttpInfoPort return peer`s httpinfo port diff --git a/p2pserver/protocols/msg_handler.go b/p2pserver/protocols/msg_handler.go index 6033854762..f1b5d111c7 100644 --- a/p2pserver/protocols/msg_handler.go +++ b/p2pserver/protocols/msg_handler.go @@ -103,6 +103,8 @@ func (self *MsgHandler) start(net p2p.P2P) { go self.heatBeat.Start() go self.bootstrap.Start() go self.subnet.Start(net) + + RegisterProposeOfflineVote(self.subnet) } func (self *MsgHandler) stop() { @@ -173,6 +175,8 @@ func (self *MsgHandler) HandlePeerMessage(ctx *p2p.Context, msg msgTypes.Message self.subnet.OnMembersRequest(ctx, m) case *msgTypes.SubnetMembers: self.subnet.OnMembersResponse(ctx, m) + case *msgTypes.OfflineWitnessMsg: + self.subnet.OnOfflineWitnessMsg(ctx, m) case *msgTypes.NotFound: log.Debug("[p2p]receive notFound message, hash is ", m.Hash) default: diff --git a/p2pserver/protocols/rpcapi.go b/p2pserver/protocols/rpcapi.go new file mode 100644 index 0000000000..8faddf57ff --- /dev/null +++ b/p2pserver/protocols/rpcapi.go @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package protocols + +import ( + "github.com/ontio/ontology/http/base/error" + "github.com/ontio/ontology/http/base/rpc" + "github.com/ontio/ontology/p2pserver/protocols/subnet" +) + +func RegisterProposeOfflineVote(subnet *subnet.SubNet) { + // curl http://localhost:20337/local -v -d '{"method":"proposeOfflineVote", "params":["pubkey1", "pubkey2"]}' + rpc.HandleFunc("proposeOfflineVote", func(params []interface{}) map[string]interface{} { + var nodes []string + for _, key := range params { + switch pubKey := key.(type) { + case string: + nodes = append(nodes, pubKey) + default: + return rpc.ResponsePack(error.INVALID_PARAMS, "") + } + } + + err := subnet.ProposeOffline(nodes) + if err != nil { + return rpc.ResponsePack(error.INTERNAL_ERROR, err.Error()) + } + + return rpc.ResponseSuccess(nil) + }) + + // curl http://localhost:20337/local -v -d '{"method":"getOfflineVotes", "params":[]}' + rpc.HandleFunc("getOfflineVotes", func(params []interface{}) map[string]interface{} { + votes := subnet.GetOfflineVotes() + + return rpc.ResponseSuccess(votes) + }) +} diff --git a/p2pserver/protocols/subnet/offline_witness.go b/p2pserver/protocols/subnet/offline_witness.go new file mode 100644 index 0000000000..e9e9951151 --- /dev/null +++ b/p2pserver/protocols/subnet/offline_witness.go @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package subnet + +import ( + "errors" + "math/rand" + "time" + + common2 "github.com/ontio/ontology/common" + "github.com/ontio/ontology/common/log" + vconfig "github.com/ontio/ontology/consensus/vbft/config" + "github.com/ontio/ontology/p2pserver/common" + "github.com/ontio/ontology/p2pserver/message/types" + p2p "github.com/ontio/ontology/p2pserver/net/protocol" + "github.com/ontio/ontology/p2pserver/protocols/utils" +) + +const MinProposeDuration = uint32(1 * time.Hour / time.Second) +const ExpireOfflineMsgTime = uint32(2 * time.Hour / time.Second) +const DelayUpdateMsgTime = 5 * time.Second + +func (self *SubNet) ProposeOffline(nodes []string) error { + if self.acct == nil { + return errors.New("only consensus node can propose offline witness") + } + key := vconfig.PubkeyID(self.acct.PublicKey) + role, view := self.gov.GetNodeRoleAndView(key) + if role != utils.ConsensusNode { + return errors.New("only consensus node can propose offline witness") + } + now := uint32(time.Now().Unix()) + connected := make(map[string]bool) + for _, val := range self.GetMembersInfo() { + if val.Connected { + connected[val.PubKey] = true + } + } + var leftNodes []string + for _, node := range nodes { + if !self.gov.IsGovNode(node) { + continue + } + if !connected[node] { + leftNodes = append(leftNodes, node) + } + } + + if len(leftNodes) == 0 { + log.Info("do not send offline witness proposal since all nodes are online") + return nil + } + msg := &types.OfflineWitnessMsg{ + Timestamp: now, + View: view, + NodePubKeys: leftNodes, + Proposer: key, + } + err := msg.AddProposeSig(self.acct) + if err != nil { + return err + } + err = self.addProposol(msg) + if err != nil { + return err + } + + self.unparker.Unpark() + return nil +} + +func (self *SubNet) sendOfflineWitness(net p2p.P2P) { + var msgs []struct { + status WitnessStatus + rawMsg []byte + } + var peerIds []common.PeerId + now := uint32(time.Now().Unix()) + self.lock.RLock() + for hash, m := range self.offlineWitness { + if m.Msg.Timestamp+ExpireOfflineMsgTime < now { + delete(self.offlineWitness, hash) + } + if m.Status != UnchangedStatus { + rawMsg := common2.SerializeToBytes(m.Msg) + msgs = append(msgs, struct { + status WitnessStatus + rawMsg []byte + }{status: UnchangedStatus, rawMsg: rawMsg}) + } + } + for _, p := range self.connected { + peerIds = append(peerIds, p.Id) + } + self.lock.RUnlock() + + for _, msg := range msgs { + switch msg.status { + case NewStatus, UpdatedStatus: + for _, peerId := range peerIds { + if p := net.GetPeer(peerId); p != nil { + _ = p.SendRaw(msg.rawMsg) + } + } + } + } +} + +func (self *SubNet) Broadcast(net p2p.P2P, msg types.Message) { + self.lock.RLock() + defer self.lock.RUnlock() + for _, p := range self.connected { + net.SendTo(p.Id, msg) + } +} + +func (self *SubNet) OnOfflineWitnessMsg(ctx *p2p.Context, msg *types.OfflineWitnessMsg) { + status := self.processOfflineWitnessMsg(ctx, msg) + switch status { + case NewStatus: + self.unparker.Unpark() + case UpdatedStatus: + delay := int64(rand.Intn(1000)) * int64(DelayUpdateMsgTime) / 1000 + time.Sleep(time.Duration(delay)) + self.unparker.Unpark() + } +} + +func (self *SubNet) processOfflineWitnessMsg(ctx *p2p.Context, msg *types.OfflineWitnessMsg) WitnessStatus { + now := uint32(time.Now().Unix()) + hash := msg.Hash() + if msg.Timestamp+ExpireOfflineMsgTime < now { + self.logger.Infof("receive expired witness msg: %s", hash.ToHexString()) + return UnchangedStatus + } + role, view := self.gov.GetNodeRoleAndView(msg.Proposer) + if role != utils.ConsensusNode || view != msg.View { + self.logger.Infof("receive expired witness msg: %s, {role: %d, view: %d}, current view: %d", + hash.ToHexString(), role, msg.View, view) + return UnchangedStatus + } + + voters := make(map[string]types.VoterMsg) + for _, voter := range msg.Voters { + if !self.gov.IsGovNode(voter.PubKey) { + self.logger.Infof("receive witness msg: %s with wrong voter: %s", hash.ToHexString(), voter.PubKey) + return UnchangedStatus + } + voters[voter.PubKey] = voter + } + + self.lock.Lock() + defer self.lock.Unlock() + offline := self.offlineWitness[msg.Hash()] + if offline == nil { + govNode := self.acct != nil && self.gov.IsGovNodePubKey(self.acct.PublicKey) + if govNode { + err := msg.VoteFor(self.acct, self.collectOfflineIndexLocked(msg.NodePubKeys)) + if err != nil { + self.logger.Infof("vote for witness msg error: %s", err) + return UnchangedStatus + } + } + offline = &Offline{Status: NewStatus, Msg: msg} + self.offlineWitness[msg.Hash()] = offline + + return NewStatus + } + for _, vote := range offline.Msg.Voters { + delete(voters, vote.PubKey) + } + for _, voter := range voters { + offline.Msg.Voters = append(offline.Msg.Voters, voter) + offline.Status = UpdatedStatus + } + if len(voters) > 0 { + return UpdatedStatus + } + + return UnchangedStatus +} + +func (self *SubNet) collectOfflineIndexLocked(nodes []string) []uint8 { + connected := make(map[string]bool) + for _, val := range self.cleanAndGetMembersInfoLocked() { + if val.Connected { + connected[val.PubKey] = true + } + } + var leftNodes []uint8 + for idx, node := range nodes { + if !connected[node] { + leftNodes = append(leftNodes, uint8(idx)) + } + } + + return leftNodes +} + +func (self *SubNet) addProposol(msg *types.OfflineWitnessMsg) error { + self.lock.Lock() + defer self.lock.Unlock() + for _, m := range self.offlineWitness { + propose := m.Msg + if propose.Proposer == msg.Proposer && (msg.Timestamp < propose.Timestamp+MinProposeDuration) { + return errors.New("have already propose offline witness recently") + } + } + + self.offlineWitness[msg.Hash()] = &Offline{Status: NewStatus, Msg: msg} + return nil +} + +func (self *SubNet) GetOfflineVotes() []*types.OfflineWitnessMsg { + self.lock.RLock() + defer self.lock.RUnlock() + + var voters []*types.OfflineWitnessMsg + for _, m := range self.offlineWitness { + msg := *m.Msg + voters = append(voters, &msg) + } + + return voters +} diff --git a/p2pserver/protocols/subnet/subnet.go b/p2pserver/protocols/subnet/subnet.go index 86a65457b2..5dcb32a86d 100644 --- a/p2pserver/protocols/subnet/subnet.go +++ b/p2pserver/protocols/subnet/subnet.go @@ -26,6 +26,7 @@ import ( "time" "github.com/ontio/ontology/account" + common2 "github.com/ontio/ontology/common" vconfig "github.com/ontio/ontology/consensus/vbft/config" "github.com/ontio/ontology/p2pserver/common" "github.com/ontio/ontology/p2pserver/message/types" @@ -39,6 +40,17 @@ const MaxInactiveTime = 10 * time.Minute var RefreshDuration = 1 * time.Minute +type WitnessStatus = byte + +const NewStatus WitnessStatus = 0 +const UpdatedStatus WitnessStatus = 1 +const UnchangedStatus WitnessStatus = 2 + +type Offline struct { + Status WitnessStatus + Msg *types.OfflineWitnessMsg +} + type SubNet struct { acct *account.Account // nil if conenesus is not enabled seeds *utils.HostsResolver @@ -50,9 +62,10 @@ type SubNet struct { seedNode uint32 // bool acturally closed bool - connected map[string]*peer.PeerInfo // connected seed or gov node, listen address --> PeerInfo - members map[string]*MemberStatus // gov node info, listen address --> pubkey hex string - logger common.Logger + connected map[string]*peer.PeerInfo // connected seed/gov node, listenAddr --> PeerInfo + members map[string]*MemberStatus // gov node info, listenAddr --> pubkey hex string + offlineWitness map[common2.Uint256]*Offline // hash -> msg + logger common.Logger } func NewSubNet(acc *account.Account, seeds *utils.HostsResolver, @@ -64,8 +77,9 @@ func NewSubNet(acc *account.Account, seeds *utils.HostsResolver, unparker: utils.NewParker(), logger: logger, - connected: make(map[string]*peer.PeerInfo), - members: make(map[string]*MemberStatus), + connected: make(map[string]*peer.PeerInfo), + members: make(map[string]*MemberStatus), + offlineWitness: make(map[common2.Uint256]*Offline), } } @@ -187,10 +201,11 @@ func (self *SubNet) OnMembersRequest(ctx *p2p.Context, msg *types.SubnetMembersR } self.lock.Lock() - members := make([]types.MemberInfo, 0, len(self.members)) + memberInfos := self.cleanAndGetMembersInfoLocked() + members := make([]types.MemberInfo, 0, len(memberInfos)) - for addr, status := range self.members { - members = append(members, types.MemberInfo{PubKey: status.PubKey, Addr: addr}) + for _, info := range memberInfos { + members = append(members, types.MemberInfo{PubKey: info.PubKey, Addr: info.ListenAddr}) } //update self.members @@ -356,10 +371,17 @@ func (self *SubNet) maintainLoop(net p2p.P2P) { self.cleanInactiveGovNode() if seedOrGov { + self.sendOfflineWitness(net) + self.sendMembersRequestToRandNodes(net) members := self.GetMembersInfo() buf, _ := json.Marshal(members) self.logger.Infof("[subnet] current members: %s", string(buf)) + votes := self.GetOfflineVotes() + if len(votes) != 0 { + buf, _ = json.Marshal(votes) + self.logger.Infof("[subnet] current offline votes: %s", string(buf)) + } } parker.ParkTimeout(RefreshDuration) @@ -382,12 +404,10 @@ func (self *SubNet) GetMaskAddrFilter() p2p.AddressFilter { } } -//restful api -func (self *SubNet) GetMembersInfo() []common.SubnetMemberInfo { - self.lock.RLock() - defer self.lock.RUnlock() - - var members []common.SubnetMemberInfo +// some gov node may change its listen ip address, +// this function will try to remove old address +func (self *SubNet) cleanAndGetMembersInfoLocked() map[string]common.SubnetMemberInfo { + members := make(map[string]common.SubnetMemberInfo) for addr, mem := range self.members { connected := self.selfAddr == addr height := uint64(0) @@ -397,14 +417,43 @@ func (self *SubNet) GetMembersInfo() []common.SubnetMemberInfo { height = p.Height() version = p.SoftVersion } - members = append(members, common.SubnetMemberInfo{ + + curr := common.SubnetMemberInfo{ PubKey: mem.PubKey, ListenAddr: addr, Connected: connected, Height: height, Version: version, - }) + } + + prev, ok := members[mem.PubKey] + if !ok { + members[mem.PubKey] = curr + } else { // already has one item + if connected && !prev.Connected { // delete prev if curr is connected, but prev is not + delete(self.members, prev.ListenAddr) + members[mem.PubKey] = curr + } else if prev.Connected && !connected { // delete curr if prev is connected, but curr is not + delete(self.members, addr) + } + + // keep both if both not connected, (both connected is not possible because of p2p handshake) + } } return members } + +//restful api +func (self *SubNet) GetMembersInfo() []common.SubnetMemberInfo { + self.lock.Lock() + members := self.cleanAndGetMembersInfoLocked() + self.lock.Unlock() + + result := make([]common.SubnetMemberInfo, 0, len(members)) + for _, info := range members { + result = append(result, info) + } + + return result +} diff --git a/p2pserver/protocols/utils/govnode_resolver.go b/p2pserver/protocols/utils/govnode_resolver.go index dc20ffb5aa..1d7da29cf9 100644 --- a/p2pserver/protocols/utils/govnode_resolver.go +++ b/p2pserver/protocols/utils/govnode_resolver.go @@ -37,9 +37,18 @@ import ( const GovNodeCacheTime = time.Minute * 10 +type NodeRole byte + +const ( + SyncNode NodeRole = iota + CandidateNode = iota + ConsensusNode = iota +) + type GovNodeResolver interface { IsGovNodePubKey(key keypair.PublicKey) bool IsGovNode(key string) bool + GetNodeRoleAndView(key string) (NodeRole, uint32) } type GovNodeMockResolver struct { @@ -61,6 +70,15 @@ func (self *GovNodeMockResolver) IsGovNode(key string) bool { return ok } +func (self *GovNodeMockResolver) GetNodeRoleAndView(key string) (NodeRole, uint32) { + _, ok := self.govNode[key] + if ok { + return CandidateNode, 0 + } + + return SyncNode, 0 +} + func (self *GovNodeMockResolver) IsGovNodePubKey(key keypair.PublicKey) bool { pubKey := vconfig.PubkeyID(key) _, ok := self.govNode[pubKey] @@ -78,13 +96,13 @@ type GovCache struct { view uint32 refreshTime time.Time govNodeNum uint32 - pubkeys map[string]struct{} + pubkeys map[string]bool } func NewGovNodeResolver(db *ledger.Ledger) *GovNodeLedgerResolver { return &GovNodeLedgerResolver{ db: db, - cache: unsafe.Pointer(&GovCache{pubkeys: make(map[string]struct{})}), + cache: unsafe.Pointer(&GovCache{pubkeys: make(map[string]bool)}), } } @@ -94,29 +112,46 @@ func (self *GovNodeLedgerResolver) IsGovNodePubKey(key keypair.PublicKey) bool { } func (self *GovNodeLedgerResolver) IsGovNode(pubKey string) bool { + role, _ := self.GetNodeRoleAndView(pubKey) + + return role != SyncNode +} + +func (self *GovNodeLedgerResolver) GetNodeRoleAndView(pubKey string) (NodeRole, uint32) { view, err := GetGovernanceView(self.db) if err != nil { log.Warnf("[subnet] gov node resolver failed to load view from ledger, err: %v", err) - return false + return SyncNode, 0 } cached := (*GovCache)(atomic.LoadPointer(&self.cache)) if cached != nil && view.View == cached.view && cached.refreshTime.Add(GovNodeCacheTime).After(time.Now()) { - _, ok := cached.pubkeys[pubKey] - return ok + cons, ok := cached.pubkeys[pubKey] + if !ok { + return SyncNode, 0 + } + if cons { + return ConsensusNode, view.View + } + + return CandidateNode, view.View } - govNode := false + nodeRole := SyncNode peers, count, err := GetPeersConfig(self.db, view.View) if err != nil { log.Warnf("[subnet] gov node resolver failed to load peers from ledger, err: %v", err) - return false + return SyncNode, view.View } - pubkeys := make(map[string]struct{}, len(peers)) + pubkeys := make(map[string]bool, len(peers)) for _, peer := range peers { - pubkeys[peer.PeerPubkey] = struct{}{} + pubkeys[peer.PeerPubkey] = peer.ConsNode if peer.PeerPubkey == pubKey { - govNode = true + if peer.ConsNode { + nodeRole = ConsensusNode + } else { + nodeRole = CandidateNode + } } } @@ -130,7 +165,7 @@ func (self *GovNodeLedgerResolver) IsGovNode(pubKey string) bool { view: view.View, })) - return govNode + return nodeRole, view.View } func GetGovernanceView(backend *ledger.Ledger) (*governance.GovernanceView, error) { @@ -146,7 +181,12 @@ func GetGovernanceView(backend *ledger.Ledger) (*governance.GovernanceView, erro return governanceView, nil } -func GetPeersConfig(backend *ledger.Ledger, view uint32) ([]*config.VBFTPeerStakeInfo, uint32, error) { +type GovNodeInfo struct { + ConsNode bool + *config.VBFTPeerStakeInfo +} + +func GetPeersConfig(backend *ledger.Ledger, view uint32) ([]*GovNodeInfo, uint32, error) { viewBytes := governance.GetUint32Bytes(view) key := append([]byte(governance.PEER_POOL), viewBytes...) data, err := backend.GetStorageItem(utils.GovernanceContractAddress, key) @@ -162,8 +202,9 @@ func GetPeersConfig(backend *ledger.Ledger, view uint32) ([]*config.VBFTPeerStak } govCount := uint32(0) - var peerstakes []*config.VBFTPeerStakeInfo + var peerstakes []*GovNodeInfo for _, id := range peerMap.PeerPoolMap { + isConsensus := id.Status == governance.ConsensusStatus || id.Status == governance.QuitConsensusStatus switch id.Status { case governance.CandidateStatus, governance.ConsensusStatus, governance.QuitConsensusStatus: conf := &config.VBFTPeerStakeInfo{ @@ -171,9 +212,12 @@ func GetPeersConfig(backend *ledger.Ledger, view uint32) ([]*config.VBFTPeerStak PeerPubkey: id.PeerPubkey, InitPos: id.InitPos + id.TotalPos, } - peerstakes = append(peerstakes, conf) + peerstakes = append(peerstakes, &GovNodeInfo{ + ConsNode: isConsensus, + VBFTPeerStakeInfo: conf, + }) } - if id.Status == governance.ConsensusStatus || id.Status == governance.QuitConsensusStatus { + if isConsensus { govCount += 1 } } diff --git a/smartcontract/service/native/governance/method.go b/smartcontract/service/native/governance/method.go index d0a07e140c..aa4f82c56b 100644 --- a/smartcontract/service/native/governance/method.go +++ b/smartcontract/service/native/governance/method.go @@ -375,7 +375,7 @@ func normalQuit(native *native.NativeService, contract common.Address, peerPoolI if err := iter.Error(); err != nil { return err } - if flag == false { + if !flag { authorizeInfo := &AuthorizeInfo{ PeerPubkey: peerPoolItem.PeerPubkey, Address: peerPoolItem.Address, @@ -1416,7 +1416,7 @@ func splitNodeFee(native *native.NativeService, contract common.Address, peerPub } var amount uint64 if native.Height > config.GetNewPeerCostHeight() { - stakeFee := new(big.Int).Sub( + stakeFee := new(big.Int).Div( new(big.Int).Mul(new(big.Int).SetUint64(nodeAmount), new(big.Int).SetUint64(totalPos)), new(big.Int).Add(new(big.Int).SetUint64(initPos), new(big.Int).SetUint64(totalPos))).Uint64() nodeFee := nodeAmount - stakeFee diff --git a/smartcontract/service/native/native_service.go b/smartcontract/service/native/native_service.go index 9b10226c3d..f4a31725de 100644 --- a/smartcontract/service/native/native_service.go +++ b/smartcontract/service/native/native_service.go @@ -29,7 +29,6 @@ import ( "github.com/ontio/ontology/smartcontract/context" "github.com/ontio/ontology/smartcontract/event" "github.com/ontio/ontology/smartcontract/states" - sstates "github.com/ontio/ontology/smartcontract/states" "github.com/ontio/ontology/smartcontract/storage" ) @@ -49,7 +48,7 @@ type NativeService struct { CacheDB *storage.CacheDB ServiceMap map[string]Handler Notifications []*event.NotifyEventInfo - InvokeParam sstates.ContractInvokeParam + InvokeParam states.ContractInvokeParam Input []byte Tx *types.Transaction Height uint32 diff --git a/smartcontract/service/native/ong/ong.go b/smartcontract/service/native/ong/ong.go index 4daef89468..0c8640a993 100644 --- a/smartcontract/service/native/ong/ong.go +++ b/smartcontract/service/native/ong/ong.go @@ -97,7 +97,7 @@ func OngApprove(native *native.NativeService) ([]byte, error) { if state.Value > constants.ONG_TOTAL_SUPPLY { return utils.BYTE_FALSE, fmt.Errorf("approve ong amount:%d over totalSupply:%d", state.Value, constants.ONG_TOTAL_SUPPLY) } - if native.ContextRef.CheckWitness(state.From) == false { + if !native.ContextRef.CheckWitness(state.From) { return utils.BYTE_FALSE, errors.NewErr("authentication failed!") } contract := native.ContextRef.CurrentContext().ContractAddress diff --git a/smartcontract/service/native/ont/ont.go b/smartcontract/service/native/ont/ont.go index 09d93cece5..a1dba581a5 100644 --- a/smartcontract/service/native/ont/ont.go +++ b/smartcontract/service/native/ont/ont.go @@ -183,7 +183,7 @@ func OntApprove(native *native.NativeService) ([]byte, error) { if state.Value > constants.ONT_TOTAL_SUPPLY { return utils.BYTE_FALSE, fmt.Errorf("approve ont amount:%d over totalSupply:%d", state.Value, constants.ONT_TOTAL_SUPPLY) } - if native.ContextRef.CheckWitness(state.From) == false { + if !native.ContextRef.CheckWitness(state.From) { return utils.BYTE_FALSE, errors.NewErr("authentication failed!") } contract := native.ContextRef.CurrentContext().ContractAddress diff --git a/smartcontract/service/native/ontfs/app_sdk.go b/smartcontract/service/native/ontfs/app_sdk.go index cd2398da99..00b6e62d7d 100644 --- a/smartcontract/service/native/ontfs/app_sdk.go +++ b/smartcontract/service/native/ontfs/app_sdk.go @@ -859,7 +859,7 @@ func FsTransferFiles(native *native.NativeService) ([]byte, error) { } for _, fileTransfer := range fileTransferList.FilesTransfer { - if native.ContextRef.CheckWitness(fileTransfer.OriOwner) == false { + if !native.ContextRef.CheckWitness(fileTransfer.OriOwner) { errInfos.AddObjectError(string(fileTransfer.FileHash), "[APP SDK] FsTransferFiles CheckFileOwner failed!") continue } diff --git a/smartcontract/service/native/ontid/event.go b/smartcontract/service/native/ontid/event.go index 2fd2cd2ebc..5bb18ce5c6 100644 --- a/smartcontract/service/native/ontid/event.go +++ b/smartcontract/service/native/ontid/event.go @@ -30,7 +30,6 @@ func newEvent(srvc *native.NativeService, st interface{}) { e.ContractAddress = srvc.ContextRef.CurrentContext().ContractAddress e.States = st srvc.Notifications = append(srvc.Notifications, &e) - return } func triggerRegisterEvent(srvc *native.NativeService, id []byte) { diff --git a/smartcontract/service/native/ontid/init.go b/smartcontract/service/native/ontid/init.go index 135398dd6c..faa8b9c13e 100644 --- a/smartcontract/service/native/ontid/init.go +++ b/smartcontract/service/native/ontid/init.go @@ -83,5 +83,4 @@ func RegisterIDContract(srvc *native.NativeService) { srvc.Register("getServiceJson", GetServiceJson) srvc.Register("getControllerJson", GetControllerJson) srvc.Register("getDocumentJson", GetDocumentJson) - return } diff --git a/smartcontract/service/native/ontid/method.go b/smartcontract/service/native/ontid/method.go index 79379e5add..6371882e1a 100644 --- a/smartcontract/service/native/ontid/method.go +++ b/smartcontract/service/native/ontid/method.go @@ -315,6 +315,9 @@ func removeKey(srvc *native.NativeService) ([]byte, error) { } var auth = false rec, err := getOldRecovery(srvc, key) + if err != nil { + return utils.BYTE_FALSE, err + } if len(rec) > 0 { auth = bytes.Equal(rec, arg2) } diff --git a/smartcontract/service/native/utils/operation.go b/smartcontract/service/native/utils/operation.go index 29418b0f10..08787dccbc 100644 --- a/smartcontract/service/native/utils/operation.go +++ b/smartcontract/service/native/utils/operation.go @@ -45,7 +45,7 @@ func ConcatBytes(args ...[]byte) []byte { } func ValidateOwner(native *native.NativeService, address common.Address) error { - if native.ContextRef.CheckWitness(address) == false { + if !native.ContextRef.CheckWitness(address) { return errors.NewErr("validateOwner, authentication failed!") } return nil diff --git a/smartcontract/service/native/utils/serialization.go b/smartcontract/service/native/utils/serialization.go index 8b5d123a2b..fd265e757c 100644 --- a/smartcontract/service/native/utils/serialization.go +++ b/smartcontract/service/native/utils/serialization.go @@ -45,6 +45,7 @@ func EncodeString(sink *common.ZeroCopySink, str string) (size uint64) { func EncodeBool(sink *common.ZeroCopySink, value bool) { sink.WriteBool(value) } + func DecodeVarUint(source *common.ZeroCopySource) (uint64, error) { value, _, irregular, eof := source.NextVarBytes() if eof { diff --git a/smartcontract/service/neovm/runtime.go b/smartcontract/service/neovm/runtime.go index f340d06815..e9f0dea150 100644 --- a/smartcontract/service/neovm/runtime.go +++ b/smartcontract/service/neovm/runtime.go @@ -155,6 +155,9 @@ func RuntimeNotify(service *NeoVmService, engine *vm.Executor) error { // RuntimeLog push smart contract execute event log to client func RuntimeLog(service *NeoVmService, engine *vm.Executor) error { sitem, err := engine.EvalStack.Peek(0) + if err != nil { + return err + } item, err := engine.EvalStack.PopAsBytes() if err != nil { return err diff --git a/smartcontract/service/neovm/wasmvm.go b/smartcontract/service/neovm/wasmvm.go index e0dbe89f94..ec05d31661 100644 --- a/smartcontract/service/neovm/wasmvm.go +++ b/smartcontract/service/neovm/wasmvm.go @@ -63,7 +63,7 @@ func WASMInvoke(service *NeoVmService, engine *vm.Executor) error { } params, ok := list.([]interface{}) - if ok == false { + if !ok { return fmt.Errorf("wasm invoke error: wrong param type:%s", reflect.TypeOf(list).String()) } diff --git a/smartcontract/service/util/util.go b/smartcontract/service/util/util.go index 30a9726681..149e1b06e3 100644 --- a/smartcontract/service/util/util.go +++ b/smartcontract/service/util/util.go @@ -52,7 +52,7 @@ func GenerateNeoVMParamEvalStack(input []byte) (*neovm.ValueStack, error) { } list, ok := params.([]interface{}) - if ok == false { + if !ok { return nil, errors.New("invoke neovm param is not list type") } @@ -66,7 +66,7 @@ func GenerateNeoVMParamEvalStack(input []byte) (*neovm.ValueStack, error) { func SetNeoServiceParamAndEngine(addr common.Address, engine context.Engine, stack *neovm.ValueStack) error { service, ok := engine.(*neovms.NeoVmService) - if ok == false { + if !ok { return errors.New("engine should be NeoVmService") } diff --git a/smartcontract/service/wasmvm/contract.go b/smartcontract/service/wasmvm/contract.go index b9aa6403fc..b96bf37739 100644 --- a/smartcontract/service/wasmvm/contract.go +++ b/smartcontract/service/wasmvm/contract.go @@ -136,6 +136,9 @@ func ContractCreate(proc *exec.Process, self.Service.CacheDB.PutContract(dep) length, err := proc.WriteAt(contractAddr[:], int64(newAddressPtr)) + if err != nil { + panic(err) + } return uint32(length) } diff --git a/smartcontract/service/wasmvm/utils.go b/smartcontract/service/wasmvm/utils.go index ebc261f70e..3a9558c838 100644 --- a/smartcontract/service/wasmvm/utils.go +++ b/smartcontract/service/wasmvm/utils.go @@ -55,7 +55,7 @@ func checkOntoWasm(m *wasm.Module) error { } entry, ok := m.Export.Entries["invoke"] - if ok == false { + if !ok { return errors.New("[Validate] invoke entry function does not export.") } diff --git a/smartcontract/service/wasmvm/wasm_service.go b/smartcontract/service/wasmvm/wasm_service.go index 6a2e35a5d6..38a64e8c0b 100644 --- a/smartcontract/service/wasmvm/wasm_service.go +++ b/smartcontract/service/wasmvm/wasm_service.go @@ -198,7 +198,7 @@ func invokeInterpreter(this *WasmVmService, contract *states.WasmContractParam, entry, ok := compiled.RawModule.Export.Entries[entryName] - if ok == false { + if !ok { return nil, errors.NewErr("[Call]Method:" + entryName + " does not exist!") } diff --git a/smartcontract/states/contract.go b/smartcontract/states/contract.go index bec34b03f4..e43930538f 100644 --- a/smartcontract/states/contract.go +++ b/smartcontract/states/contract.go @@ -48,9 +48,18 @@ func (this *ContractInvokeParam) Serialization(sink *common.ZeroCopySink) { func (this *ContractInvokeParam) Deserialization(source *common.ZeroCopySource) error { var irregular, eof bool this.Version, eof = source.NextByte() + if eof { + return io.ErrUnexpectedEOF + } this.Address, eof = source.NextAddress() + if eof { + return io.ErrUnexpectedEOF + } var method []byte method, _, irregular, eof = source.NextVarBytes() + if eof { + return io.ErrUnexpectedEOF + } if irregular { return common.ErrIrregularData } diff --git a/smartcontract/states/wasmContract.go b/smartcontract/states/wasmContract.go index 411746dc8a..723133052a 100644 --- a/smartcontract/states/wasmContract.go +++ b/smartcontract/states/wasmContract.go @@ -38,6 +38,9 @@ func (this *WasmContractParam) Serialization(sink *common.ZeroCopySink) { func (this *WasmContractParam) Deserialization(source *common.ZeroCopySource) error { var irregular, eof bool this.Address, eof = source.NextAddress() + if eof { + return io.ErrUnexpectedEOF + } this.Args, _, irregular, eof = source.NextVarBytes() if irregular { diff --git a/txnpool/proc/txnpool_server.go b/txnpool/proc/txnpool_server.go index c40ee6a04b..c293cf6c6b 100644 --- a/txnpool/proc/txnpool_server.go +++ b/txnpool/proc/txnpool_server.go @@ -611,9 +611,8 @@ func (s *TXPoolServer) getStats() []uint64 { s.stats.RLock() defer s.stats.RUnlock() ret := make([]uint64, 0, len(s.stats.count)) - for _, v := range s.stats.count { - ret = append(ret, v) - } + ret = append(ret, s.stats.count...) + return ret } diff --git a/vm/crossvm_codec/notify_codec.go b/vm/crossvm_codec/notify_codec.go index c1bdfd74c4..b9858a9386 100644 --- a/vm/crossvm_codec/notify_codec.go +++ b/vm/crossvm_codec/notify_codec.go @@ -65,7 +65,7 @@ func stringify(notify interface{}) interface{} { // input byte array should be the following format // evt\0(4byte) + type(1byte) + usize( bytearray or list) (4 bytes) + data... func parseNotify(input []byte) (interface{}, error) { - if bytes.HasPrefix(input, []byte("evt\x00")) == false { + if !bytes.HasPrefix(input, []byte("evt\x00")) { return nil, ERROR_PARAM_FORMAT } diff --git a/vm/crossvm_codec/vmcall_codec.go b/vm/crossvm_codec/vmcall_codec.go index 340c73c510..7727b71eec 100644 --- a/vm/crossvm_codec/vmcall_codec.go +++ b/vm/crossvm_codec/vmcall_codec.go @@ -27,7 +27,7 @@ import ( //input byte array should be the following format // version(1byte) + type(1byte) + data... func DeserializeCallParam(input []byte) (interface{}, error) { - if bytes.HasPrefix(input, []byte{0}) == false { + if !bytes.HasPrefix(input, []byte{0}) { return nil, ERROR_PARAM_FORMAT } diff --git a/vm/neovm/executor.go b/vm/neovm/executor.go index 91ac078bae..41eb78356c 100644 --- a/vm/neovm/executor.go +++ b/vm/neovm/executor.go @@ -877,7 +877,7 @@ func (self *Executor) ExecuteOp(opcode OpCode, context *ExecutionContext) (VMSta value, ok, err := mapVal.Get(index) if err != nil { return FAULT, err - } else if ok == false { + } else if !ok { // todo: suply a nil value in vm? return FAULT, errors.ERR_MAP_NOT_EXIST } diff --git a/vm/neovm/types/int_value.go b/vm/neovm/types/int_value.go index 3013fc046b..45e2126c55 100644 --- a/vm/neovm/types/int_value.go +++ b/vm/neovm/types/int_value.go @@ -36,14 +36,14 @@ type IntValue struct { func (self IntValue) Rsh(other IntValue) (result IntValue, err error) { var val uint64 - if other.isbig == false { + if !other.isbig { if other.integer < 0 { err = errors.ERR_SHIFT_BY_NEG return } val = uint64(other.integer) } else { - if other.bigint.IsUint64() == false { + if !other.bigint.IsUint64() { return IntValue{}, errors.ERR_SHIFT_BY_NEG } val = other.bigint.Uint64() @@ -71,14 +71,14 @@ func (self IntValue) Rsh(other IntValue) (result IntValue, err error) { func (self IntValue) Lsh(other IntValue) (result IntValue, err error) { var val uint64 - if other.isbig == false { + if !other.isbig { if other.integer < 0 { err = errors.ERR_SHIFT_BY_NEG return } val = uint64(other.integer) } else { - if other.bigint.IsUint64() == false { + if !other.bigint.IsUint64() { return IntValue{}, errors.ERR_SHIFT_BY_NEG } val = other.bigint.Uint64() @@ -127,7 +127,7 @@ func IntValFromNeoBytes(val []byte) (IntValue, error) { func (self *IntValue) ToNeoBytes() []byte { val := self.bigint - if self.isbig == false { + if !self.isbig { val = big.NewInt(self.integer) } value := common.BigIntToNeoBytes(val) @@ -221,7 +221,7 @@ func (self IntValue) Or(other IntValue) (IntValue, error) { } func (self IntValue) Cmp(other IntValue) int { - if self.isbig == false && other.isbig == false { + if !self.isbig && !other.isbig { if self.integer < other.integer { return -1 } else if self.integer == other.integer { @@ -231,12 +231,12 @@ func (self IntValue) Cmp(other IntValue) int { } } var left, right *big.Int - if self.isbig == false { + if !self.isbig { left = big.NewInt(self.integer) } else { left = self.bigint } - if other.isbig == false { + if !other.isbig { right = big.NewInt(other.integer) } else { right = other.bigint @@ -321,19 +321,19 @@ type overflowFn func(a, b int64) (result int64, ok bool) type bigintFn func(a, b *big.Int) (IntValue, error) func (self IntValue) intOp(other IntValue, littleintFunc overflowFn, bigintFunc bigintFn) (IntValue, error) { - if self.isbig == false && other.isbig == false { + if !self.isbig && !other.isbig { val, ok := littleintFunc(self.integer, other.integer) if ok { return IntValFromInt(val), nil } } var left, right *big.Int - if self.isbig == false { + if !self.isbig { left = big.NewInt(self.integer) } else { left = self.bigint } - if other.isbig == false { + if !other.isbig { right = big.NewInt(other.integer) } else { right = other.bigint diff --git a/vm/neovm/types/neovm_value.go b/vm/neovm/types/neovm_value.go index 3c61d8184d..f63e53defe 100644 --- a/vm/neovm/types/neovm_value.go +++ b/vm/neovm/types/neovm_value.go @@ -556,7 +556,7 @@ func (self *VmValue) AsInt64() (int64, error) { return 0, err } if val.isbig { - if val.bigint.IsInt64() == false { + if !val.bigint.IsInt64() { return 0, errors.ERR_INTEGER_UNDERFLOW } return val.bigint.Int64(), nil