github.com/aergoio/aergo@v1.3.1/rpc/grpcserver.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package rpc 7 8 import ( 9 "bytes" 10 "context" 11 "crypto/sha256" 12 "encoding/binary" 13 "encoding/json" 14 "errors" 15 "reflect" 16 "strings" 17 "sync" 18 "sync/atomic" 19 "time" 20 21 "github.com/aergoio/aergo-actor/actor" 22 "github.com/aergoio/aergo-lib/log" 23 "github.com/aergoio/aergo/chain" 24 "github.com/aergoio/aergo/consensus" 25 "github.com/aergoio/aergo/consensus/impl/raftv2" 26 "github.com/aergoio/aergo/internal/common" 27 "github.com/aergoio/aergo/message" 28 "github.com/aergoio/aergo/p2p/metric" 29 "github.com/aergoio/aergo/p2p/p2pcommon" 30 "github.com/aergoio/aergo/pkg/component" 31 "github.com/aergoio/aergo/types" 32 "github.com/golang/protobuf/ptypes/timestamp" 33 "google.golang.org/grpc/codes" 34 "google.golang.org/grpc/status" 35 ) 36 37 var ( 38 logger = log.NewLogger("rpc") 39 ) 40 41 var ( 42 ErrUninitAccessor = errors.New("accessor is not initilized") 43 ErrNotSupportedConsensus = errors.New("not supported by this consensus") 44 ) 45 46 type EventStream struct { 47 filter *types.FilterInfo 48 stream types.AergoRPCService_ListEventStreamServer 49 } 50 51 // AergoRPCService implements GRPC server which is defined in rpc.proto 52 type AergoRPCService struct { 53 hub *component.ComponentHub 54 actorHelper p2pcommon.ActorService 55 consensusAccessor consensus.ConsensusAccessor //TODO refactor with actorHelper 56 msgHelper message.Helper 57 58 streamID uint32 59 blockStreamLock sync.RWMutex 60 blockStream map[uint32]types.AergoRPCService_ListBlockStreamServer 61 blockMetadataStreamLock sync.RWMutex 62 blockMetadataStream map[uint32]types.AergoRPCService_ListBlockMetadataStreamServer 63 64 eventStreamLock sync.RWMutex 65 eventStream map[*EventStream]*EventStream 66 67 clientAuthLock sync.RWMutex 68 clientAuthOn bool 69 clientAuth map[string]Authentication 70 } 71 72 // FIXME remove redundant constants 73 const halfMinute = time.Second * 30 74 const defaultActorTimeout = time.Second * 3 75 76 var _ types.AergoRPCServiceServer = (*AergoRPCService)(nil) 77 78 func (rpc *AergoRPCService) SetConsensusAccessor(ca consensus.ConsensusAccessor) { 79 if rpc == nil { 80 return 81 } 82 83 rpc.consensusAccessor = ca 84 } 85 86 func (rpc *AergoRPCService) Metric(ctx context.Context, req *types.MetricsRequest) (*types.Metrics, error) { 87 if err := rpc.checkAuth(ctx, ShowNode); err != nil { 88 return nil, err 89 } 90 result := &types.Metrics{} 91 processed := make(map[types.MetricType]interface{}) 92 for _, mt := range req.Types { 93 if _, found := processed[mt]; found { 94 continue 95 } 96 processed[mt] = mt 97 98 switch mt { 99 case types.MetricType_P2P_NETWORK: 100 rpc.fillPeerMetrics(result) 101 default: 102 // TODO log itB 103 } 104 } 105 106 return result, nil 107 } 108 109 func (rpc *AergoRPCService) fillPeerMetrics(result *types.Metrics) { 110 // fill metrics for p2p 111 presult, err := rpc.actorHelper.CallRequestDefaultTimeout(message.P2PSvc, 112 &message.GetMetrics{}) 113 if err != nil { 114 return 115 } 116 metrics := presult.([]*metric.PeerMetric) 117 mets := make([]*types.PeerMetric, len(metrics)) 118 for i, met := range metrics { 119 rMet := &types.PeerMetric{PeerID: []byte(met.PeerID), SumIn: met.TotalIn(), AvrIn: met.InMetric.APS(), 120 SumOut: met.TotalOut(), AvrOut: met.OutMetric.APS()} 121 mets[i] = rMet 122 } 123 124 result.Peers = mets 125 } 126 127 // Blockchain handle rpc request blockchain. It has no additional input parameter 128 func (rpc *AergoRPCService) Blockchain(ctx context.Context, in *types.Empty) (*types.BlockchainStatus, error) { 129 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 130 return nil, err 131 } 132 ca := rpc.actorHelper.GetChainAccessor() 133 last, err := ca.GetBestBlock() 134 if err != nil { 135 return nil, err 136 } 137 138 digest := sha256.New() 139 digest.Write(last.GetHeader().GetChainID()) 140 bestChainIDHash := digest.Sum(nil) 141 142 chainInfo, err := rpc.getChainInfo(ctx) 143 if err != nil { 144 logger.Warn().Err(err).Msg("failed to get chain info in blockchain") 145 chainInfo = nil 146 } 147 return &types.BlockchainStatus{ 148 BestBlockHash: last.BlockHash(), 149 BestHeight: last.GetHeader().GetBlockNo(), 150 ConsensusInfo: ca.GetConsensusInfo(), 151 BestChainIdHash: bestChainIDHash, 152 ChainInfo: chainInfo, 153 }, nil 154 } 155 156 // GetChainInfo handles a getchaininfo RPC request. 157 func (rpc *AergoRPCService) GetChainInfo(ctx context.Context, in *types.Empty) (*types.ChainInfo, error) { 158 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 159 return nil, err 160 } 161 return rpc.getChainInfo(ctx) 162 } 163 164 func (rpc *AergoRPCService) getChainInfo(ctx context.Context) (*types.ChainInfo, error) { 165 chainInfo := &types.ChainInfo{} 166 167 if genesisInfo := rpc.actorHelper.GetChainAccessor().GetGenesisInfo(); genesisInfo != nil { 168 id := genesisInfo.ID 169 170 chainInfo.Id = &types.ChainId{ 171 Magic: id.Magic, 172 Public: id.PublicNet, 173 Mainnet: id.MainNet, 174 Consensus: id.Consensus, 175 } 176 177 if totalBalance := genesisInfo.TotalBalance(); totalBalance != nil { 178 chainInfo.Maxtokens = totalBalance.Bytes() 179 } 180 } 181 182 cInfo, err := rpc.GetConsensusInfo(ctx, &types.Empty{}) 183 if err != nil { 184 return nil, status.Errorf(codes.Internal, err.Error()) 185 } 186 chainInfo.BpNumber = uint32(len(cInfo.GetBps())) 187 188 chainInfo.Maxblocksize = uint64(chain.MaxBlockSize()) 189 190 if consensus.IsDposName(chainInfo.Id.Consensus) { 191 if minStaking := types.GetStakingMinimum(); minStaking != nil { 192 chainInfo.Stakingminimum = minStaking.Bytes() 193 } 194 195 if total, err := rpc.actorHelper.GetChainAccessor().GetSystemValue(types.StakingTotal); total != nil { 196 chainInfo.Totalstaking = total.Bytes() 197 } else { 198 return nil, err 199 } 200 } 201 202 return chainInfo, nil 203 } 204 205 // ListBlockMetadata handle rpc request 206 func (rpc *AergoRPCService) ListBlockMetadata(ctx context.Context, in *types.ListParams) (*types.BlockMetadataList, error) { 207 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 208 return nil, err 209 } 210 blocks, err := rpc.getBlocks(ctx, in) 211 if err != nil { 212 return nil, status.Errorf(codes.Internal, err.Error()) 213 } 214 var metas []*types.BlockMetadata 215 for _, block := range blocks { 216 metas = append(metas, block.GetMetadata()) 217 } 218 return &types.BlockMetadataList{Blocks: metas}, nil 219 } 220 221 // ListBlockHeaders (Deprecated) handle rpc request listblocks 222 func (rpc *AergoRPCService) ListBlockHeaders(ctx context.Context, in *types.ListParams) (*types.BlockHeaderList, error) { 223 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 224 return nil, err 225 } 226 blocks, err := rpc.getBlocks(ctx, in) 227 if err != nil { 228 return nil, err 229 } 230 for _, block := range blocks { 231 block.Body = nil 232 } 233 return &types.BlockHeaderList{Blocks: blocks}, nil 234 } 235 236 func (rpc *AergoRPCService) getBlocks(ctx context.Context, in *types.ListParams) ([]*types.Block, error) { 237 var maxFetchSize uint32 238 // TODO refactor with almost same code is in p2pcmdblock.go 239 if in.Size > uint32(1000) { 240 maxFetchSize = uint32(1000) 241 } else { 242 maxFetchSize = in.Size 243 } 244 idx := uint32(0) 245 hashes := make([][]byte, 0, maxFetchSize) 246 blocks := make([]*types.Block, 0, maxFetchSize) 247 var err error 248 if len(in.Hash) > 0 { 249 hash := in.Hash 250 for idx < maxFetchSize { 251 foundBlock, futureErr := extractBlockFromFuture(rpc.hub.RequestFuture(message.ChainSvc, 252 &message.GetBlock{BlockHash: hash}, defaultActorTimeout, "rpc.(*AergoRPCService).ListBlockHeaders#1")) 253 if nil != futureErr { 254 if idx == 0 { 255 err = futureErr 256 } 257 break 258 } 259 hashes = append(hashes, foundBlock.BlockHash()) 260 blocks = append(blocks, foundBlock) 261 idx++ 262 hash = foundBlock.Header.PrevBlockHash 263 if len(hash) == 0 { 264 break 265 } 266 } 267 if in.Asc || in.Offset != 0 { 268 err = errors.New("Has unsupported param") 269 } 270 } else { 271 end := types.BlockNo(0) 272 start := types.BlockNo(in.Height) - types.BlockNo(in.Offset) 273 if start >= types.BlockNo(maxFetchSize) { 274 end = start - types.BlockNo(maxFetchSize-1) 275 } 276 if in.Asc { 277 for i := end; i <= start; i++ { 278 foundBlock, futureErr := extractBlockFromFuture(rpc.hub.RequestFuture(message.ChainSvc, 279 &message.GetBlockByNo{BlockNo: i}, defaultActorTimeout, "rpc.(*AergoRPCService).ListBlockHeaders#2")) 280 if nil != futureErr { 281 if i == end { 282 err = futureErr 283 } 284 break 285 } 286 hashes = append(hashes, foundBlock.BlockHash()) 287 blocks = append(blocks, foundBlock) 288 idx++ 289 } 290 } else { 291 for i := start; i >= end; i-- { 292 foundBlock, futureErr := extractBlockFromFuture(rpc.hub.RequestFuture(message.ChainSvc, 293 &message.GetBlockByNo{BlockNo: i}, defaultActorTimeout, "rpc.(*AergoRPCService).ListBlockHeaders#2")) 294 if nil != futureErr { 295 if i == start { 296 err = futureErr 297 } 298 break 299 } 300 hashes = append(hashes, foundBlock.BlockHash()) 301 blocks = append(blocks, foundBlock) 302 idx++ 303 } 304 } 305 } 306 return blocks, err 307 } 308 309 func (rpc *AergoRPCService) BroadcastToListBlockStream(block *types.Block) { 310 var err error 311 rpc.blockStreamLock.RLock() 312 for _, stream := range rpc.blockStream { 313 if stream != nil { 314 err = stream.Send(block) 315 if err != nil { 316 logger.Warn().Err(err).Msg("failed to broadcast block stream") 317 } 318 } 319 } 320 rpc.blockStreamLock.RUnlock() 321 } 322 323 func (rpc *AergoRPCService) BroadcastToListBlockMetadataStream(meta *types.BlockMetadata) { 324 var err error 325 rpc.blockMetadataStreamLock.RLock() 326 for _, stream := range rpc.blockMetadataStream { 327 if stream != nil { 328 err = stream.Send(meta) 329 if err != nil { 330 logger.Warn().Err(err).Msg("failed to broadcast block meta stream") 331 } 332 } 333 } 334 rpc.blockMetadataStreamLock.RUnlock() 335 } 336 337 // ListBlockStream starts a stream of new blocks 338 func (rpc *AergoRPCService) ListBlockStream(in *types.Empty, stream types.AergoRPCService_ListBlockStreamServer) error { 339 streamId := atomic.AddUint32(&rpc.streamID, 1) 340 rpc.blockStreamLock.Lock() 341 rpc.blockStream[streamId] = stream 342 rpc.blockStreamLock.Unlock() 343 logger.Info().Uint32("id", streamId).Msg("block stream added") 344 345 for { 346 select { 347 case <-stream.Context().Done(): 348 rpc.blockStreamLock.Lock() 349 delete(rpc.blockStream, streamId) 350 rpc.blockStreamLock.Unlock() 351 logger.Info().Uint32("id", streamId).Msg("block stream deleted") 352 return nil 353 } 354 } 355 } 356 357 // ListBlockMetadataStream starts a stream of new blocks' metadata 358 func (rpc *AergoRPCService) ListBlockMetadataStream(in *types.Empty, stream types.AergoRPCService_ListBlockMetadataStreamServer) error { 359 streamID := atomic.AddUint32(&rpc.streamID, 1) 360 rpc.blockMetadataStreamLock.Lock() 361 rpc.blockMetadataStream[streamID] = stream 362 rpc.blockMetadataStreamLock.Unlock() 363 logger.Info().Uint32("id", streamID).Msg("block meta stream added") 364 365 for { 366 select { 367 case <-stream.Context().Done(): 368 rpc.blockMetadataStreamLock.Lock() 369 delete(rpc.blockMetadataStream, streamID) 370 rpc.blockMetadataStreamLock.Unlock() 371 logger.Info().Uint32("id", streamID).Msg("block meta stream deleted") 372 return nil 373 } 374 } 375 } 376 377 func extractBlockFromFuture(future *actor.Future) (*types.Block, error) { 378 rawResponse, err := future.Result() 379 if err != nil { 380 return nil, err 381 } 382 var blockRsp *message.GetBlockRsp 383 switch v := rawResponse.(type) { 384 case message.GetBlockRsp: 385 blockRsp = &v 386 case message.GetBestBlockRsp: 387 blockRsp = (*message.GetBlockRsp)(&v) 388 case message.GetBlockByNoRsp: 389 blockRsp = (*message.GetBlockRsp)(&v) 390 default: 391 return nil, errors.New("Unsupported message type") 392 } 393 return extractBlock(blockRsp) 394 } 395 396 func extractBlock(from *message.GetBlockRsp) (*types.Block, error) { 397 if nil != from.Err { 398 return nil, from.Err 399 } 400 return from.Block, nil 401 402 } 403 404 // GetBlock handle rpc request getblock 405 func (rpc *AergoRPCService) GetBlock(ctx context.Context, in *types.SingleBytes) (*types.Block, error) { 406 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 407 return nil, err 408 } 409 var result interface{} 410 var err error 411 if cap(in.Value) == 0 { 412 return nil, status.Errorf(codes.InvalidArgument, "Received no bytes") 413 } 414 if len(in.Value) == 32 { 415 result, err = rpc.hub.RequestFuture(message.ChainSvc, &message.GetBlock{BlockHash: in.Value}, 416 defaultActorTimeout, "rpc.(*AergoRPCService).GetBlock#2").Result() 417 } else if len(in.Value) == 8 { 418 number := uint64(binary.LittleEndian.Uint64(in.Value)) 419 result, err = rpc.hub.RequestFuture(message.ChainSvc, &message.GetBlockByNo{BlockNo: number}, 420 defaultActorTimeout, "rpc.(*AergoRPCService).GetBlock#1").Result() 421 } else { 422 return nil, status.Errorf(codes.InvalidArgument, "Invalid input. Should be a 32 byte hash or up to 8 byte number.") 423 } 424 if err != nil { 425 return nil, err 426 } 427 found, err := rpc.msgHelper.ExtractBlockFromResponse(result) 428 if err != nil { 429 return nil, status.Errorf(codes.Internal, err.Error()) 430 } 431 if found == nil { 432 return nil, status.Errorf(codes.NotFound, "Not found") 433 } 434 return found, nil 435 } 436 437 // GetBlockMetadata handle rpc request getblock 438 func (rpc *AergoRPCService) GetBlockMetadata(ctx context.Context, in *types.SingleBytes) (*types.BlockMetadata, error) { 439 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 440 return nil, err 441 } 442 block, err := rpc.GetBlock(ctx, in) 443 if err != nil { 444 return nil, err 445 } 446 meta := block.GetMetadata() 447 return meta, nil 448 } 449 450 // GetBlockBody handle rpc request getblockbody 451 func (rpc *AergoRPCService) GetBlockBody(ctx context.Context, in *types.BlockBodyParams) (*types.BlockBodyPaged, error) { 452 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 453 return nil, err 454 } 455 block, err := rpc.GetBlock(ctx, &types.SingleBytes{Value: in.Hashornumber}) 456 if err != nil { 457 return nil, err 458 } 459 body := block.GetBody() 460 461 total := uint32(len(body.Txs)) 462 463 var fetchSize uint32 464 if in.Paging.Size > uint32(1000) { 465 fetchSize = uint32(1000) 466 } else if in.Paging.Size == uint32(0) { 467 fetchSize = 100 468 } else { 469 fetchSize = in.Paging.Size 470 } 471 472 offset := in.Paging.Offset 473 if offset >= uint32(len(body.Txs)) { 474 body.Txs = []*types.Tx{} 475 } else { 476 limit := offset + fetchSize 477 if limit > uint32(len(body.Txs)) { 478 limit = uint32(len(body.Txs)) 479 } 480 body.Txs = body.Txs[offset:limit] 481 } 482 483 response := &types.BlockBodyPaged{ 484 Body: body, 485 Total: total, 486 Size: fetchSize, 487 Offset: offset, 488 } 489 return response, nil 490 } 491 492 // GetTX handle rpc request gettx 493 func (rpc *AergoRPCService) GetTX(ctx context.Context, in *types.SingleBytes) (*types.Tx, error) { 494 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 495 return nil, err 496 } 497 result, err := rpc.actorHelper.CallRequestDefaultTimeout(message.MemPoolSvc, 498 &message.MemPoolExist{Hash: in.Value}) 499 if err != nil { 500 return nil, err 501 } 502 tx, err := rpc.msgHelper.ExtractTxFromResponse(result) 503 if err != nil { 504 return nil, err 505 } 506 if tx != nil { 507 return tx, nil 508 } 509 // TODO try find tx in blockchain, but chainservice doesn't have method yet. 510 511 return nil, status.Errorf(codes.NotFound, "not found") 512 } 513 514 // GetBlockTX handle rpc request gettx 515 func (rpc *AergoRPCService) GetBlockTX(ctx context.Context, in *types.SingleBytes) (*types.TxInBlock, error) { 516 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 517 return nil, err 518 } 519 result, err := rpc.hub.RequestFuture(message.ChainSvc, 520 &message.GetTx{TxHash: in.Value}, defaultActorTimeout, "rpc.(*AergoRPCService).GetBlockTX").Result() 521 if err != nil { 522 return nil, err 523 } 524 rsp, ok := result.(message.GetTxRsp) 525 if !ok { 526 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 527 } 528 return &types.TxInBlock{Tx: rsp.Tx, TxIdx: rsp.TxIds}, rsp.Err 529 } 530 531 var emptyBytes = make([]byte, 0) 532 533 // SendTX try to fill the nonce, sign, hash, chainIdHash in the transaction automatically and commit it 534 func (rpc *AergoRPCService) SendTX(ctx context.Context, tx *types.Tx) (*types.CommitResult, error) { 535 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 536 return nil, err 537 } 538 if tx.Body.Nonce == 0 { 539 getStateResult, err := rpc.hub.RequestFuture(message.ChainSvc, 540 &message.GetState{Account: tx.Body.Account}, defaultActorTimeout, "rpc.(*AergoRPCService).SendTx").Result() 541 if err != nil { 542 return nil, err 543 } 544 getStateRsp, ok := getStateResult.(message.GetStateRsp) 545 if !ok { 546 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(getStateResult)) 547 } 548 if getStateRsp.Err != nil { 549 return nil, status.Errorf(codes.Internal, "internal error : %s", getStateRsp.Err.Error()) 550 } 551 tx.Body.Nonce = getStateRsp.State.GetNonce() + 1 552 } 553 554 if tx.Body.ChainIdHash == nil { 555 ca := rpc.actorHelper.GetChainAccessor() 556 last, err := ca.GetBestBlock() 557 if err != nil { 558 return nil, err 559 } 560 tx.Body.ChainIdHash = common.Hasher(last.GetHeader().GetChainID()) 561 } 562 563 signTxResult, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 564 &message.SignTx{Tx: tx, Requester: tx.Body.Account}, defaultActorTimeout, "rpc.(*AergoRPCService).SendTX") 565 if err != nil { 566 if err == component.ErrHubUnregistered { 567 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 568 } 569 return nil, status.Errorf(codes.Internal, err.Error()) 570 } 571 572 signTxRsp, ok := signTxResult.(*message.SignTxRsp) 573 if !ok { 574 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(signTxResult)) 575 } 576 if signTxRsp.Err != nil { 577 return nil, signTxRsp.Err 578 } 579 tx = signTxRsp.Tx 580 memPoolPutResult, err := rpc.hub.RequestFuture(message.MemPoolSvc, 581 &message.MemPoolPut{Tx: tx}, 582 defaultActorTimeout, "rpc.(*AergoRPCService).SendTX").Result() 583 memPoolPutRsp, ok := memPoolPutResult.(*message.MemPoolPutRsp) 584 if !ok { 585 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(memPoolPutResult)) 586 } 587 resultErr := memPoolPutRsp.Err 588 if resultErr != nil { 589 return &types.CommitResult{Hash: tx.Hash, Error: convertError(resultErr), Detail: resultErr.Error()}, err 590 } 591 return &types.CommitResult{Hash: tx.Hash, Error: convertError(resultErr)}, err 592 } 593 594 // CommitTX handle rpc request commit 595 func (rpc *AergoRPCService) CommitTX(ctx context.Context, in *types.TxList) (*types.CommitResultList, error) { 596 // TODO: check validity 597 //if bytes.Equal(emptyBytes, in.Hash) { 598 // return nil, status.Errorf(codes.InvalidArgument, "invalid hash") 599 //} 600 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 601 return nil, err 602 } 603 if in.Txs == nil { 604 return nil, status.Errorf(codes.InvalidArgument, "input tx is empty") 605 } 606 rs := make([]*types.CommitResult, len(in.Txs)) 607 futures := make([]*actor.Future, len(in.Txs)) 608 results := &types.CommitResultList{Results: rs} 609 //results := &types.CommitResultList{} 610 cnt := 0 611 612 for i, tx := range in.Txs { 613 hash := tx.Hash 614 var r types.CommitResult 615 r.Hash = hash 616 617 calculated := tx.CalculateTxHash() 618 619 if !bytes.Equal(hash, calculated) { 620 r.Error = types.CommitStatus_TX_INVALID_HASH 621 } 622 results.Results[i] = &r 623 cnt++ 624 625 //send tx message to mempool 626 f := rpc.hub.RequestFuture(message.MemPoolSvc, 627 &message.MemPoolPut{Tx: tx}, 628 defaultActorTimeout, "rpc.(*AergoRPCService).CommitTX") 629 futures[i] = f 630 } 631 for i, future := range futures { 632 result, err := future.Result() 633 if err != nil { 634 return nil, err 635 } 636 rsp, ok := result.(*message.MemPoolPutRsp) 637 if !ok { 638 err = status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 639 } else { 640 err = rsp.Err 641 } 642 results.Results[i].Error = convertError(err) 643 if err != nil { 644 results.Results[i].Detail = err.Error() 645 } 646 } 647 648 return results, nil 649 } 650 651 // GetState handle rpc request getstate 652 func (rpc *AergoRPCService) GetState(ctx context.Context, in *types.SingleBytes) (*types.State, error) { 653 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 654 return nil, err 655 } 656 result, err := rpc.hub.RequestFuture(message.ChainSvc, 657 &message.GetState{Account: in.Value}, defaultActorTimeout, "rpc.(*AergoRPCService).GetState").Result() 658 if err != nil { 659 return nil, err 660 } 661 rsp, ok := result.(message.GetStateRsp) 662 if !ok { 663 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 664 } 665 return rsp.State, rsp.Err 666 } 667 668 // GetStateAndProof handle rpc request getstateproof 669 func (rpc *AergoRPCService) GetStateAndProof(ctx context.Context, in *types.AccountAndRoot) (*types.AccountProof, error) { 670 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 671 return nil, err 672 } 673 result, err := rpc.hub.RequestFuture(message.ChainSvc, 674 &message.GetStateAndProof{Account: in.Account, Root: in.Root, Compressed: in.Compressed}, defaultActorTimeout, "rpc.(*AergoRPCService).GetStateAndProof").Result() 675 if err != nil { 676 return nil, err 677 } 678 rsp, ok := result.(message.GetStateAndProofRsp) 679 if !ok { 680 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 681 } 682 return rsp.StateProof, rsp.Err 683 } 684 685 // CreateAccount handle rpc request newaccount 686 func (rpc *AergoRPCService) CreateAccount(ctx context.Context, in *types.Personal) (*types.Account, error) { 687 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 688 return nil, err 689 } 690 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 691 &message.CreateAccount{Passphrase: in.Passphrase}, defaultActorTimeout, "rpc.(*AergoRPCService).CreateAccount") 692 if err != nil { 693 if err == component.ErrHubUnregistered { 694 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 695 } 696 return nil, status.Errorf(codes.Internal, err.Error()) 697 } 698 /* 699 //same code but not good at folding in editor 700 switch err { 701 case nil: 702 case component.ErrHubUnregistered: 703 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 704 default: 705 return nil, status.Errorf(codes.Internal, err.Error()) 706 } 707 */ 708 709 rsp, ok := result.(*message.CreateAccountRsp) 710 if !ok { 711 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 712 } 713 return rsp.Account, nil 714 /* 715 //it's better? 716 switch rsp := result.(type) { 717 case *message.CreateAccountRsp: 718 return rsp.Accounts, nil 719 default: 720 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 721 } 722 */ 723 } 724 725 // GetAccounts handle rpc request getaccounts 726 func (rpc *AergoRPCService) GetAccounts(ctx context.Context, in *types.Empty) (*types.AccountList, error) { 727 if err := rpc.checkAuth(ctx, ShowNode); err != nil { 728 return nil, err 729 } 730 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 731 &message.GetAccounts{}, defaultActorTimeout, "rpc.(*AergoRPCService).GetAccounts") 732 if err != nil { 733 if err == component.ErrHubUnregistered { 734 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 735 } 736 return nil, status.Errorf(codes.Internal, err.Error()) 737 } 738 739 rsp, ok := result.(*message.GetAccountsRsp) 740 if !ok { 741 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 742 } 743 return rsp.Accounts, nil 744 } 745 746 // LockAccount handle rpc request lockaccount 747 func (rpc *AergoRPCService) LockAccount(ctx context.Context, in *types.Personal) (*types.Account, error) { 748 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 749 return nil, err 750 } 751 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 752 &message.LockAccount{Account: in.Account, Passphrase: in.Passphrase}, 753 defaultActorTimeout, "rpc.(*AergoRPCService).LockAccount") 754 if err != nil { 755 if err == component.ErrHubUnregistered { 756 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 757 } 758 return nil, status.Errorf(codes.Internal, err.Error()) 759 } 760 761 rsp, ok := result.(*message.AccountRsp) 762 if !ok { 763 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 764 } 765 return rsp.Account, rsp.Err 766 } 767 768 // UnlockAccount handle rpc request unlockaccount 769 func (rpc *AergoRPCService) UnlockAccount(ctx context.Context, in *types.Personal) (*types.Account, error) { 770 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 771 return nil, err 772 } 773 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 774 &message.UnlockAccount{Account: in.Account, Passphrase: in.Passphrase}, 775 defaultActorTimeout, "rpc.(*AergoRPCService).UnlockAccount") 776 if err != nil { 777 if err == component.ErrHubUnregistered { 778 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 779 } 780 return nil, status.Errorf(codes.Internal, err.Error()) 781 } 782 783 rsp, ok := result.(*message.AccountRsp) 784 if !ok { 785 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 786 } 787 return rsp.Account, rsp.Err 788 } 789 790 func (rpc *AergoRPCService) ImportAccount(ctx context.Context, in *types.ImportFormat) (*types.Account, error) { 791 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 792 return nil, err 793 } 794 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 795 &message.ImportAccount{Wif: in.Wif.Value, OldPass: in.Oldpass, NewPass: in.Newpass}, 796 defaultActorTimeout, "rpc.(*AergoRPCService).ImportAccount") 797 if err != nil { 798 if err == component.ErrHubUnregistered { 799 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 800 } 801 return nil, status.Errorf(codes.Internal, err.Error()) 802 } 803 804 rsp, ok := result.(*message.ImportAccountRsp) 805 if !ok { 806 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 807 } 808 return rsp.Account, rsp.Err 809 } 810 811 func (rpc *AergoRPCService) ExportAccount(ctx context.Context, in *types.Personal) (*types.SingleBytes, error) { 812 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 813 return nil, err 814 } 815 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 816 &message.ExportAccount{Account: in.Account, Pass: in.Passphrase}, 817 defaultActorTimeout, "rpc.(*AergoRPCService).ExportAccount") 818 if err != nil { 819 if err == component.ErrHubUnregistered { 820 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 821 } 822 return nil, status.Errorf(codes.Internal, err.Error()) 823 } 824 825 rsp, ok := result.(*message.ExportAccountRsp) 826 if !ok { 827 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 828 } 829 return &types.SingleBytes{Value: rsp.Wif}, rsp.Err 830 } 831 832 // SignTX handle rpc request signtx 833 func (rpc *AergoRPCService) SignTX(ctx context.Context, in *types.Tx) (*types.Tx, error) { 834 if err := rpc.checkAuth(ctx, WriteBlockChain); err != nil { 835 return nil, err 836 } 837 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 838 &message.SignTx{Tx: in}, defaultActorTimeout, "rpc.(*AergoRPCService).SignTX") 839 if err != nil { 840 if err == component.ErrHubUnregistered { 841 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 842 } 843 return nil, status.Errorf(codes.Internal, err.Error()) 844 } 845 846 rsp, ok := result.(*message.SignTxRsp) 847 if !ok { 848 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 849 } 850 return rsp.Tx, rsp.Err 851 } 852 853 // VerifyTX handle rpc request verifytx 854 func (rpc *AergoRPCService) VerifyTX(ctx context.Context, in *types.Tx) (*types.VerifyResult, error) { 855 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 856 return nil, err 857 } 858 //TODO : verify without account service 859 result, err := rpc.hub.RequestFutureResult(message.AccountsSvc, 860 &message.VerifyTx{Tx: in}, defaultActorTimeout, "rpc.(*AergoRPCService).VerifyTX") 861 if err != nil { 862 if err == component.ErrHubUnregistered { 863 return nil, status.Errorf(codes.Unavailable, "Unavailable personal feature") 864 } 865 return nil, status.Errorf(codes.Internal, err.Error()) 866 } 867 868 rsp, ok := result.(*message.VerifyTxRsp) 869 if !ok { 870 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 871 } 872 ret := &types.VerifyResult{Tx: rsp.Tx} 873 if rsp.Err == types.ErrSignNotMatch { 874 ret.Error = types.VerifyStatus_VERIFY_STATUS_SIGN_NOT_MATCH 875 } else { 876 ret.Error = types.VerifyStatus_VERIFY_STATUS_OK 877 } 878 return ret, nil 879 } 880 881 // GetPeers handle rpc request getpeers 882 func (rpc *AergoRPCService) GetPeers(ctx context.Context, in *types.PeersParams) (*types.PeerList, error) { 883 if err := rpc.checkAuth(ctx, ShowNode); err != nil { 884 return nil, err 885 } 886 result, err := rpc.hub.RequestFuture(message.P2PSvc, 887 &message.GetPeers{in.NoHidden, in.ShowSelf}, halfMinute, "rpc.(*AergoRPCService).GetPeers").Result() 888 if err != nil { 889 return nil, err 890 } 891 rsp, ok := result.(*message.GetPeersRsp) 892 if !ok { 893 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 894 } 895 896 ret := &types.PeerList{Peers: make([]*types.Peer, 0, len(rsp.Peers))} 897 for _, pi := range rsp.Peers { 898 blkNotice := &types.NewBlockNotice{BlockHash: pi.LastBlockHash, BlockNo: pi.LastBlockNumber} 899 peer := &types.Peer{Address: pi.Addr, State: int32(pi.State), Bestblock: blkNotice, LashCheck: pi.CheckTime.UnixNano(), Hidden: pi.Hidden, Selfpeer: pi.Self, Version: pi.Version} 900 ret.Peers = append(ret.Peers, peer) 901 } 902 903 return ret, nil 904 } 905 906 // NodeState handle rpc request nodestate 907 func (rpc *AergoRPCService) NodeState(ctx context.Context, in *types.NodeReq) (*types.SingleBytes, error) { 908 if err := rpc.checkAuth(ctx, ShowNode); err != nil { 909 return nil, err 910 } 911 timeout := int64(binary.LittleEndian.Uint64(in.Timeout)) 912 component := string(in.Component) 913 914 logger.Debug().Str("comp", component).Int64("timeout", timeout).Msg("nodestate") 915 916 statics, err := rpc.hub.Statistics(time.Duration(timeout)*time.Second, component) 917 if err != nil { 918 return nil, err 919 } 920 921 data, err := json.MarshalIndent(statics, "", "\t") 922 if err != nil { 923 return nil, err 924 } 925 return &types.SingleBytes{Value: data}, nil 926 } 927 928 //GetVotes handle rpc request getvotes 929 func (rpc *AergoRPCService) GetVotes(ctx context.Context, in *types.VoteParams) (*types.VoteList, error) { 930 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 931 return nil, err 932 } 933 934 result, err := rpc.hub.RequestFuture(message.ChainSvc, 935 &message.GetElected{Id: in.GetId(), N: in.GetCount()}, defaultActorTimeout, "rpc.(*AergoRPCService).GetVote").Result() 936 937 if err != nil { 938 return nil, err 939 } 940 rsp, ok := result.(*message.GetVoteRsp) 941 if !ok { 942 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 943 } 944 return rsp.Top, rsp.Err 945 } 946 947 func (rpc *AergoRPCService) GetAccountVotes(ctx context.Context, in *types.AccountAddress) (*types.AccountVoteInfo, error) { 948 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 949 return nil, err 950 } 951 ids := []string{} 952 for _, v := range types.AllVotes { 953 ids = append(ids, v[2:]) 954 } 955 result, err := rpc.hub.RequestFuture(message.ChainSvc, 956 &message.GetVote{Addr: in.Value, Ids: ids}, defaultActorTimeout, "rpc.(*AergoRPCService).GetAccountVote").Result() 957 if err != nil { 958 return nil, err 959 } 960 rsp, ok := result.(*message.GetAccountVoteRsp) 961 if !ok { 962 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 963 } 964 return rsp.Info, rsp.Err 965 } 966 967 //GetStaking handle rpc request getstaking 968 func (rpc *AergoRPCService) GetStaking(ctx context.Context, in *types.AccountAddress) (*types.Staking, error) { 969 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 970 return nil, err 971 } 972 var err error 973 var result interface{} 974 975 if len(in.Value) <= types.AddressLength { 976 result, err = rpc.hub.RequestFuture(message.ChainSvc, 977 &message.GetStaking{Addr: in.Value}, defaultActorTimeout, "rpc.(*AergoRPCService).GetStaking").Result() 978 if err != nil { 979 return nil, err 980 } 981 } else { 982 return nil, status.Errorf(codes.InvalidArgument, "Only support valid address") 983 } 984 rsp, ok := result.(*message.GetStakingRsp) 985 if !ok { 986 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 987 } 988 return rsp.Staking, rsp.Err 989 } 990 991 func (rpc *AergoRPCService) GetNameInfo(ctx context.Context, in *types.Name) (*types.NameInfo, error) { 992 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 993 return nil, err 994 } 995 result, err := rpc.hub.RequestFuture(message.ChainSvc, 996 &message.GetNameInfo{Name: in.Name, BlockNo: in.BlockNo}, defaultActorTimeout, "rpc.(*AergoRPCService).GetName").Result() 997 if err != nil { 998 return nil, err 999 } 1000 rsp, ok := result.(*message.GetNameInfoRsp) 1001 if !ok { 1002 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1003 } 1004 if rsp.Err == types.ErrNameNotFound { 1005 return rsp.Owner, status.Errorf(codes.NotFound, rsp.Err.Error()) 1006 } 1007 return rsp.Owner, rsp.Err 1008 } 1009 1010 func (rpc *AergoRPCService) GetReceipt(ctx context.Context, in *types.SingleBytes) (*types.Receipt, error) { 1011 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1012 return nil, err 1013 } 1014 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1015 &message.GetReceipt{TxHash: in.Value}, defaultActorTimeout, "rpc.(*AergoRPCService).GetReceipt").Result() 1016 if err != nil { 1017 return nil, err 1018 } 1019 rsp, ok := result.(message.GetReceiptRsp) 1020 if !ok { 1021 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1022 } 1023 return rsp.Receipt, rsp.Err 1024 } 1025 1026 func (rpc *AergoRPCService) GetABI(ctx context.Context, in *types.SingleBytes) (*types.ABI, error) { 1027 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1028 return nil, err 1029 } 1030 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1031 &message.GetABI{Contract: in.Value}, defaultActorTimeout, "rpc.(*AergoRPCService).GetABI").Result() 1032 if err != nil { 1033 return nil, err 1034 } 1035 rsp, ok := result.(message.GetABIRsp) 1036 if !ok { 1037 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1038 } 1039 return rsp.ABI, rsp.Err 1040 } 1041 1042 func (rpc *AergoRPCService) QueryContract(ctx context.Context, in *types.Query) (*types.SingleBytes, error) { 1043 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1044 return nil, err 1045 } 1046 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1047 &message.GetQuery{Contract: in.ContractAddress, Queryinfo: in.Queryinfo}, defaultActorTimeout, "rpc.(*AergoRPCService).QueryContract").Result() 1048 if err != nil { 1049 return nil, err 1050 } 1051 rsp, ok := result.(message.GetQueryRsp) 1052 if !ok { 1053 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1054 } 1055 return &types.SingleBytes{Value: rsp.Result}, rsp.Err 1056 } 1057 1058 // QueryContractState queries the state of a contract state variable without executing a contract function. 1059 func (rpc *AergoRPCService) QueryContractState(ctx context.Context, in *types.StateQuery) (*types.StateQueryProof, error) { 1060 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1061 return nil, err 1062 } 1063 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1064 &message.GetStateQuery{ContractAddress: in.ContractAddress, StorageKeys: in.StorageKeys, Root: in.Root, Compressed: in.Compressed}, defaultActorTimeout, "rpc.(*AergoRPCService).GetStateQuery").Result() 1065 if err != nil { 1066 return nil, err 1067 } 1068 rsp, ok := result.(message.GetStateQueryRsp) 1069 if !ok { 1070 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1071 } 1072 return rsp.Result, rsp.Err 1073 } 1074 1075 func toTimestamp(time time.Time) *timestamp.Timestamp { 1076 return ×tamp.Timestamp{ 1077 Seconds: time.Unix(), 1078 Nanos: int32(time.Nanosecond())} 1079 } 1080 1081 func fromTimestamp(timestamp *timestamp.Timestamp) time.Time { 1082 return time.Unix(timestamp.Seconds, int64(timestamp.Nanos)) 1083 } 1084 1085 func (rpc *AergoRPCService) ListEventStream(in *types.FilterInfo, stream types.AergoRPCService_ListEventStreamServer) error { 1086 err := in.ValidateCheck(0) 1087 if err != nil { 1088 return err 1089 } 1090 _, err = in.GetExArgFilter() 1091 if err != nil { 1092 return err 1093 } 1094 1095 eventStream := &EventStream{in, stream} 1096 rpc.eventStreamLock.Lock() 1097 rpc.eventStream[eventStream] = eventStream 1098 rpc.eventStreamLock.Unlock() 1099 1100 for { 1101 select { 1102 case <-eventStream.stream.Context().Done(): 1103 rpc.eventStreamLock.Lock() 1104 delete(rpc.eventStream, eventStream) 1105 rpc.eventStreamLock.Unlock() 1106 return nil 1107 } 1108 } 1109 } 1110 1111 func (rpc *AergoRPCService) BroadcastToEventStream(events []*types.Event) error { 1112 var err error 1113 rpc.eventStreamLock.RLock() 1114 defer rpc.eventStreamLock.RUnlock() 1115 1116 for _, es := range rpc.eventStream { 1117 if es != nil { 1118 argFilter, _ := es.filter.GetExArgFilter() 1119 for _, event := range events { 1120 if event.Filter(es.filter, argFilter) { 1121 err = es.stream.Send(event) 1122 if err != nil { 1123 logger.Warn().Err(err).Msg("failed to broadcast block stream") 1124 break 1125 } 1126 } 1127 } 1128 } 1129 } 1130 return nil 1131 } 1132 1133 func (rpc *AergoRPCService) ListEvents(ctx context.Context, in *types.FilterInfo) (*types.EventList, error) { 1134 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1135 return nil, err 1136 } 1137 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1138 &message.ListEvents{Filter: in}, defaultActorTimeout, "rpc.(*AergoRPCService).ListEvents").Result() 1139 if err != nil { 1140 return nil, err 1141 } 1142 rsp, ok := result.(*message.ListEventsRsp) 1143 if !ok { 1144 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1145 } 1146 return &types.EventList{Events: rsp.Events}, rsp.Err 1147 } 1148 1149 func (rpc *AergoRPCService) GetServerInfo(ctx context.Context, in *types.KeyParams) (*types.ServerInfo, error) { 1150 if err := rpc.checkAuth(ctx, ShowNode); err != nil { 1151 return nil, err 1152 } 1153 result, err := rpc.hub.RequestFuture(message.RPCSvc, 1154 &message.GetServerInfo{Categories: in.Key}, defaultActorTimeout, "rpc.(*AergoRPCService).GetServerInfo").Result() 1155 if err != nil { 1156 return nil, err 1157 } 1158 rsp, ok := result.(*types.ServerInfo) 1159 if !ok { 1160 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1161 } 1162 return rsp, nil 1163 } 1164 1165 // GetConsensusInfo handle rpc request blockchain. It has no additional input parameter 1166 func (rpc *AergoRPCService) GetConsensusInfo(ctx context.Context, in *types.Empty) (*types.ConsensusInfo, error) { 1167 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1168 return nil, err 1169 } 1170 if rpc.consensusAccessor == nil { 1171 return nil, ErrUninitAccessor 1172 } 1173 1174 return rpc.consensusAccessor.ConsensusInfo(), nil 1175 } 1176 1177 // ChainStat handles rpc request chainstat. 1178 func (rpc *AergoRPCService) ChainStat(ctx context.Context, in *types.Empty) (*types.ChainStats, error) { 1179 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1180 return nil, err 1181 } 1182 ca := rpc.actorHelper.GetChainAccessor() 1183 if ca == nil { 1184 return nil, ErrUninitAccessor 1185 } 1186 return &types.ChainStats{Report: ca.GetChainStats()}, nil 1187 } 1188 1189 func (rpc *AergoRPCService) ChangeMembership(ctx context.Context, in *types.MembershipChange) (*types.MembershipChangeReply, error) { 1190 if err := rpc.checkAuth(ctx, ControlNode); err != nil { 1191 return nil, err 1192 } 1193 if rpc.consensusAccessor == nil { 1194 return nil, ErrUninitAccessor 1195 } 1196 1197 if genesisInfo := rpc.actorHelper.GetChainAccessor().GetGenesisInfo(); genesisInfo != nil { 1198 if genesisInfo.ID.Consensus != raftv2.GetName() { 1199 return nil, ErrNotSupportedConsensus 1200 } 1201 } 1202 1203 member, err := rpc.consensusAccessor.ConfChange(in) 1204 if err != nil { 1205 return nil, err 1206 } 1207 1208 reply := &types.MembershipChangeReply{Attr: &types.MemberAttr{ID: uint64(member.ID), Name: member.Name, Address: member.Address, PeerID: []byte(types.PeerID(member.PeerID))}} 1209 return reply, nil 1210 } 1211 1212 //GetEnterpriseConfig return aergo.enterprise configure values. key "ADMINS" is for getting register admin addresses and "ALL" is for getting all key list. 1213 func (rpc *AergoRPCService) GetEnterpriseConfig(ctx context.Context, in *types.EnterpriseConfigKey) (*types.EnterpriseConfig, error) { 1214 genensis := rpc.actorHelper.GetChainAccessor().GetGenesisInfo() 1215 if genensis.PublicNet() { 1216 return nil, status.Error(codes.Unavailable, "not supported in public") 1217 } 1218 1219 if err := rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1220 return nil, err 1221 } 1222 result, err := rpc.hub.RequestFuture(message.ChainSvc, 1223 &message.GetEnterpriseConf{Key: in.Key}, defaultActorTimeout, "rpc.(*AergoRPCService).GetEnterpiseConfig").Result() 1224 if err != nil { 1225 return nil, err 1226 } 1227 rsp, ok := result.(*message.GetEnterpriseConfRsp) 1228 if !ok { 1229 return nil, status.Errorf(codes.Internal, "internal type (%v) error", reflect.TypeOf(result)) 1230 } 1231 return rsp.Conf, nil 1232 } 1233 1234 func (rpc *AergoRPCService) GetConfChangeProgress(ctx context.Context, in *types.SingleBytes) (*types.ConfChangeProgress, error) { 1235 var ( 1236 progress *types.ConfChangeProgress 1237 err error 1238 ) 1239 1240 genesis := rpc.actorHelper.GetChainAccessor().GetGenesisInfo() 1241 if genesis.PublicNet() { 1242 return nil, status.Error(codes.Unavailable, "not supported in public") 1243 } 1244 1245 if strings.ToLower(genesis.ConsensusType()) != consensus.ConsensusName[consensus.ConsensusRAFT] { 1246 return nil, status.Error(codes.Unavailable, "not supported if not raft consensus") 1247 } 1248 1249 if err = rpc.checkAuth(ctx, ReadBlockChain); err != nil { 1250 return nil, err 1251 } 1252 1253 if rpc.consensusAccessor == nil { 1254 return nil, ErrUninitAccessor 1255 } 1256 1257 if len(in.Value) != 8 { 1258 return nil, status.Errorf(codes.InvalidArgument, "Invalid input. Request ID should be a 8 byte number.") 1259 } 1260 1261 reqID := uint64(binary.LittleEndian.Uint64(in.Value)) 1262 1263 if progress, err = rpc.consensusAccessor.ConfChangeInfo(reqID); err != nil { 1264 return nil, err 1265 } 1266 1267 if progress == nil { 1268 return nil, status.Errorf(codes.NotFound, "not found") 1269 } 1270 1271 return progress, nil 1272 }