Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rosetta Implementation - pt4 (Stage 3.4 of Node API Overhaul) #3380

Merged
merged 34 commits into from
Oct 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
341ccfe
[rosetta] Add /construct function framework
Daniel-VDM Aug 26, 2020
b3a7718
[rpc] Expose EstimateGas
Daniel-VDM Sep 15, 2020
447a4b0
[rosetta] Add InvalidTransactionConstructionError
Daniel-VDM Sep 15, 2020
8c090ae
[rosetta] Add error report for b32 error in newAccountIdentifier
Daniel-VDM Sep 16, 2020
5319dd9
[rosetta] Simplify assertValidNetworkIdentifier
Daniel-VDM Sep 16, 2020
138ad26
[rosetta] Implement assertValidTransferOperationsAndGetTxAccounts
Daniel-VDM Sep 16, 2020
7e711fb
[rosetta] Add & Expose OperationComponents
Daniel-VDM Sep 16, 2020
e6f3800
[rosetta] Add error for 3+ operations in getOperationComponents
Daniel-VDM Sep 16, 2020
264ec54
[rosetta] Expose GetOperationComponents
Daniel-VDM Sep 16, 2020
814ccec
[rosetta] Add CrossShardTransactionOperationMetadata
Daniel-VDM Sep 17, 2020
882f763
[go.mod] Bump rosetta version to 0.4.4 & dependent libs
Daniel-VDM Sep 17, 2020
36b8240
[rosetta] Rename PreStakingBlockRewardOperation
Daniel-VDM Sep 17, 2020
6b54a7f
[rosetta] Init operation_components.go & move respective code
Daniel-VDM Sep 17, 2020
9d65b30
[rosetta] Add getAddress and update respective functions
Daniel-VDM Sep 18, 2020
2ba0051
[rosetta] Create transaction_construction.go & impl ConstructTransaction
Daniel-VDM Sep 18, 2020
51b1db1
[internal/commonm] Add MustGeneratePrivateKey
Daniel-VDM Sep 23, 2020
3f1c877
[rosetta] Implement parseUnsignedTransaction
Daniel-VDM Sep 23, 2020
77190d6
[rosetta] Implement parseSignedTransaction
Daniel-VDM Sep 23, 2020
fb4c65c
[rosetta] Finish initial Construct implementation
Daniel-VDM Sep 24, 2020
c1572a4
[rosetta] Implement construction_check_test.go
Daniel-VDM Sep 24, 2020
6b546f1
[rosetta] Implement construction_parse_test.go
Daniel-VDM Sep 29, 2020
3d83e48
[rosetta] Add operation_components_test.go
Daniel-VDM Sep 29, 2020
4eb20a0
[rosetta] Implement transaction_construction_test.go
Daniel-VDM Sep 30, 2020
95aab05
[rosetta] Add TestGetAddressFromKnownPublicKey
Daniel-VDM Oct 1, 2020
885e7da
[hmy] Fix possible nil ptr crash for GetBlockSigners
Daniel-VDM Oct 3, 2020
dc4a1a3
[rosetta] Fix unpackWrappedTransactionFromHexString
Daniel-VDM Oct 3, 2020
39cd494
[rosetta] Add SignatureType & SignedPayloadLength with checks
Daniel-VDM Oct 3, 2020
59a2ada
[rosetta] Correct error message dumps for transaction_construction.go
Daniel-VDM Oct 3, 2020
548f635
[rpc] Fix estimate gas fail check
Daniel-VDM Oct 4, 2020
5bb3d5f
[rosetta] Add DefaultSenderAddress for transaction formatter
Daniel-VDM Oct 6, 2020
10c70ec
[rosetta] Fix imports
Daniel-VDM Oct 6, 2020
9136c57
[rosetta] Address PR comments
Daniel-VDM Oct 7, 2020
d68c600
[rosetta] Add checks to tx formatter for nil to addr
Daniel-VDM Oct 9, 2020
7c25530
[rosetta] Remove EstimatedGasUsed from WrappedTransaction
Daniel-VDM Oct 9, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,48 @@ module github.com/harmony-one/harmony
go 1.14

require (
github.com/OneOfOne/xxhash v1.2.5 // indirect
github.com/VictoriaMetrics/fastcache v1.5.7 // indirect
github.com/Workiva/go-datastructures v1.0.50
github.com/allegro/bigcache v1.2.1 // indirect
github.com/aristanetworks/goarista v0.0.0-20190607111240-52c2a7864a08 // indirect
github.com/aws/aws-sdk-go v1.30.1
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcutil v1.0.2
github.com/cespare/cp v1.1.1
github.com/coinbase/rosetta-sdk-go v0.4.4
github.com/davecgh/go-spew v1.1.1
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f // indirect
github.com/deckarep/golang-set v1.7.1
github.com/dlclark/regexp2 v1.2.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa // indirect
github.com/ethereum/go-ethereum v1.9.21
github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a // indirect
github.com/garslo/gogen v0.0.0-20170307003452-d6ebae628c7c // indirect
github.com/go-sourcemap/sourcemap v2.1.2+incompatible // indirect
github.com/golang/mock v1.4.0
github.com/golang/protobuf v1.4.2
github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26 // indirect
github.com/golangci/golangci-lint v1.22.2
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2 // indirect
github.com/harmony-ek/gencodec v0.0.0-20190215044613-e6740dbdd846
github.com/harmony-one/abool v1.0.1
github.com/harmony-one/bls v0.0.6
github.com/harmony-one/taggedrlp v0.1.4
github.com/harmony-one/vdf v0.0.0-20190924175951-620379da8849
github.com/hashicorp/golang-lru v0.5.4
github.com/holiman/uint256 v1.1.1 // indirect
github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 // indirect
github.com/ipfs/go-ds-badger v0.2.4
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/karalabe/hid v1.0.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/libp2p/go-addr-util v0.0.2 // indirect
github.com/libp2p/go-libp2p v0.10.3
github.com/libp2p/go-libp2p-core v0.6.1
github.com/libp2p/go-libp2p-crypto v0.1.0
github.com/libp2p/go-libp2p-discovery v0.5.0
github.com/libp2p/go-libp2p-host v0.1.0 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.8.3
github.com/libp2p/go-libp2p-net v0.1.0 // indirect
github.com/libp2p/go-libp2p-peer v0.2.0 // indirect
github.com/libp2p/go-libp2p-peerstore v0.2.6 // indirect
github.com/libp2p/go-libp2p-pubsub v0.3.3
github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/multiformats/go-multiaddr v0.2.2
github.com/multiformats/go-multiaddr-net v0.1.5
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/pborman/uuid v1.2.0
github.com/pelletier/go-toml v1.2.0
github.com/pkg/errors v0.9.1
github.com/prometheus/common v0.4.1 // indirect
github.com/prometheus/procfs v0.0.3 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
github.com/rjeczalik/notify v0.9.2
github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/rs/zerolog v1.18.0
github.com/shirou/gopsutil v2.20.5+incompatible // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.6.1
Expand All @@ -80,10 +58,6 @@ require (
google.golang.org/protobuf v1.25.0
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
gopkg.in/yaml.v2 v2.3.0
)

Expand Down
4 changes: 4 additions & 0 deletions hmy/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package hmy

import (
"context"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -43,6 +44,9 @@ func (hmy *Harmony) GetBlockSigners(
if err != nil {
return nil, nil, err
}
if blockWithSigners == nil {
return nil, nil, fmt.Errorf("block number %v not found", blockNum+1)
}
committee, err := hmy.GetValidators(blk.Epoch())
if err != nil {
return nil, nil, err
Expand Down
11 changes: 11 additions & 0 deletions internal/common/address.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package common

import (
"crypto/ecdsa"
"database/sql/driver"
"encoding/hex"
"fmt"
"math/big"

ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/internal/bech32"
"github.com/harmony-one/harmony/internal/utils"
"github.com/pkg/errors"
Expand Down Expand Up @@ -228,3 +230,12 @@ func ParseAddr(s string) ethCommon.Address {
// The result can be 0x00...00 if the passing param is not a correct address.
return ethCommon.HexToAddress(s)
}

// MustGeneratePrivateKey generates a random private key for an address. It panics on error.
func MustGeneratePrivateKey() *ecdsa.PrivateKey {
key, err := crypto.GenerateKey()
if err != nil {
panic(err)
}
return key
}
28 changes: 28 additions & 0 deletions internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"net"
"os"
"regexp"
"runtime"
"strconv"
"strings"
"sync"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -80,6 +82,32 @@ func GetAddressFromBLSPubKeyBytes(pubKeyBytes []byte) common.Address {
return addr
}

// GetCallStackInfo return a string containing the file name, function name
// and the line number of a specified entry on the call stack.
// Inspired by https://github.com/jimlawless/whereami
func GetCallStackInfo(depthList ...int) string {
var depth int
if depthList == nil {
depth = 1
} else {
depth = depthList[0]
}
function, file, line, _ := runtime.Caller(depth)
return fmt.Sprintf("File: %s Function: %s Line: %d",
chopPath(file), runtime.FuncForPC(function).Name(), line,
)
}

// chopPath returns the source filename after the last slash.
// Inspired by https://github.com/jimlawless/whereami
func chopPath(original string) string {
i := strings.LastIndex(original, "/")
if i == -1 {
return original
}
return original[i+1:]
}

// TODO Remove this from main code - it is only used in *_test.go

// GenKeyP2P generates a pair of RSA keys used in libp2p host
Expand Down
11 changes: 8 additions & 3 deletions rosetta/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (

"github.com/coinbase/rosetta-sdk-go/types"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/rpc"
"github.com/harmony-one/harmony/shard"
)

const (
// RosettaVersion tied back to the version of the rosetta go-sdk
RosettaVersion = "0.3.4" // TODO (dm): set variable via build flags
RosettaVersion = "0.4.4" // TODO (dm): set variable via build flags

// Blockchain ..
Blockchain = "Harmony"
Expand All @@ -26,6 +25,9 @@ const (

// CurveType ..
CurveType = types.Secp256k1

// SignatureType ..
SignatureType = types.EcdsaRecovery
)

var (
Expand All @@ -43,6 +45,9 @@ var (
Symbol: Symbol,
Decimals: Decimals,
}

// CurrencyHash for quick equivalent checks
CurrencyHash = types.Hash(Currency)
)

// SyncStatus ..
Expand Down Expand Up @@ -81,7 +86,7 @@ func (s *SubNetworkMetadata) UnmarshalFromInterface(metadata interface{}) error

// GetNetwork fetches the networking identifier for the given shard
func GetNetwork(shardID uint32) (*types.NetworkIdentifier, error) {
metadata, err := rpc.NewStructuredResponse(SubNetworkMetadata{
metadata, err := types.MarshalMap(SubNetworkMetadata{
IsBeacon: shardID == shard.BeaconChainShardID,
})
if err != nil {
Expand Down
23 changes: 21 additions & 2 deletions rosetta/common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"

"github.com/coinbase/rosetta-sdk-go/types"
"github.com/harmony-one/harmony/rpc"

nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils"
)

var (
Expand Down Expand Up @@ -63,18 +65,35 @@ var (
Message: "receipt not found",
Retriable: false,
}

// UnsupportedCurveTypeError ..
UnsupportedCurveTypeError = types.Error{
Code: 8,
Message: "unsupported curve type",
Retriable: false,
}

// InvalidTransactionConstructionError ..
InvalidTransactionConstructionError = types.Error{
Code: 9,
Message: "invalid transaction construction",
Retriable: false,
}
)

// NewError create a new error with a given detail structure
func NewError(rosettaError types.Error, detailStructure interface{}) *types.Error {
newError := rosettaError
details, err := rpc.NewStructuredResponse(detailStructure)
details, err := types.MarshalMap(detailStructure)
if err != nil {
newError.Details = map[string]interface{}{
"message": fmt.Sprintf("unable to get error details: %v", err.Error()),
}
} else {
newError.Details = details
}
newError.Details["trace"] = utils.GetCallStackInfo(2)
newError.Details["rosetta_version"] = RosettaVersion
newError.Details["node_version"] = nodeconfig.GetVersion()
return &newError
}
19 changes: 19 additions & 0 deletions rosetta/common/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func TestErrorCodes(t *testing.T) {
BlockNotFoundError,
TransactionNotFoundError,
ReceiptNotFoundError,
UnsupportedCurveTypeError,
InvalidTransactionConstructionError,
}

for i, err := range errors {
Expand All @@ -40,6 +42,8 @@ func TestRetryableError(t *testing.T) {
BlockNotFoundError,
TransactionNotFoundError,
ReceiptNotFoundError,
UnsupportedCurveTypeError,
InvalidTransactionConstructionError,
}

for _, err := range retriableErrors {
Expand All @@ -54,3 +58,18 @@ func TestRetryableError(t *testing.T) {
}
}
}

func TestNewError(t *testing.T) {
testErr := NewError(CatchAllError, map[string]interface{}{
"message": "boom",
})
if testErr == &CatchAllError {
t.Fatal("expected return of a copy of error")
}
if testErr.Details == nil {
t.Fatal("suppose to have details")
}
if testErr.Details["trace"] == nil {
t.Error("expect trace")
}
}
46 changes: 45 additions & 1 deletion rosetta/common/operations.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package common

import (
"encoding/json"
"fmt"

"github.com/coinbase/rosetta-sdk-go/types"

rpcV2 "github.com/harmony-one/harmony/rpc/v2"
staking "github.com/harmony-one/harmony/staking/types"
)

// Invariant: A transaction can only contain 1 type of operation(s) other than gas expenditure.
const (
// ExpendGasOperation ..
ExpendGasOperation = "Gas"
Expand All @@ -22,7 +28,7 @@ const (
GenesisFundsOperation = "Genesis"

// PreStakingBlockRewardOperation ..
PreStakingBlockRewardOperation = "PreOpenStakingBlockReward"
PreStakingBlockRewardOperation = "PreStakingBlockReward"

// UndelegationPayoutOperation ..
UndelegationPayoutOperation = "UndelegationPayout"
Expand Down Expand Up @@ -70,3 +76,41 @@ var (
Successful: false,
}
)

// CreateValidatorOperationMetadata ..
type CreateValidatorOperationMetadata rpcV2.CreateValidatorMsg

// EditValidatorOperationMetadata ..
type EditValidatorOperationMetadata rpcV2.EditValidatorMsg

// DelegateOperationMetadata ..
type DelegateOperationMetadata rpcV2.DelegateMsg

// UndelegateOperationMetadata ..
type UndelegateOperationMetadata rpcV2.UndelegateMsg

// CollectRewardsMetadata ..
type CollectRewardsMetadata rpcV2.CollectRewardsMsg

// CrossShardTransactionOperationMetadata ..
type CrossShardTransactionOperationMetadata struct {
From *types.AccountIdentifier `json:"from"`
To *types.AccountIdentifier `json:"to"`
}

// UnmarshalFromInterface ..
func (s *CrossShardTransactionOperationMetadata) UnmarshalFromInterface(data interface{}) error {
var T CrossShardTransactionOperationMetadata
dat, err := json.Marshal(data)
if err != nil {
return err
}
if err := json.Unmarshal(dat, &T); err != nil {
return err
}
if T.To == nil || T.From == nil {
return fmt.Errorf("expected to & from to be present for CrossShardTransactionOperationMetadata")
}
*s = T
return nil
}
3 changes: 2 additions & 1 deletion rosetta/rosetta.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func StartServers(hmy *hmy.Harmony, config nodeconfig.RosettaServerConfig) error
return err
}

router := server.CorsMiddleware(recoverMiddleware(loggerMiddleware(getRouter(serverAsserter, hmy))))
router := recoverMiddleware(server.CorsMiddleware(loggerMiddleware(getRouter(serverAsserter, hmy))))
utils.Logger().Info().
Int("port", config.HTTPPort).
Str("ip", config.HTTPIp).
Expand Down Expand Up @@ -80,6 +80,7 @@ func getRouter(asserter *asserter.Asserter, hmy *hmy.Harmony) http.Handler {
server.NewBlockAPIController(services.NewBlockAPI(hmy), asserter),
server.NewMempoolAPIController(services.NewMempoolAPI(hmy), asserter),
server.NewNetworkAPIController(services.NewNetworkAPI(hmy), asserter),
server.NewConstructionAPIController(services.NewConstructionAPI(hmy), asserter),
)
}

Expand Down
Loading