diff --git a/rpc/core/accounts.go b/rpc/core/accounts.go new file mode 100644 index 000000000..b70fa1874 --- /dev/null +++ b/rpc/core/accounts.go @@ -0,0 +1,32 @@ +package core + +import ( + "github.com/tendermint/tendermint/account" +) + +//----------------------------------------------------------------------------- + +func GenPrivAccount() *account.PrivAccount { + return account.GenPrivAccount() +} + +//----------------------------------------------------------------------------- + +func GetAccount(address []byte) *account.Account { + state := consensusState.GetState() + return state.GetAccount(address) +} + +//----------------------------------------------------------------------------- + +func ListAccounts() (uint, []*account.Account) { + var blockHeight uint + var accounts []*account.Account + state := consensusState.GetState() + blockHeight = state.LastBlockHeight + state.GetAccounts().Iterate(func(key interface{}, value interface{}) bool { + accounts = append(accounts, value.(*account.Account)) + return false + }) + return blockHeight, accounts +} diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go new file mode 100644 index 000000000..0a92d2044 --- /dev/null +++ b/rpc/core/blocks.go @@ -0,0 +1,44 @@ +package core + +import ( + "fmt" + . "github.com/tendermint/tendermint/common" + "github.com/tendermint/tendermint/types" +) + +//----------------------------------------------------------------------------- + +func BlockchainInfoHandler(minHeight, maxHeight uint) (uint, []*types.BlockMeta) { + if maxHeight == 0 { + maxHeight = blockStore.Height() + } else { + maxHeight = MinUint(blockStore.Height(), maxHeight) + } + if minHeight == 0 { + minHeight = uint(MaxInt(1, int(maxHeight)-20)) + } + log.Debug("BlockchainInfoHandler", "maxHeight", maxHeight, "minHeight", minHeight) + + blockMetas := []*types.BlockMeta{} + for height := maxHeight; height >= minHeight; height-- { + blockMeta := blockStore.LoadBlockMeta(height) + blockMetas = append(blockMetas, blockMeta) + } + + return blockStore.Height(), blockMetas +} + +//----------------------------------------------------------------------------- + +func GetBlockHandler(height uint) (*types.BlockMeta, *types.Block, error) { + if height == 0 { + return nil, nil, fmt.Errorf("height must be greater than 1") + } + if height > blockStore.Height() { + return nil, nil, fmt.Errorf("height must be less than the current blockchain height") + } + + blockMeta := blockStore.LoadBlockMeta(height) + block := blockStore.LoadBlock(height) + return blockMeta, block, nil +} diff --git a/rpc/core/log.go b/rpc/core/log.go new file mode 100644 index 000000000..d359bee26 --- /dev/null +++ b/rpc/core/log.go @@ -0,0 +1,7 @@ +package core + +import ( + "github.com/tendermint/log15" +) + +var log = log15.New("module", "rpc") diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go new file mode 100644 index 000000000..e20dc2b54 --- /dev/null +++ b/rpc/core/mempool.go @@ -0,0 +1,42 @@ +package core + +import ( + "fmt" + . "github.com/tendermint/tendermint/common" + "github.com/tendermint/tendermint/merkle" + "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/types" +) + +//----------------------------------------------------------------------------- + +type Receipt struct { + TxHash []byte + CreatesContract bool + ContractAddr []byte +} + +// pass pointer? +// Note: tx must be signed +func BroadcastTx(tx types.Tx) (*Receipt, error) { + err := mempoolReactor.BroadcastTx(tx) + if err != nil { + return nil, fmt.Errorf("Error broadcasting transaction: %v", err) + } + + txHash := merkle.HashFromBinary(tx) + var createsContract bool + var contractAddr []byte + // check if creates new contract + if callTx, ok := tx.(*types.CallTx); ok { + if callTx.Address == nil { + createsContract = true + contractAddr = state.NewContractAddress(callTx.Input.Address, uint64(callTx.Input.Sequence)) + } + } + return &Receipt{txHash, createsContract, contractAddr}, nil +} + +/* +curl -H 'content-type: text/plain;' http://127.0.0.1:8888/submit_tx?tx=... +*/ diff --git a/rpc/core/net.go b/rpc/core/net.go new file mode 100644 index 000000000..b143d7271 --- /dev/null +++ b/rpc/core/net.go @@ -0,0 +1,39 @@ +package core + +import ( + "github.com/tendermint/tendermint/config" + dbm "github.com/tendermint/tendermint/db" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/types" +) + +//----------------------------------------------------------------------------- + +func Status() ([]byte, string, []byte, uint, int64) { + db := dbm.NewMemDB() + genesisState := sm.MakeGenesisStateFromFile(db, config.App().GetString("GenesisFile")) + genesisHash := genesisState.Hash() + latestHeight := blockStore.Height() + var ( + latestBlockMeta *types.BlockMeta + latestBlockHash []byte + latestBlockTime int64 + ) + if latestHeight != 0 { + latestBlockMeta = blockStore.LoadBlockMeta(latestHeight) + latestBlockHash = latestBlockMeta.Hash + latestBlockTime = latestBlockMeta.Header.Time.UnixNano() + } + + return genesisHash, config.App().GetString("Network"), latestBlockHash, latestHeight, latestBlockTime +} + +//----------------------------------------------------------------------------- + +func NetInfo() (int, bool, string) { + o, i, _ := p2pSwitch.NumPeers() + numPeers := o + i + listening := p2pSwitch.IsListening() + network := config.App().GetString("Network") + return numPeers, listening, network +} diff --git a/rpc/core/pipe.go b/rpc/core/pipe.go new file mode 100644 index 000000000..b939c6dd6 --- /dev/null +++ b/rpc/core/pipe.go @@ -0,0 +1,29 @@ +package core + +import ( + "github.com/tendermint/tendermint/consensus" + mempl "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/types" +) + +var blockStore *types.BlockStore +var consensusState *consensus.ConsensusState +var mempoolReactor *mempl.MempoolReactor +var p2pSwitch *p2p.Switch + +func SetPipeBlockStore(bs *types.BlockStore) { + blockStore = bs +} + +func SetPipeConsensusState(cs *consensus.ConsensusState) { + consensusState = cs +} + +func SetPipeMempoolReactor(mr *mempl.MempoolReactor) { + mempoolReactor = mr +} + +func SetPipeSwitch(sw *p2p.Switch) { + p2pSwitch = sw +} diff --git a/rpc/core/txs.go b/rpc/core/txs.go new file mode 100644 index 000000000..805414898 --- /dev/null +++ b/rpc/core/txs.go @@ -0,0 +1,45 @@ +package core + +import ( + "fmt" + "github.com/tendermint/tendermint/account" + "github.com/tendermint/tendermint/types" +) + +//----------------------------------------------------------------------------- + +func SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (types.Tx, error) { + // more checks? + + for i, privAccount := range privAccounts { + if privAccount == nil || privAccount.PrivKey == nil { + return nil, fmt.Errorf("Invalid (empty) privAccount @%v", i) + } + } + + switch tx.(type) { + case *types.SendTx: + sendTx := tx.(*types.SendTx) + for i, input := range sendTx.Inputs { + input.PubKey = privAccounts[i].PubKey + input.Signature = privAccounts[i].Sign(sendTx) + } + case *types.CallTx: + callTx := tx.(*types.CallTx) + callTx.Input.PubKey = privAccounts[0].PubKey + callTx.Input.Signature = privAccounts[0].Sign(callTx) + case *types.BondTx: + bondTx := tx.(*types.BondTx) + for i, input := range bondTx.Inputs { + input.PubKey = privAccounts[i].PubKey + input.Signature = privAccounts[i].Sign(bondTx) + } + case *types.UnbondTx: + unbondTx := tx.(*types.UnbondTx) + unbondTx.Signature = privAccounts[0].Sign(unbondTx).(account.SignatureEd25519) + case *types.RebondTx: + rebondTx := tx.(*types.RebondTx) + rebondTx.Signature = privAccounts[0].Sign(rebondTx).(account.SignatureEd25519) + } + return tx, nil +} diff --git a/rpc/core/validators.go b/rpc/core/validators.go new file mode 100644 index 000000000..b1892f69b --- /dev/null +++ b/rpc/core/validators.go @@ -0,0 +1,26 @@ +package core + +import ( + sm "github.com/tendermint/tendermint/state" +) + +//----------------------------------------------------------------------------- + +func ListValidators() (uint, []*sm.Validator, []*sm.Validator) { + var blockHeight uint + var bondedValidators []*sm.Validator + var unbondingValidators []*sm.Validator + + state := consensusState.GetState() + blockHeight = state.LastBlockHeight + state.BondedValidators.Iterate(func(index uint, val *sm.Validator) bool { + bondedValidators = append(bondedValidators, val) + return false + }) + state.UnbondingValidators.Iterate(func(index uint, val *sm.Validator) bool { + unbondingValidators = append(unbondingValidators, val) + return false + }) + + return blockHeight, bondedValidators, unbondingValidators +}