signer/core: move API JSON types to separate package (#23275)

This PR moves (some) account types into a standalone package, to avoid
depending on signer/core from accounts/external.
This commit is contained in:
Martin Holst Swende 2021-07-29 16:06:44 +02:00 committed by GitHub
parent 8f11d279d2
commit 295bc35ecf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 52 additions and 46 deletions

View File

@ -29,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
type ExternalBackend struct { type ExternalBackend struct {
@ -203,7 +203,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
t := common.NewMixedcaseAddress(*tx.To()) t := common.NewMixedcaseAddress(*tx.To())
to = &t to = &t
} }
args := &core.SendTxArgs{ args := &apitypes.SendTxArgs{
Data: &data, Data: &data,
Nonce: hexutil.Uint64(tx.Nonce()), Nonce: hexutil.Uint64(tx.Nonce()),
Value: hexutil.Big(*tx.Value()), Value: hexutil.Big(*tx.Value()),

View File

@ -23,7 +23,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/fourbyte" "github.com/ethereum/go-ethereum/signer/fourbyte"
) )
@ -41,7 +41,7 @@ func parse(data []byte) {
if err != nil { if err != nil {
die(err) die(err)
} }
messages := core.ValidationMessages{} messages := apitypes.ValidationMessages{}
db.ValidateCallData(nil, data, &messages) db.ValidateCallData(nil, data, &messages)
for _, m := range messages.Messages { for _, m := range messages.Messages {
fmt.Printf("%v: %v\n", m.Typ, m.Message) fmt.Printf("%v: %v\n", m.Typ, m.Message)

View File

@ -50,10 +50,10 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/fourbyte" "github.com/ethereum/go-ethereum/signer/fourbyte"
"github.com/ethereum/go-ethereum/signer/rules" "github.com/ethereum/go-ethereum/signer/rules"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -923,7 +923,7 @@ func testExternalUI(api *core.SignerAPI) {
time.Sleep(delay) time.Sleep(delay)
data := hexutil.Bytes([]byte{}) data := hexutil.Bytes([]byte{})
to := common.NewMixedcaseAddress(a) to := common.NewMixedcaseAddress(a)
tx := core.SendTxArgs{ tx := apitypes.SendTxArgs{
Data: &data, Data: &data,
Nonce: 0x1, Nonce: 0x1,
Value: hexutil.Big(*big.NewInt(6)), Value: hexutil.Big(*big.NewInt(6)),
@ -1055,11 +1055,11 @@ func GenDoc(ctx *cli.Context) {
data := hexutil.Bytes([]byte{0x01, 0x02, 0x03, 0x04}) data := hexutil.Bytes([]byte{0x01, 0x02, 0x03, 0x04})
add("SignTxRequest", desc, &core.SignTxRequest{ add("SignTxRequest", desc, &core.SignTxRequest{
Meta: meta, Meta: meta,
Callinfo: []core.ValidationInfo{ Callinfo: []apitypes.ValidationInfo{
{Typ: "Warning", Message: "Something looks odd, show this message as a warning"}, {Typ: "Warning", Message: "Something looks odd, show this message as a warning"},
{Typ: "Info", Message: "User should see this as well"}, {Typ: "Info", Message: "User should see this as well"},
}, },
Transaction: core.SendTxArgs{ Transaction: apitypes.SendTxArgs{
Data: &data, Data: &data,
Nonce: 0x1, Nonce: 0x1,
Value: hexutil.Big(*big.NewInt(6)), Value: hexutil.Big(*big.NewInt(6)),
@ -1075,7 +1075,7 @@ func GenDoc(ctx *cli.Context) {
add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+ add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+
", because the UI is free to make modifications to the transaction.", ", because the UI is free to make modifications to the transaction.",
&core.SignTxResponse{Approved: true, &core.SignTxResponse{Approved: true,
Transaction: core.SendTxArgs{ Transaction: apitypes.SendTxArgs{
Data: &data, Data: &data,
Nonce: 0x4, Nonce: 0x4,
Value: hexutil.Big(*big.NewInt(6)), Value: hexutil.Big(*big.NewInt(6)),

View File

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"
) )
@ -52,7 +53,7 @@ type ExternalAPI interface {
// New request to create a new account // New request to create a new account
New(ctx context.Context) (common.Address, error) New(ctx context.Context) (common.Address, error)
// SignTransaction request to sign the specified transaction // SignTransaction request to sign the specified transaction
SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error)
// SignData - request to sign the given data (plus prefix) // SignData - request to sign the given data (plus prefix)
SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error)
// SignTypedData - request to sign the given structured data (plus prefix) // SignTypedData - request to sign the given structured data (plus prefix)
@ -104,7 +105,7 @@ type Validator interface {
// ValidateTransaction does a number of checks on the supplied transaction, and // ValidateTransaction does a number of checks on the supplied transaction, and
// returns either a list of warnings, or an error (indicating that the transaction // returns either a list of warnings, or an error (indicating that the transaction
// should be immediately rejected). // should be immediately rejected).
ValidateTransaction(selector *string, tx *SendTxArgs) (*ValidationMessages, error) ValidateTransaction(selector *string, tx *apitypes.SendTxArgs) (*apitypes.ValidationMessages, error)
} }
// SignerAPI defines the actual implementation of ExternalAPI // SignerAPI defines the actual implementation of ExternalAPI
@ -220,14 +221,14 @@ func (m Metadata) String() string {
type ( type (
// SignTxRequest contains info about a Transaction to sign // SignTxRequest contains info about a Transaction to sign
SignTxRequest struct { SignTxRequest struct {
Transaction SendTxArgs `json:"transaction"` Transaction apitypes.SendTxArgs `json:"transaction"`
Callinfo []ValidationInfo `json:"call_info"` Callinfo []apitypes.ValidationInfo `json:"call_info"`
Meta Metadata `json:"meta"` Meta Metadata `json:"meta"`
} }
// SignTxResponse result from SignTxRequest // SignTxResponse result from SignTxRequest
SignTxResponse struct { SignTxResponse struct {
//The UI may make changes to the TX //The UI may make changes to the TX
Transaction SendTxArgs `json:"transaction"` Transaction apitypes.SendTxArgs `json:"transaction"`
Approved bool `json:"approved"` Approved bool `json:"approved"`
} }
SignDataRequest struct { SignDataRequest struct {
@ -235,7 +236,7 @@ type (
Address common.MixedcaseAddress `json:"address"` Address common.MixedcaseAddress `json:"address"`
Rawdata []byte `json:"raw_data"` Rawdata []byte `json:"raw_data"`
Messages []*NameValueType `json:"messages"` Messages []*NameValueType `json:"messages"`
Callinfo []ValidationInfo `json:"call_info"` Callinfo []apitypes.ValidationInfo `json:"call_info"`
Hash hexutil.Bytes `json:"hash"` Hash hexutil.Bytes `json:"hash"`
Meta Metadata `json:"meta"` Meta Metadata `json:"meta"`
} }
@ -537,7 +538,7 @@ func (api *SignerAPI) lookupOrQueryPassword(address common.Address, title, promp
} }
// SignTransaction signs the given Transaction and returns it both as json and rlp-encoded form // SignTransaction signs the given Transaction and returns it both as json and rlp-encoded form
func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) { func (api *SignerAPI) SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
var ( var (
err error err error
result SignTxResponse result SignTxResponse
@ -548,7 +549,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
} }
// If we are in 'rejectMode', then reject rather than show the user warnings // If we are in 'rejectMode', then reject rather than show the user warnings
if api.rejectMode { if api.rejectMode {
if err := msgs.getWarnings(); err != nil { if err := msgs.GetWarnings(); err != nil {
return nil, err return nil, err
} }
} }
@ -585,7 +586,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
return nil, err return nil, err
} }
// Convert fields into a real transaction // Convert fields into a real transaction
var unsignedTx = result.Transaction.toTransaction() var unsignedTx = result.Transaction.ToTransaction()
// Get the password for the transaction // Get the password for the transaction
pw, err := api.lookupOrQueryPassword(acc.Address, "Account password", pw, err := api.lookupOrQueryPassword(acc.Address, "Account password",
fmt.Sprintf("Please enter the password for account %s", acc.Address.String())) fmt.Sprintf("Please enter the password for account %s", acc.Address.String()))
@ -621,7 +622,7 @@ func (api *SignerAPI) SignGnosisSafeTx(ctx context.Context, signerAddress common
} }
// If we are in 'rejectMode', then reject rather than show the user warnings // If we are in 'rejectMode', then reject rather than show the user warnings
if api.rejectMode { if api.rejectMode {
if err := msgs.getWarnings(); err != nil { if err := msgs.GetWarnings(); err != nil {
return nil, err return nil, err
} }
} }

View File

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/fourbyte" "github.com/ethereum/go-ethereum/signer/fourbyte"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"
) )
@ -223,14 +224,14 @@ func TestNewAcc(t *testing.T) {
} }
} }
func mkTestTx(from common.MixedcaseAddress) core.SendTxArgs { func mkTestTx(from common.MixedcaseAddress) apitypes.SendTxArgs {
to := common.NewMixedcaseAddress(common.HexToAddress("0x1337")) to := common.NewMixedcaseAddress(common.HexToAddress("0x1337"))
gas := hexutil.Uint64(21000) gas := hexutil.Uint64(21000)
gasPrice := (hexutil.Big)(*big.NewInt(2000000000)) gasPrice := (hexutil.Big)(*big.NewInt(2000000000))
value := (hexutil.Big)(*big.NewInt(1e18)) value := (hexutil.Big)(*big.NewInt(1e18))
nonce := (hexutil.Uint64)(0) nonce := (hexutil.Uint64)(0)
data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a")) data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a"))
tx := core.SendTxArgs{ tx := apitypes.SendTxArgs{
From: from, From: from,
To: &to, To: &to,
Gas: gas, Gas: gas,

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package apitypes
import ( import (
"encoding/json" "encoding/json"
@ -52,7 +52,7 @@ func (vs *ValidationMessages) Info(msg string) {
} }
/// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present /// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
func (v *ValidationMessages) getWarnings() error { func (v *ValidationMessages) GetWarnings() error {
var messages []string var messages []string
for _, msg := range v.Messages { for _, msg := range v.Messages {
if msg.Typ == WARN || msg.Typ == CRIT { if msg.Typ == WARN || msg.Typ == CRIT {
@ -97,7 +97,7 @@ func (args SendTxArgs) String() string {
return err.Error() return err.Error()
} }
func (args *SendTxArgs) toTransaction() *types.Transaction { func (args *SendTxArgs) ToTransaction() *types.Transaction {
txArgs := ethapi.TransactionArgs{ txArgs := ethapi.TransactionArgs{
Gas: &args.Gas, Gas: &args.Gas,
GasPrice: args.GasPrice, GasPrice: args.GasPrice,

View File

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
type AuditLogger struct { type AuditLogger struct {
@ -43,7 +44,7 @@ func (l *AuditLogger) New(ctx context.Context) (common.Address, error) {
return l.api.New(ctx) return l.api.New(ctx)
} }
func (l *AuditLogger) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) { func (l *AuditLogger) SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
sel := "<nil>" sel := "<nil>"
if methodSelector != nil { if methodSelector != nil {
sel = *methodSelector sel = *methodSelector

View File

@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
// GnosisSafeTx is a type to parse the safe-tx returned by the relayer, // GnosisSafeTx is a type to parse the safe-tx returned by the relayer,
@ -76,9 +77,9 @@ func (tx *GnosisSafeTx) ToTypedData() TypedData {
// ArgsForValidation returns a SendTxArgs struct, which can be used for the // ArgsForValidation returns a SendTxArgs struct, which can be used for the
// common validations, e.g. look up 4byte destinations // common validations, e.g. look up 4byte destinations
func (tx *GnosisSafeTx) ArgsForValidation() *SendTxArgs { func (tx *GnosisSafeTx) ArgsForValidation() *apitypes.SendTxArgs {
gp := hexutil.Big(tx.GasPrice) gp := hexutil.Big(tx.GasPrice)
args := &SendTxArgs{ args := &apitypes.SendTxArgs{
From: tx.Safe, From: tx.Safe,
To: &tx.To, To: &tx.To,
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()), Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),

View File

@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
type SigFormat struct { type SigFormat struct {
@ -323,7 +324,7 @@ func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAd
// signTypedData is identical to the capitalized version, except that it also returns the hash (preimage) // signTypedData is identical to the capitalized version, except that it also returns the hash (preimage)
// - the signature preimage (hash) // - the signature preimage (hash)
func (api *SignerAPI) signTypedData(ctx context.Context, addr common.MixedcaseAddress, func (api *SignerAPI) signTypedData(ctx context.Context, addr common.MixedcaseAddress,
typedData TypedData, validationMessages *ValidationMessages) (hexutil.Bytes, hexutil.Bytes, error) { typedData TypedData, validationMessages *apitypes.ValidationMessages) (hexutil.Bytes, hexutil.Bytes, error) {
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@ -23,14 +23,14 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
// ValidateTransaction does a number of checks on the supplied transaction, and // ValidateTransaction does a number of checks on the supplied transaction, and
// returns either a list of warnings, or an error (indicating that the transaction // returns either a list of warnings, or an error (indicating that the transaction
// should be immediately rejected). // should be immediately rejected).
func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) (*core.ValidationMessages, error) { func (db *Database) ValidateTransaction(selector *string, tx *apitypes.SendTxArgs) (*apitypes.ValidationMessages, error) {
messages := new(core.ValidationMessages) messages := new(apitypes.ValidationMessages)
// Prevent accidental erroneous usage of both 'input' and 'data' (show stopper) // Prevent accidental erroneous usage of both 'input' and 'data' (show stopper)
if tx.Data != nil && tx.Input != nil && !bytes.Equal(*tx.Data, *tx.Input) { if tx.Data != nil && tx.Input != nil && !bytes.Equal(*tx.Data, *tx.Input) {
@ -90,7 +90,7 @@ func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) (
// ValidateCallData checks if the ABI call-data + method selector (if given) can // ValidateCallData checks if the ABI call-data + method selector (if given) can
// be parsed and seems to match. // be parsed and seems to match.
func (db *Database) ValidateCallData(selector *string, data []byte, messages *core.ValidationMessages) { func (db *Database) ValidateCallData(selector *string, data []byte, messages *apitypes.ValidationMessages) {
// If the data is empty, we have a plain value transfer, nothing more to do // If the data is empty, we have a plain value transfer, nothing more to do
if len(data) == 0 { if len(data) == 0 {
return return

View File

@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
func mixAddr(a string) (*common.MixedcaseAddress, error) { func mixAddr(a string) (*common.MixedcaseAddress, error) {
@ -36,7 +36,7 @@ func toHexUint(h string) hexutil.Uint64 {
b := big.NewInt(0).SetBytes(common.FromHex(h)) b := big.NewInt(0).SetBytes(common.FromHex(h))
return hexutil.Uint64(b.Uint64()) return hexutil.Uint64(b.Uint64())
} }
func dummyTxArgs(t txtestcase) *core.SendTxArgs { func dummyTxArgs(t txtestcase) *apitypes.SendTxArgs {
to, _ := mixAddr(t.to) to, _ := mixAddr(t.to)
from, _ := mixAddr(t.from) from, _ := mixAddr(t.from)
n := toHexUint(t.n) n := toHexUint(t.n)
@ -55,7 +55,7 @@ func dummyTxArgs(t txtestcase) *core.SendTxArgs {
input = &a input = &a
} }
return &core.SendTxArgs{ return &apitypes.SendTxArgs{
From: *from, From: *from,
To: to, To: to,
Value: value, Value: value,

View File

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"
) )
@ -180,7 +181,7 @@ func TestSignTxRequest(t *testing.T) {
} }
t.Logf("to %v", to.Address().String()) t.Logf("to %v", to.Address().String())
resp, err := r.ApproveTx(&core.SignTxRequest{ resp, err := r.ApproveTx(&core.SignTxRequest{
Transaction: core.SendTxArgs{ Transaction: apitypes.SendTxArgs{
From: *from, From: *from,
To: to}, To: to},
Callinfo: nil, Callinfo: nil,
@ -432,7 +433,7 @@ func dummyTx(value hexutil.Big) *core.SignTxRequest {
gasPrice := hexutil.Big(*big.NewInt(2000000)) gasPrice := hexutil.Big(*big.NewInt(2000000))
return &core.SignTxRequest{ return &core.SignTxRequest{
Transaction: core.SendTxArgs{ Transaction: apitypes.SendTxArgs{
From: *from, From: *from,
To: to, To: to,
Value: value, Value: value,
@ -440,7 +441,7 @@ func dummyTx(value hexutil.Big) *core.SignTxRequest {
GasPrice: &gasPrice, GasPrice: &gasPrice,
Gas: gas, Gas: gas,
}, },
Callinfo: []core.ValidationInfo{ Callinfo: []apitypes.ValidationInfo{
{Typ: "Warning", Message: "All your base are bellong to us"}, {Typ: "Warning", Message: "All your base are bellong to us"},
}, },
Meta: core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"}, Meta: core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},