mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
Merge 409ebf035b into 12eabbd76d
This commit is contained in:
commit
cbaf70a1f4
3 changed files with 222 additions and 17 deletions
|
|
@ -498,19 +498,21 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
||||||
modified = true
|
modified = true
|
||||||
log.Info("Value changed by UI", "was", v0, "is", v1)
|
log.Info("Value changed by UI", "was", v0, "is", v1)
|
||||||
}
|
}
|
||||||
if d0, d1 := original.Transaction.Data, new.Transaction.Data; d0 != d1 {
|
// Compare effective calldata (prefer Input over Data)
|
||||||
d0s := ""
|
var oldData, newData []byte
|
||||||
d1s := ""
|
if original.Transaction.Input != nil {
|
||||||
if d0 != nil {
|
oldData = *original.Transaction.Input
|
||||||
d0s = hexutil.Encode(*d0)
|
} else if original.Transaction.Data != nil {
|
||||||
}
|
oldData = *original.Transaction.Data
|
||||||
if d1 != nil {
|
}
|
||||||
d1s = hexutil.Encode(*d1)
|
if new.Transaction.Input != nil {
|
||||||
}
|
newData = *new.Transaction.Input
|
||||||
if d1s != d0s {
|
} else if new.Transaction.Data != nil {
|
||||||
modified = true
|
newData = *new.Transaction.Data
|
||||||
log.Info("Data changed by UI", "was", d0s, "is", d1s)
|
}
|
||||||
}
|
if !bytes.Equal(oldData, newData) {
|
||||||
|
modified = true
|
||||||
|
log.Info("Data changed by UI", "was", hexutil.Encode(oldData), "is", hexutil.Encode(newData))
|
||||||
}
|
}
|
||||||
if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 {
|
if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 {
|
||||||
modified = true
|
modified = true
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -142,10 +143,32 @@ func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, erro
|
||||||
fmt.Printf(" %v\n", bh)
|
fmt.Printf(" %v\n", bh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.Transaction.Data != nil {
|
{
|
||||||
d := *request.Transaction.Data
|
var (
|
||||||
if len(d) > 0 {
|
data []byte
|
||||||
fmt.Printf("data: %v\n", hexutil.Encode(d))
|
inputSet bool
|
||||||
|
dataSet bool
|
||||||
|
)
|
||||||
|
if request.Transaction.Input != nil {
|
||||||
|
data = *request.Transaction.Input
|
||||||
|
inputSet = true
|
||||||
|
}
|
||||||
|
if request.Transaction.Data != nil {
|
||||||
|
dataSet = true
|
||||||
|
if !inputSet {
|
||||||
|
data = *request.Transaction.Data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inputSet && dataSet && !bytes.Equal(*request.Transaction.Input, *request.Transaction.Data) {
|
||||||
|
fmt.Printf("input: %v\n", hexutil.Encode(*request.Transaction.Input))
|
||||||
|
fmt.Printf("data: %v\n", hexutil.Encode(*request.Transaction.Data))
|
||||||
|
fmt.Printf("WARNING: both input and data provided and differ; input will be used\n")
|
||||||
|
} else if len(data) > 0 {
|
||||||
|
label := "data"
|
||||||
|
if inputSet {
|
||||||
|
label = "input"
|
||||||
|
}
|
||||||
|
fmt.Printf("%s: %v\n", label, hexutil.Encode(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.Callinfo != nil {
|
if request.Callinfo != nil {
|
||||||
|
|
|
||||||
180
signer/core/cliui_calldata_test.go
Normal file
180
signer/core/cliui_calldata_test.go
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func captureOutput(t *testing.T, fn func()) string {
|
||||||
|
t.Helper()
|
||||||
|
old := os.Stdout
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("pipe error: %v", err)
|
||||||
|
}
|
||||||
|
os.Stdout = w
|
||||||
|
var buf bytes.Buffer
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
_, _ = buf.ReadFrom(r)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
fn()
|
||||||
|
_ = w.Close()
|
||||||
|
<-done
|
||||||
|
os.Stdout = old
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApproveTx_DisplaysEffectiveCalldata(t *testing.T) {
|
||||||
|
mkUI := func(input string) *CommandlineUI {
|
||||||
|
return &CommandlineUI{in: bufio.NewReader(strings.NewReader(input))}
|
||||||
|
}
|
||||||
|
hex := func(b []byte) string { return hexutil.Encode(b) }
|
||||||
|
// helper to create *hexutil.Bytes
|
||||||
|
hx := func(b []byte) *hexutil.Bytes { v := hexutil.Bytes(b); return &v }
|
||||||
|
// zero 1559 fee fields to avoid GasPrice nil deref in CLI
|
||||||
|
zeroFee := func(a *apitypes.SendTxArgs) {
|
||||||
|
z := new(hexutil.Big)
|
||||||
|
a.MaxFeePerGas = z
|
||||||
|
a.MaxPriorityFeePerGas = z
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
args apitypes.SendTxArgs
|
||||||
|
wantContains []string
|
||||||
|
wantNotExists []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "only input",
|
||||||
|
args: func() apitypes.SendTxArgs {
|
||||||
|
a := apitypes.SendTxArgs{Input: hx([]byte{0x01, 0x02})}
|
||||||
|
zeroFee(&a)
|
||||||
|
return a
|
||||||
|
}(),
|
||||||
|
wantContains: []string{
|
||||||
|
"input:",
|
||||||
|
hex([]byte{0x01, 0x02}),
|
||||||
|
},
|
||||||
|
wantNotExists: []string{"WARNING: both input and data provided and differ"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only data",
|
||||||
|
args: func() apitypes.SendTxArgs { a := apitypes.SendTxArgs{Data: hx([]byte{0x0a})}; zeroFee(&a); return a }(),
|
||||||
|
wantContains: []string{
|
||||||
|
"data:",
|
||||||
|
hex([]byte{0x0a}),
|
||||||
|
},
|
||||||
|
wantNotExists: []string{"WARNING: both input and data provided and differ"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both equal",
|
||||||
|
args: func() apitypes.SendTxArgs {
|
||||||
|
b := hexutil.Bytes([]byte{0xaa, 0xbb})
|
||||||
|
a := apitypes.SendTxArgs{Input: &b, Data: &b}
|
||||||
|
zeroFee(&a)
|
||||||
|
return a
|
||||||
|
}(),
|
||||||
|
wantContains: []string{
|
||||||
|
"input:",
|
||||||
|
hex([]byte{0xaa, 0xbb}),
|
||||||
|
},
|
||||||
|
wantNotExists: []string{"WARNING: both input and data provided and differ", "data:"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both different",
|
||||||
|
args: func() apitypes.SendTxArgs {
|
||||||
|
a := apitypes.SendTxArgs{Input: hx([]byte{0x01}), Data: hx([]byte{0x02})}
|
||||||
|
zeroFee(&a)
|
||||||
|
return a
|
||||||
|
}(),
|
||||||
|
wantContains: []string{
|
||||||
|
"input:",
|
||||||
|
"data:",
|
||||||
|
"WARNING: both input and data provided and differ",
|
||||||
|
hex([]byte{0x01}),
|
||||||
|
hex([]byte{0x02}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ui := mkUI("y\n")
|
||||||
|
req := &SignTxRequest{Transaction: tc.args}
|
||||||
|
out := captureOutput(t, func() {
|
||||||
|
_, err := ui.ApproveTx(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ApproveTx error: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, s := range tc.wantContains {
|
||||||
|
if !strings.Contains(out, s) {
|
||||||
|
t.Fatalf("output does not contain %q. Output:\n%s", s, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, s := range tc.wantNotExists {
|
||||||
|
if strings.Contains(out, s) {
|
||||||
|
t.Fatalf("output should not contain %q. Output:\n%s", s, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogDiff_EffectiveCalldata(t *testing.T) {
|
||||||
|
mk := func(inOld, dataOld, inNew, dataNew []byte) (SignTxRequest, SignTxResponse) {
|
||||||
|
var (
|
||||||
|
inO, dO, inN, dN *hexutil.Bytes
|
||||||
|
)
|
||||||
|
if inOld != nil {
|
||||||
|
v := hexutil.Bytes(inOld)
|
||||||
|
inO = &v
|
||||||
|
}
|
||||||
|
if dataOld != nil {
|
||||||
|
v := hexutil.Bytes(dataOld)
|
||||||
|
dO = &v
|
||||||
|
}
|
||||||
|
if inNew != nil {
|
||||||
|
v := hexutil.Bytes(inNew)
|
||||||
|
inN = &v
|
||||||
|
}
|
||||||
|
if dataNew != nil {
|
||||||
|
v := hexutil.Bytes(dataNew)
|
||||||
|
dN = &v
|
||||||
|
}
|
||||||
|
return SignTxRequest{Transaction: apitypes.SendTxArgs{Input: inO, Data: dO}}, SignTxResponse{Transaction: apitypes.SendTxArgs{Input: inN, Data: dN}}
|
||||||
|
}
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
inOld []byte
|
||||||
|
dataOld []byte
|
||||||
|
inNew []byte
|
||||||
|
dataNew []byte
|
||||||
|
modified bool
|
||||||
|
}{
|
||||||
|
{"only input unchanged", []byte{0x01}, nil, []byte{0x01}, nil, false},
|
||||||
|
{"only data unchanged", nil, []byte{0x02}, nil, []byte{0x02}, false},
|
||||||
|
{"both equal unchanged", []byte{0x0a}, []byte{0x0a}, []byte{0x0a}, []byte{0x0a}, false},
|
||||||
|
{"effective changed (input differs)", []byte{0x01}, nil, []byte{0x02}, nil, true},
|
||||||
|
{"effective changed (data differs, no input)", nil, []byte{0x01}, nil, []byte{0x02}, true},
|
||||||
|
{"effective equal though underlying fields differ", []byte{0xaa}, []byte{0xbb}, []byte{0xaa}, []byte{0xbb}, false},
|
||||||
|
{"both set but only new input changes", []byte{0x01}, []byte{0x01}, []byte{0x02}, []byte{0x01}, true},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
orig, nw := mk(tc.inOld, tc.dataOld, tc.inNew, tc.dataNew)
|
||||||
|
m := logDiff(&orig, &nw)
|
||||||
|
if m != tc.modified {
|
||||||
|
t.Fatalf("modified mismatch: have %v want %v", m, tc.modified)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue