Skip to content
This repository was archived by the owner on May 13, 2022. It is now read-only.

Commit f8aa2d5

Browse files
author
Silas Davis
committed
Fix ABI Address packing issue and error swallowing
- Burrow deploy was swallowing errors in multiple playbook runs - 0.29.8 ABI fix accidentally removed support for hex string addresses - corrected! - Make console logging look more reasonable - Fix ability to call fallback function Signed-off-by: Silas Davis <[email protected]>
1 parent 69b2160 commit f8aa2d5

File tree

12 files changed

+100
-63
lines changed

12 files changed

+100
-63
lines changed

cmd/burrow/commands/deploy.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/hyperledger/burrow/deploy/def"
1212
"github.com/hyperledger/burrow/deploy/proposals"
1313
"github.com/hyperledger/burrow/logging"
14+
"github.com/hyperledger/burrow/logging/loggers"
1415
cli "github.com/jawher/mow.cli"
1516
)
1617

@@ -34,9 +35,6 @@ func Deploy(output Output) func(cmd *cli.Cmd) {
3435
defaultOutputOpt := cmd.StringOpt("o output", def.DefaultOutputFile,
3536
"filename for playbook output file. by default, this name will reflect the playbook passed")
3637

37-
playbooksOpt := cmd.StringsArg("FILE", []string{},
38-
"path to playbook file which deploy should run. if also using the --dir flag, give the relative path to playbooks file, which should be in the same directory")
39-
4038
defaultSetsOpt := cmd.StringsOpt("e set", []string{},
4139
"default sets to use; operates the same way as the [set] jobs, only before the jobs file is ran (and after default address")
4240

@@ -75,6 +73,9 @@ func Deploy(output Output) func(cmd *cli.Cmd) {
7573

7674
proposalList := cmd.StringOpt("list-proposals state", "", "List proposals, either all, executed, expired, or current")
7775

76+
playbooksArg := cmd.StringsArg("FILE", []string{},
77+
"path to playbook file which deploy should run. if also using the --dir flag, give the relative path to playbooks file, which should be in the same directory")
78+
7879
cmd.Spec = "[--chain=<host:port>] [--keys=<host:port>] [--mempool-signing] [--dir=<root directory>] " +
7980
"[--output=<output file>] [--wasm] [--set=<KEY=VALUE>]... [--bin-path=<path>] [--gas=<gas>] " +
8081
"[--jobs=<concurrent playbooks>] [--address=<address>] [--fee=<fee>] [--amount=<amount>] [--local-abi] " +
@@ -115,7 +116,10 @@ func Deploy(output Output) func(cmd *cli.Cmd) {
115116
args.ProposeVerify = *proposalVerify
116117
args.ProposeVote = *proposalVote
117118
args.ProposeCreate = *proposalCreate
118-
stderrLogger := log.NewLogfmtLogger(os.Stderr)
119+
stderrLogger, err := loggers.NewStreamLogger(os.Stderr, loggers.TerminalFormat)
120+
if err != nil {
121+
output.Fatalf("Could not make logger: %v", err)
122+
}
119123
logger := logging.NewLogger(stderrLogger)
120124
handleTerm()
121125

@@ -133,10 +137,10 @@ func Deploy(output Output) func(cmd *cli.Cmd) {
133137
output.Fatalf(err.Error())
134138
}
135139
} else {
136-
if len(*playbooksOpt) == 0 {
140+
if len(*playbooksArg) == 0 {
137141
output.Fatalf("incorrect usage: missing deployment yaml file(s)")
138142
}
139-
failures, err := pkgs.RunPlaybooks(args, *playbooksOpt, logger)
143+
failures, err := pkgs.RunPlaybooks(args, *playbooksArg, logger)
140144
if err != nil {
141145
fmt.Fprintln(os.Stderr, err)
142146
os.Exit(1)

deploy/def/jobs.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package def
22

33
import (
4+
"fmt"
45
"regexp"
56

67
validation "github.com/go-ozzo/ozzo-validation"
@@ -405,6 +406,11 @@ type Call struct {
405406
Variables []*abi.Variable
406407
}
407408

409+
// TODO: maybe do for others...
410+
func (job *Call) String() string {
411+
return fmt.Sprintf("%#v", job)
412+
}
413+
408414
func (job *Call) Validate() error {
409415
return validation.ValidateStruct(job,
410416
validation.Field(&job.Destination, validation.Required),

deploy/jobs/jobs_contracts.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ import (
77
"strings"
88

99
"github.com/hyperledger/burrow/acm/acmstate"
10-
"github.com/hyperledger/burrow/execution/errors"
11-
"github.com/hyperledger/burrow/execution/exec"
12-
"github.com/hyperledger/burrow/logging"
13-
1410
"github.com/hyperledger/burrow/crypto"
1511
compilers "github.com/hyperledger/burrow/deploy/compile"
1612
"github.com/hyperledger/burrow/deploy/def"
1713
"github.com/hyperledger/burrow/deploy/util"
14+
"github.com/hyperledger/burrow/execution/errors"
1815
"github.com/hyperledger/burrow/execution/evm/abi"
16+
"github.com/hyperledger/burrow/execution/exec"
17+
"github.com/hyperledger/burrow/logging"
1918
"github.com/hyperledger/burrow/txs/payload"
2019
hex "github.com/tmthrgd/go-hex"
2120
)
@@ -431,6 +430,7 @@ func FormulateCallJob(call *def.Call, do *def.DeployArgs, deployScript *def.Play
431430
if err != nil {
432431
return nil, err
433432
}
433+
434434
// Use default
435435
call.Source = FirstOf(call.Source, deployScript.Account)
436436
call.Amount = FirstOf(call.Amount, do.DefaultAmount)

deploy/run_deploy.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,18 @@ func RunPlaybooks(args *def.DeployArgs, playbooks []string, logger *logging.Logg
112112
successes := 0
113113

114114
for range playbooks {
115+
// Receive results as they come
115116
jobResult := <-resultQ
116117
results[jobResult.jobNo] = &jobResult
118+
// Print them in order
117119
for results[printed] != nil {
118120
res := results[printed]
119121
os.Stderr.Write(res.log.Bytes())
120122
if res.err != nil {
121-
fmt.Fprintf(os.Stderr, "ERROR: %v", res.err)
123+
fmt.Fprintf(os.Stderr, "Error in RunPlaybooks: %v\n", res.err)
122124
}
123125
res.log.Truncate(0)
124-
if jobResult.err != nil {
126+
if res.err != nil {
125127
failures++
126128
} else {
127129
successes++
@@ -135,7 +137,7 @@ func RunPlaybooks(args *def.DeployArgs, playbooks []string, logger *logging.Logg
135137
close(resultQ)
136138

137139
if successes > 0 {
138-
logger.InfoMsg("JOBS THAT SUCCEEEDED", "count", successes)
140+
logger.InfoMsg("JOBS THAT SUCCEEDED", "count", successes)
139141
for i, playbook := range playbooks {
140142
res := results[i]
141143
if res.err != nil {

deploy/util/variables.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,10 @@ func replaceBlockVariable(toReplace string, client *def.Client, logger *logging.
195195
func PreProcessInputData(function string, data interface{}, do *def.DeployArgs, script *def.Playbook, client *def.Client, constructor bool, logger *logging.Logger) (string, []interface{}, error) {
196196
var callDataArray []interface{}
197197
var callArray []string
198-
if function == "" && !constructor {
199-
if reflect.TypeOf(data).Kind() == reflect.Slice {
200-
return "", []interface{}{""}, fmt.Errorf("Incorrect formatting of deploy.yaml. Please update it to include a function field.")
201-
}
202-
function = strings.Split(data.(string), " ")[0]
203-
callArray = strings.Split(data.(string), " ")[1:]
198+
if _, ok := data.(string); function == "" && !constructor && ok {
199+
callArray = strings.Split(data.(string), " ")
200+
function = callArray[0]
201+
callArray = callArray[1:]
204202
for _, val := range callArray {
205203
output, _ := PreProcess(val, do, script, client, logger)
206204
callDataArray = append(callDataArray, output)

docker-compose.yml

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ version: "3"
22
services:
33
db:
44
image: postgres:11-alpine
5+
environment:
6+
- POSTGRES_HOST_AUTH_METHOD=trust
57
ports:
68
- 5432
79
environment:

execution/evm/abi/abi_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ func TestPacker(t *testing.T) {
2626
name string
2727
expectedOutput []byte
2828
}{
29+
// Test string address
30+
{
31+
`[{"constant":false,"inputs":[{"internalType":"address payable","name":"friend","type":"address"}],"name":"sendToAFriend","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}]`,
32+
[]interface{}{"C42DEED84BDF2CA695F2E91F4E6395D191CF35FC"},
33+
"sendToAFriend",
34+
pad([]byte{196, 45, 238, 216, 75, 223, 44, 166, 149, 242, 233, 31, 78, 99, 149, 209, 145, 207, 53, 252}, 32, true),
35+
},
2936
// From: https://github.com/hyperledger/burrow/issues/1326
3037
{
3138
`[{"constant":false,"inputs":[{"internalType":"address payable","name":"friend","type":"address"}],"name":"sendToAFriend","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}]`,

execution/evm/abi/primitives.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,16 @@ func (e EVMAddress) pack(v interface{}) ([]byte, error) {
520520
bs = a[:]
521521
case *crypto.Address:
522522
bs = (*a)[:]
523+
case string:
524+
address, err := crypto.AddressFromHexString(a)
525+
if err != nil {
526+
return nil, fmt.Errorf("could not convert '%s' to address: %v", a, err)
527+
}
528+
bs = address[:]
523529
case []byte:
524530
address, err := crypto.AddressFromBytes(a)
525531
if err != nil {
526-
return nil, err
532+
return nil, fmt.Errorf("could not convert byte 0x%X to address: %v", a, err)
527533
}
528534
bs = address[:]
529535
default:

execution/evm/abi/spec.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010
"github.com/hyperledger/burrow/crypto"
1111
)
1212

13+
// Token to use in deploy yaml in order to indicate call to the fallback function.
14+
const FallbackFunctionName = "()"
15+
1316
// Spec is the ABI for contract decoded.
1417
type Spec struct {
1518
Constructor *FunctionSpec
@@ -69,6 +72,8 @@ func ReadSpec(specBytes []byte) (*Spec, error) {
6972
case "fallback":
7073
abiSpec.Fallback.Inputs = make([]Argument, 0)
7174
abiSpec.Fallback.Outputs = make([]Argument, 0)
75+
abiSpec.Fallback.SetConstant()
76+
abiSpec.Functions[FallbackFunctionName] = abiSpec.Fallback
7277
case "event":
7378
ev := new(EventSpec)
7479
err = ev.unmarshalSpec(&s)
@@ -136,13 +141,13 @@ func (spec *Spec) Pack(fname string, args ...interface{}) ([]byte, *FunctionSpec
136141
if _, ok := spec.Functions[fname]; ok {
137142
funcSpec = spec.Functions[fname]
138143
} else {
139-
return nil, nil, fmt.Errorf("Unknown function %s", fname)
144+
return nil, nil, fmt.Errorf("unknown function in Pack: %s", fname)
140145
}
141146
} else {
142147
if spec.Constructor.Inputs != nil {
143148
funcSpec = spec.Constructor
144149
} else {
145-
return nil, nil, fmt.Errorf("Contract does not have a constructor")
150+
return nil, nil, fmt.Errorf("contract does not have a constructor")
146151
}
147152
}
148153

@@ -179,7 +184,7 @@ func (spec *Spec) Unpack(data []byte, fname string, args ...interface{}) error {
179184
argSpec = funcSpec.Outputs
180185

181186
if argSpec == nil {
182-
return fmt.Errorf("Unknown function %s", fname)
187+
return fmt.Errorf("unknown function in Unpack: %s", fname)
183188
}
184189

185190
return unpack(argSpec, data, func(i int) interface{} {
@@ -199,7 +204,7 @@ func (spec *Spec) UnpackWithID(data []byte, args ...interface{}) error {
199204
}
200205

201206
if argSpec == nil {
202-
return fmt.Errorf("Unknown function %x", id)
207+
return fmt.Errorf("unknown function in UnpackWithID: %x", id)
203208
}
204209

205210
return unpack(argSpec, data[4:], func(i int) interface{} {

logging/loggers/stream_logger.go

+44-30
Original file line numberDiff line numberDiff line change
@@ -15,56 +15,70 @@ type Syncable interface {
1515
}
1616

1717
func NewStreamLogger(writer io.Writer, format string) (log.Logger, error) {
18-
var logger log.Logger
19-
var err error
2018
switch format {
2119
case "":
2220
return NewStreamLogger(writer, DefaultFormat)
2321
case JSONFormat:
24-
logger = log.NewJSONLogger(writer)
22+
return NewJSONLogger(writer), nil
2523
case LogfmtFormat:
26-
logger = log.NewLogfmtLogger(writer)
24+
return NewLogfmtLogger(writer), nil
2725
case TerminalFormat:
28-
logger = term.NewLogger(writer, log.NewLogfmtLogger, func(keyvals ...interface{}) term.FgBgColor {
29-
switch structure.Value(keyvals, structure.ChannelKey) {
30-
case structure.TraceChannelName:
31-
return term.FgBgColor{Fg: term.DarkGreen}
32-
default:
33-
return term.FgBgColor{Fg: term.Yellow}
34-
}
35-
})
26+
return NewTerminalLogger(writer), nil
3627
default:
37-
logger, err = NewTemplateLogger(writer, format, []byte{})
38-
if err != nil {
39-
return nil, fmt.Errorf("did not recognise format '%s' as named format and could not parse as "+
40-
"template: %v", format, err)
41-
}
28+
return NewTemplateLogger(writer, format, []byte{})
4229
}
43-
return log.LoggerFunc(func(keyvals ...interface{}) error {
44-
switch structure.Signal(keyvals) {
45-
case structure.SyncSignal:
46-
if s, ok := writer.(Syncable); ok {
47-
return s.Sync()
48-
}
49-
// Don't log signals
50-
return nil
30+
}
31+
32+
func NewJSONLogger(writer io.Writer) log.Logger {
33+
return interceptSync(writer, log.NewJSONLogger(writer))
34+
}
35+
36+
func NewLogfmtLogger(writer io.Writer) log.Logger {
37+
return interceptSync(writer, log.NewLogfmtLogger(writer))
38+
}
39+
40+
func NewTerminalLogger(writer io.Writer) log.Logger {
41+
logger := term.NewLogger(writer, log.NewLogfmtLogger, func(keyvals ...interface{}) term.FgBgColor {
42+
kvm := structure.KeyValuesMap(keyvals)
43+
delete(kvm, structure.TraceChannelName)
44+
delete(kvm, structure.MessageKey)
45+
delete(kvm, structure.TimeKey)
46+
switch structure.Value(keyvals, structure.ChannelKey) {
47+
case structure.TraceChannelName:
48+
return term.FgBgColor{Fg: term.DarkGreen}
5149
default:
52-
return logger.Log(keyvals...)
50+
return term.FgBgColor{Fg: term.Yellow}
5351
}
54-
}), nil
52+
})
53+
return interceptSync(writer, logger)
5554
}
5655

5756
func NewTemplateLogger(writer io.Writer, textTemplate string, recordSeparator []byte) (log.Logger, error) {
5857
tmpl, err := template.New("template-logger").Parse(textTemplate)
5958
if err != nil {
60-
return nil, err
59+
return nil, fmt.Errorf("could not parse '%s' as a text template: %v", textTemplate, err)
6160
}
62-
return log.LoggerFunc(func(keyvals ...interface{}) error {
61+
logger := log.LoggerFunc(func(keyvals ...interface{}) error {
6362
err := tmpl.Execute(writer, structure.KeyValuesMap(keyvals))
6463
if err == nil {
6564
_, err = writer.Write(recordSeparator)
6665
}
6766
return err
68-
}), nil
67+
})
68+
return interceptSync(writer, logger), nil
69+
}
6970

71+
func interceptSync(writer io.Writer, logger log.Logger) log.Logger {
72+
return log.LoggerFunc(func(keyvals ...interface{}) error {
73+
switch structure.Signal(keyvals) {
74+
case structure.SyncSignal:
75+
if s, ok := writer.(Syncable); ok {
76+
return s.Sync()
77+
}
78+
// Don't log signals
79+
return nil
80+
default:
81+
return logger.Log(keyvals...)
82+
}
83+
})
7084
}

tests/jobs_fixtures/app37-fallback_function/deploy.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
- name: getX
1212
query-contract:
1313
destination: $deployC
14-
function: x
14+
function: x
1515

1616
- name: assertLevelUp
1717
assert:
1818
key: $getX
1919
relation: eq
20-
val: 1
20+
val: 1

tests/test_runner.sh

-7
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ export boot=${boot:-true}
2525
export debug=${debug:-false}
2626
export clean=${clean:-true}
2727

28-
export failures="not supplied by test"
29-
3028
export test_exit=0
3129

3230
if [[ "$debug" = true ]]; then
@@ -114,11 +112,6 @@ test_teardown(){
114112
echo "Tests complete! Tests are Green. :)"
115113
else
116114
echo "Tests complete. Tests are Red. :("
117-
echo "Failures in:"
118-
for failure in "${failures[@]}"
119-
do
120-
echo "$failure"
121-
done
122115
fi
123116
exit ${test_exit}
124117
}

0 commit comments

Comments
 (0)