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

Commit dbfe3c6

Browse files
committed
Add wasm printMem and other debug functions
Signed-off-by: Sean Young <[email protected]>
1 parent b64774e commit dbfe3c6

23 files changed

+944
-110
lines changed

deploy/jobs/jobs_contracts.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,17 @@ func deployFinalize(client *def.Client, tx payload.Payload, logger *logging.Logg
574574
}
575575

576576
func logEvents(txe *exec.TxExecution, client *def.Client, logger *logging.Logger) {
577-
if client.AllSpecs == nil {
578-
return
579-
}
580-
581577
for _, event := range txe.Events {
578+
print := event.GetPrint()
579+
580+
if print != nil {
581+
logger.InfoMsg("print", "address", print.Address.String(), "msg", string(print.Data))
582+
continue
583+
}
584+
582585
eventLog := event.GetLog()
583586

584-
if eventLog == nil {
587+
if eventLog == nil || client.AllSpecs == nil {
585588
continue
586589
}
587590

deploy/jobs/jobs_test_jobs.go

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ func QueryContractJob(query *def.QueryContract, do *def.DeployArgs, script *def.
6969
return "", nil, err
7070
}
7171

72+
logEvents(txe, client, logger)
73+
7274
result2 := util.GetReturnValue(query.Variables, logger)
7375
// Finalize
7476
if result2 != "" {

execution/exec/event.go

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
TypeEnvelope
2525
TypeEndTx
2626
TypeEndBlock
27+
TypePrint
2728
)
2829

2930
var nameFromType = map[EventType]string{

execution/exec/event_sink.go

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
type EventSink interface {
88
Call(call *CallEvent, exception *errors.Exception) error
99
Log(log *LogEvent) error
10+
Print(print *PrintEvent) error
1011
}
1112

1213
type noopEventSink struct {
@@ -24,6 +25,10 @@ func (es *noopEventSink) Log(log *LogEvent) error {
2425
return nil
2526
}
2627

28+
func (es *noopEventSink) Print(print *PrintEvent) error {
29+
return nil
30+
}
31+
2732
type logFreeEventSink struct {
2833
EventSink
2934
}

execution/exec/events.go

+11
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ func (evs *Events) Log(log *LogEvent) error {
4444
return nil
4545
}
4646

47+
func (evs *Events) Print(print *PrintEvent) error {
48+
evs.Append(&Event{
49+
Header: &Header{
50+
EventType: TypePrint,
51+
EventID: EventStringLogEvent(print.Address),
52+
},
53+
Print: print,
54+
})
55+
return nil
56+
}
57+
4758
func (evs Events) CallTrace() string {
4859
var calls []string
4960
for _, ev := range evs {

execution/exec/exec.pb.go

+374-85
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

execution/exec/stream_event.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ func (ev *StreamEvent) EventType() EventType {
3535
return TypeEndTx
3636
case ev.EndBlock != nil:
3737
return TypeEndBlock
38+
case ev.Event.Print != nil:
39+
return TypePrint
3840
}
3941
return TypeUnknown
4042
}

execution/exec/tx_execution.go

+8
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ func (txe *TxExecution) GovernAccount(governAccount *GovernAccountEvent, excepti
128128
})
129129
}
130130

131+
func (txe *TxExecution) Print(print *PrintEvent) error {
132+
txe.Append(&Event{
133+
Header: txe.Header(TypePrint, EventStringLogEvent(print.Address), nil),
134+
Print: print,
135+
})
136+
return nil
137+
}
138+
131139
// Errors pushed to TxExecutions end up in merkle state so it is essential that they are deterministic and independent
132140
// of the code path taken to execution (e.g. replay takes a different path to that of normal consensus reactor so stack
133141
// traces may differ - as they may across architectures)

execution/solidity/ewasm.solang

+4
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,8 @@ contract ewasm is E {
4848
function test_events() public {
4949
emit L(102, "Hello from wasm", true);
5050
}
51+
52+
function test_print(int64 arg1, string arg2) public {
53+
print("arg1:{} arg2:{}".format(arg1, arg2));
54+
}
5155
}

execution/solidity/ewasm.solang.go

+2-2
Large diffs are not rendered by default.

execution/wasm/contract.go

+136
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"math/big"
77

8+
hex "github.com/tmthrgd/go-hex"
9+
810
"github.com/hyperledger/burrow/execution/evm"
911
"github.com/hyperledger/burrow/execution/exec"
1012

@@ -79,6 +81,140 @@ func (ctx *context) ResolveGlobal(module, field string) int64 {
7981
}
8082

8183
func (ctx *context) ResolveFunc(module, field string) lifeExec.FunctionImport {
84+
if module == "debug" {
85+
// See https://github.com/ewasm/hera#interfaces
86+
switch field {
87+
case "print32":
88+
return func(vm *lifeExec.VirtualMachine) int64 {
89+
n := int32(vm.GetCurrentFrame().Locals[0])
90+
91+
s := fmt.Sprintf("%d", n)
92+
93+
err := ctx.state.EventSink.Print(&exec.PrintEvent{
94+
Address: ctx.params.Callee,
95+
Data: []byte(s),
96+
})
97+
98+
if err != nil {
99+
panic(fmt.Sprintf(" => print32 failed: %v", err))
100+
}
101+
102+
return Success
103+
}
104+
105+
case "print64":
106+
return func(vm *lifeExec.VirtualMachine) int64 {
107+
n := int64(vm.GetCurrentFrame().Locals[0])
108+
109+
s := fmt.Sprintf("%d", n)
110+
111+
err := ctx.state.EventSink.Print(&exec.PrintEvent{
112+
Address: ctx.params.Callee,
113+
Data: []byte(s),
114+
})
115+
116+
if err != nil {
117+
panic(fmt.Sprintf(" => print32 failed: %v", err))
118+
}
119+
120+
return Success
121+
}
122+
123+
case "printMem":
124+
return func(vm *lifeExec.VirtualMachine) int64 {
125+
dataPtr := int(uint32(vm.GetCurrentFrame().Locals[0]))
126+
dataLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
127+
128+
s := vm.Memory[dataPtr : dataPtr+dataLen]
129+
130+
err := ctx.state.EventSink.Print(&exec.PrintEvent{
131+
Address: ctx.params.Callee,
132+
Data: s,
133+
})
134+
135+
if err != nil {
136+
panic(fmt.Sprintf(" => printMem failed: %v", err))
137+
}
138+
139+
return Success
140+
}
141+
142+
case "printMemHex":
143+
return func(vm *lifeExec.VirtualMachine) int64 {
144+
dataPtr := int(uint32(vm.GetCurrentFrame().Locals[0]))
145+
dataLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
146+
147+
s := hex.EncodeToString(vm.Memory[dataPtr : dataPtr+dataLen])
148+
149+
err := ctx.state.EventSink.Print(&exec.PrintEvent{
150+
Address: ctx.params.Callee,
151+
Data: []byte(s),
152+
})
153+
154+
if err != nil {
155+
panic(fmt.Sprintf(" => printMemHex failed: %v", err))
156+
}
157+
158+
return Success
159+
}
160+
161+
case "printStorage":
162+
return func(vm *lifeExec.VirtualMachine) int64 {
163+
keyPtr := int(uint32(vm.GetCurrentFrame().Locals[0]))
164+
165+
key := bin.Word256{}
166+
167+
copy(key[:], vm.Memory[keyPtr:keyPtr+32])
168+
169+
val, err := ctx.state.GetStorage(ctx.params.Callee, key)
170+
if err != nil {
171+
panic(err)
172+
}
173+
174+
err = ctx.state.EventSink.Print(&exec.PrintEvent{
175+
Address: ctx.params.Callee,
176+
Data: val,
177+
})
178+
179+
if err != nil {
180+
panic(fmt.Sprintf(" => printStorage failed: %v", err))
181+
}
182+
183+
return Success
184+
}
185+
186+
case "printStorageHex":
187+
return func(vm *lifeExec.VirtualMachine) int64 {
188+
keyPtr := int(uint32(vm.GetCurrentFrame().Locals[0]))
189+
190+
key := bin.Word256{}
191+
192+
copy(key[:], vm.Memory[keyPtr:keyPtr+32])
193+
194+
val, err := ctx.state.GetStorage(ctx.params.Callee, key)
195+
if err != nil {
196+
panic(err)
197+
}
198+
199+
s := hex.EncodeToString(val)
200+
201+
err = ctx.state.EventSink.Print(&exec.PrintEvent{
202+
Address: ctx.params.Callee,
203+
Data: []byte(s),
204+
})
205+
206+
if err != nil {
207+
panic(fmt.Sprintf(" => printStorage failed: %v", err))
208+
}
209+
210+
return Success
211+
}
212+
213+
default:
214+
panic(fmt.Sprintf("function %s unknown for debug module", field))
215+
}
216+
}
217+
82218
if module != "ethereum" {
83219
panic(fmt.Sprintf("unknown module %s", module))
84220
}

execution/wasm/storage_test.solang.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package wasm
22

33
import hex "github.com/tmthrgd/go-hex"
44

5-
var Bytecode_storage_test = hex.MustDecodeString("0061736D01000000011C0660027F7F0060017F006000017F60037F7F7F0060017F017F6000000280010608657468657265756D0C73746F7261676553746F7265000008657468657265756D0C67657443616C6C56616C7565000108657468657265756D0B676574436F646553697A65000208657468657265756D08636F6465436F7079000308657468657265756D0666696E697368000008657468657265756D06726576657274000003060500040502050405017001010105030100020608017F01418080040B071102066D656D6F72790200046D61696E000A0AAB0305240002402001450D00034020004200370300200041086A21002001417F6A22010D000B0B0BA60101047F418080042101024003400240200128020C0D002001280208220220004F0D020B200128020022010D000B41002101410028020821020B02402002200041076A41787122036B22024118490D00200120036A41106A22002001280200220436020002402004450D00200420003602040B2000200241706A3602082000410036020C2000200136020420012000360200200120033602080B2001410136020C200141106A0B2E004100410036028080044100410036028480044100410036028C800441003F0041107441F0FF7B6A36028880040B4E01017F230041C0006B22002400200041386A4200370300200042003703302000420037032820004200370320200041041006200042E600370300200041206A20001000200041C0006A240041000B5E01027F230041106B220024002000100102402000290300200041086A290300844200520D0010084100100241C0736A22003602B00741002000100722013602B407200141C00C2000100310091A410041AE071004000B410041001005000B0BB507010041000BAE070061736D01000000011C0660017F006000017F60037F7F7F0060027F7F0060017F017F600000029F010708657468657265756D0C67657443616C6C56616C7565000008657468657265756D0F67657443616C6C4461746153697A65000108657468657265756D0C63616C6C44617461436F7079000208657468657265756D0B73746F726167654C6F6164000308657468657265756D0C73746F7261676553746F7265000308657468657265756D06726576657274000308657468657265756D0666696E697368000303060503020405050405017001010105030100020608017F01418080040B071102066D656D6F72790200046D61696E000B0AB20505240002402001450D00034020004200370300200041086A21002001417F6A22010D000B0B0B2D002001411F6A21010340200120002D00003A00002001417F6A2101200041016A21002002417F6A22020D000B0BA60101047F418080042101024003400240200128020C0D002001280208220220004F0D020B200128020022010D000B41002101410028020821020B02402002200041076A41787122036B22024118490D00200120036A41106A22002001280200220436020002402004450D00200420003602040B2000200241706A3602082000410036020C2000200136020420012000360200200120033602080B2001410136020C200141106A0B2E004100410036028080044100410036028480044100410036028C800441003F0041107441F0FF7B6A36028880040B850302037F017E230041A0016B22002400200041086A100002400240024002402000290308200041106A290300844200520D00100A41001001220136020441002001100922023602082002410020011002200141034D0D014100200228020022013602000240200141A298B6BE01460D00200141DE9AB88F79470D0220004180016A41186A420037030020004200370390012000420037038801200042003703800120004180016A200041E0006A1003200041C0006A41186A420037030020004200370350200042003703482000420037034020002903602103200041206A410410072000200342017C370320200041C0006A200041206A10044100450D03410041001005000B20004198016A420037030020004200370390012000420037038801200042003703800120004180016A200041E0006A10032000200029036042027C3703184100450D03410041001005000B410041001005000B410041001005000B410041001006000B41201009220141041007200041186A200141081008200141201006000B")
5+
var Bytecode_storage_test = hex.MustDecodeString("0061736D01000000011C0660027F7F0060017F006000017F60037F7F7F0060017F017F6000000280010608657468657265756D0C73746F7261676553746F7265000008657468657265756D0C67657443616C6C56616C7565000108657468657265756D0B676574436F646553697A65000208657468657265756D08636F6465436F7079000308657468657265756D0666696E697368000008657468657265756D06726576657274000003060500040502050405017001010105030100020608017F01418080040B071102066D656D6F72790200046D61696E000A0AAB0305240002402001450D00034020004200370300200041086A21002001417F6A22010D000B0B0BA60101047F418080042101024003400240200128020C0D002001280208220220004F0D020B200128020022010D000B41002101410028020821020B02402002200041076A41787122036B22024118490D00200120036A41106A22002001280200220436020002402004450D00200420003602040B2000200241706A3602082000410036020C2000200136020420012000360200200120033602080B2001410136020C200141106A0B2E004100410036028080044100410036028480044100410036028C800441003F0041107441F0FF7B6A36028880040B4E01017F230041C0006B22002400200041386A4200370300200042003703302000420037032820004200370320200041041006200042E600370300200041206A20001000200041C0006A240041000B5E01027F230041106B220024002000100102402000290300200041086A290300844200520D0010084100100241C0736A22003602B00741002000100722013602B407200141C00C2000100310091A410041AE071004000B410041001005000B0BB507010041000BAE070061736D01000000011C0660017F006000017F60037F7F7F0060027F7F0060017F017F600000029F010708657468657265756D0C67657443616C6C56616C7565000008657468657265756D0F67657443616C6C4461746153697A65000108657468657265756D0C63616C6C44617461436F7079000208657468657265756D0B73746F726167654C6F6164000308657468657265756D06726576657274000308657468657265756D0C73746F7261676553746F7265000308657468657265756D0666696E697368000303060503020405050405017001010105030100020608017F01418080040B071102066D656D6F72790200046D61696E000B0AB20505240002402001450D00034020004200370300200041086A21002001417F6A22010D000B0B0B2D002001411F6A21010340200120002D00003A00002001417F6A2101200041016A21002002417F6A22020D000B0BA60101047F418080042101024003400240200128020C0D002001280208220220004F0D020B200128020022010D000B41002101410028020821020B02402002200041076A41787122036B22024118490D00200120036A41106A22002001280200220436020002402004450D00200420003602040B2000200241706A3602082000410036020C2000200136020420012000360200200120033602080B2001410136020C200141106A0B2E004100410036028080044100410036028480044100410036028C800441003F0041107441F0FF7B6A36028880040B850302037F017E230041A0016B22002400200041086A100002400240024002402000290308200041106A290300844200520D00100A41001001220136020441002001100922023602082002410020011002200141034D0D014100200228020022013602000240200141DE9AB88F79460D00200141A298B6BE01470D0220004198016A420037030020004200370390012000420037038801200042003703800120004180016A200041E0006A10032000200029036042027C3703184100450D03410041001004000B20004180016A41186A420037030020004200370390012000420037038801200042003703800120004180016A200041E0006A1003200041C0006A41186A420037030020004200370350200042003703482000420037034020002903602103200041206A410410072000200342017C370320200041C0006A200041206A10054100450D03410041001004000B410041001004000B410041001004000B41201009220141041007200041186A200141081008200141201006000B410041001006000B")
66
var Abi_storage_test = []byte(`[{"type":"constructor","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"getFooPlus2","type":"function","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"name":"incFoo","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}]`)

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,6 @@ require (
5353
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
5454
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
5555
google.golang.org/grpc v1.35.0
56+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 // indirect
5657
gopkg.in/yaml.v2 v2.4.0
5758
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
834834
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
835835
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
836836
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
837+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
838+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
837839
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
838840
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
839841
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

integration/rpctransact/call_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,23 @@ func testCallTx(t *testing.T, kern *core.Kernel, cli rpctransact.TransactClient)
591591
assert.Equal(t, true, f3)
592592
return
593593
})
594+
595+
t.Run("WasmPrint", func(t *testing.T) {
596+
t.Parallel()
597+
createTxe, err := rpctest.CreateWASMContract(cli, inputAddress, solidity.Bytecode_ewasm, nil)
598+
require.NoError(t, err)
599+
address := lastCall(createTxe.Events).CallData.Callee
600+
spec, err := abi.ReadSpec(solidity.Abi_ewasm)
601+
require.NoError(t, err)
602+
data, _, err := spec.Pack("test_print", 102, "Fishy")
603+
require.NoError(t, err)
604+
callTxe, err := rpctest.CallContract(cli, inputAddress, address, data)
605+
require.NoError(t, err)
606+
evs := filterPrint(callTxe.Events)
607+
require.Len(t, evs, 1)
608+
assert.Equal(t, string(evs[0].Data), "arg1:102 arg2:Fishy")
609+
return
610+
})
594611
})
595612
}
596613

@@ -634,6 +651,16 @@ func filterLogs(evs []*exec.Event) []*exec.LogEvent {
634651
return logEvs
635652
}
636653

654+
func filterPrint(evs []*exec.Event) []*exec.PrintEvent {
655+
var printEvs []*exec.PrintEvent
656+
for _, ev := range evs {
657+
if ev.Print != nil {
658+
printEvs = append(printEvs, ev.Print)
659+
}
660+
}
661+
return printEvs
662+
}
663+
637664
func lastCall(evs []*exec.Event) *exec.CallEvent {
638665
callEvs := filterCalls(evs)
639666
return callEvs[len(callEvs)-1]

js/proto/exec_pb.d.ts

+36
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,12 @@ export class Event extends jspb.Message {
511511
setGovernaccount(value?: GovernAccountEvent): Event;
512512

513513

514+
hasPrint(): boolean;
515+
clearPrint(): void;
516+
getPrint(): PrintEvent | undefined;
517+
setPrint(value?: PrintEvent): Event;
518+
519+
514520
serializeBinary(): Uint8Array;
515521
toObject(includeInstance?: boolean): Event.AsObject;
516522
static toObject(includeInstance: boolean, msg: Event): Event.AsObject;
@@ -529,6 +535,7 @@ export namespace Event {
529535
call?: CallEvent.AsObject,
530536
log?: LogEvent.AsObject,
531537
governaccount?: GovernAccountEvent.AsObject,
538+
print?: PrintEvent.AsObject,
532539
}
533540
}
534541

@@ -654,6 +661,35 @@ export namespace CallEvent {
654661
}
655662
}
656663

664+
export class PrintEvent extends jspb.Message {
665+
getAddress(): Uint8Array | string;
666+
getAddress_asU8(): Uint8Array;
667+
getAddress_asB64(): string;
668+
setAddress(value: Uint8Array | string): PrintEvent;
669+
670+
getData(): Uint8Array | string;
671+
getData_asU8(): Uint8Array;
672+
getData_asB64(): string;
673+
setData(value: Uint8Array | string): PrintEvent;
674+
675+
676+
serializeBinary(): Uint8Array;
677+
toObject(includeInstance?: boolean): PrintEvent.AsObject;
678+
static toObject(includeInstance: boolean, msg: PrintEvent): PrintEvent.AsObject;
679+
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
680+
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
681+
static serializeBinaryToWriter(message: PrintEvent, writer: jspb.BinaryWriter): void;
682+
static deserializeBinary(bytes: Uint8Array): PrintEvent;
683+
static deserializeBinaryFromReader(message: PrintEvent, reader: jspb.BinaryReader): PrintEvent;
684+
}
685+
686+
export namespace PrintEvent {
687+
export type AsObject = {
688+
address: Uint8Array | string,
689+
data: Uint8Array | string,
690+
}
691+
}
692+
657693
export class GovernAccountEvent extends jspb.Message {
658694

659695
hasAccountupdate(): boolean;

0 commit comments

Comments
 (0)