From 2899c53a4e37ac3138fbf11861c548a8511702c3 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 24 Dec 2020 10:35:57 +0300 Subject: [PATCH 01/52] New feature #16 "Continuation Transaction" added --- pkg/settings/features.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/settings/features.go b/pkg/settings/features.go index fcfe72e5d..a80e872c2 100644 --- a/pkg/settings/features.go +++ b/pkg/settings/features.go @@ -16,8 +16,9 @@ const ( Ride4DApps // RIDE V3 OrderV3 ReduceNFTFee - BlockReward // 14 - BlockV5 // 15 + BlockReward // 14 + BlockV5 // 15 + ContinuationTransaction // 16 LeaseExpiration ) @@ -42,5 +43,6 @@ var FeaturesInfo = map[Feature]FeatureInfo{ ReduceNFTFee: {true, "Reduce NFT fee"}, BlockReward: {true, "Block Reward and Community Driven Monetary Policy"}, BlockV5: {true, "Ride V4, VRF, Protobuf, Failed transactions"}, + ContinuationTransaction: {true, "Continuation Transaction"}, LeaseExpiration: {false, "Lease Expiration"}, } From 96b3ccf86b06dbf2e83c1ef4e0926f306ab5ca46 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 29 Dec 2020 11:41:37 +0300 Subject: [PATCH 02/52] LeaseScriptAction and LeaseCancelScriptAction (#398) * WIP: New LeaseScriptAction and LeaseCancelScriptAction added, RIDE functions added. * Existing tests restored * ActiveLeases gRPC API method returns new responses * Creation of diffs for Lease and LeaseCancel actions implemented. Uncertain leases storage added. * Error fixed * Tests on Lease and LeaseCancel action application. Protobuf schema udpated. --- pkg/grpc/generated/waves/amount.pb.go | 2 +- pkg/grpc/generated/waves/block.pb.go | 2 +- .../waves/invoke_script_result.pb.go | 389 +++++++++++++----- .../waves/node/grpc/accounts_api.pb.go | 372 +++++++++++------ .../waves/node/grpc/assets_api.pb.go | 2 +- .../waves/node/grpc/blockchain_api.pb.go | 30 +- .../waves/node/grpc/blocks_api.pb.go | 32 +- .../waves/node/grpc/transactions_api.pb.go | 235 ++++++----- pkg/grpc/generated/waves/order.pb.go | 2 +- pkg/grpc/generated/waves/recipient.pb.go | 2 +- pkg/grpc/generated/waves/transaction.pb.go | 2 +- pkg/grpc/protobuf-schemas | 2 +- pkg/grpc/server/accounts_api.go | 45 +- pkg/grpc/server/accounts_api_test.go | 17 +- pkg/proto/protobuf_converters.go | 40 ++ pkg/proto/scripting.go | 107 +++++ pkg/proto/scripting_test.go | 59 +++ pkg/ride/constants.go | 170 ++++---- pkg/ride/converters.go | 37 ++ pkg/ride/functions.go | 35 ++ pkg/ride/functions_generated.go | 60 +-- pkg/ride/functions_proto.go | 173 +++++++- pkg/ride/generate/main.go | 28 +- pkg/ride/selectors.go | 23 +- pkg/ride/tree_estimatorV1.go | 2 + pkg/ride/tree_estimatorV2.go | 2 + pkg/ride/tree_estimatorV3.go | 2 + pkg/ride/tree_evaluation_test.go | 34 ++ pkg/ride/tree_evaluator.go | 4 + pkg/state/invoke_applier.go | 116 +++++- pkg/state/invoke_applier_test.go | 201 ++++++++- pkg/state/invoke_results_test.go | 8 + pkg/state/leases.go | 40 +- pkg/state/state.go | 4 + .../testdata/scripts/ride5_leasing.base64 | 1 + pkg/state/transaction_checker.go | 7 + 36 files changed, 1748 insertions(+), 539 deletions(-) create mode 100644 pkg/state/testdata/scripts/ride5_leasing.base64 diff --git a/pkg/grpc/generated/waves/amount.pb.go b/pkg/grpc/generated/waves/amount.pb.go index 1e493f9b0..dfcd35aa8 100644 --- a/pkg/grpc/generated/waves/amount.pb.go +++ b/pkg/grpc/generated/waves/amount.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/amount.proto package waves diff --git a/pkg/grpc/generated/waves/block.pb.go b/pkg/grpc/generated/waves/block.pb.go index cbf18f54d..1d5c84a8c 100644 --- a/pkg/grpc/generated/waves/block.pb.go +++ b/pkg/grpc/generated/waves/block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/block.proto package waves diff --git a/pkg/grpc/generated/waves/invoke_script_result.pb.go b/pkg/grpc/generated/waves/invoke_script_result.pb.go index 1b0871dfa..c68577dda 100644 --- a/pkg/grpc/generated/waves/invoke_script_result.pb.go +++ b/pkg/grpc/generated/waves/invoke_script_result.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/invoke_script_result.proto package waves @@ -30,13 +30,15 @@ type InvokeScriptResult struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Data []*DataTransactionData_DataEntry `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` - Transfers []*InvokeScriptResult_Payment `protobuf:"bytes,2,rep,name=transfers,proto3" json:"transfers,omitempty"` - Issues []*InvokeScriptResult_Issue `protobuf:"bytes,3,rep,name=issues,proto3" json:"issues,omitempty"` - Reissues []*InvokeScriptResult_Reissue `protobuf:"bytes,4,rep,name=reissues,proto3" json:"reissues,omitempty"` - Burns []*InvokeScriptResult_Burn `protobuf:"bytes,5,rep,name=burns,proto3" json:"burns,omitempty"` - ErrorMessage *InvokeScriptResult_ErrorMessage `protobuf:"bytes,6,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - SponsorFees []*InvokeScriptResult_SponsorFee `protobuf:"bytes,7,rep,name=sponsor_fees,json=sponsorFees,proto3" json:"sponsor_fees,omitempty"` + Data []*DataTransactionData_DataEntry `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` + Transfers []*InvokeScriptResult_Payment `protobuf:"bytes,2,rep,name=transfers,proto3" json:"transfers,omitempty"` + Issues []*InvokeScriptResult_Issue `protobuf:"bytes,3,rep,name=issues,proto3" json:"issues,omitempty"` + Reissues []*InvokeScriptResult_Reissue `protobuf:"bytes,4,rep,name=reissues,proto3" json:"reissues,omitempty"` + Burns []*InvokeScriptResult_Burn `protobuf:"bytes,5,rep,name=burns,proto3" json:"burns,omitempty"` + ErrorMessage *InvokeScriptResult_ErrorMessage `protobuf:"bytes,6,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + SponsorFees []*InvokeScriptResult_SponsorFee `protobuf:"bytes,7,rep,name=sponsor_fees,json=sponsorFees,proto3" json:"sponsor_fees,omitempty"` + Leases []*InvokeScriptResult_Lease `protobuf:"bytes,8,rep,name=leases,proto3" json:"leases,omitempty"` + LeaseCancels []*InvokeScriptResult_LeaseCancel `protobuf:"bytes,9,rep,name=lease_cancels,json=leaseCancels,proto3" json:"lease_cancels,omitempty"` } func (x *InvokeScriptResult) Reset() { @@ -120,6 +122,20 @@ func (x *InvokeScriptResult) GetSponsorFees() []*InvokeScriptResult_SponsorFee { return nil } +func (x *InvokeScriptResult) GetLeases() []*InvokeScriptResult_Lease { + if x != nil { + return x.Leases + } + return nil +} + +func (x *InvokeScriptResult) GetLeaseCancels() []*InvokeScriptResult_LeaseCancel { + if x != nil { + return x.LeaseCancels + } + return nil +} + type InvokeScriptResult_Payment struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -443,6 +459,124 @@ func (x *InvokeScriptResult_SponsorFee) GetMinFee() *Amount { return nil } +type InvokeScriptResult_Lease struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Recipient *Recipient `protobuf:"bytes,1,opt,name=recipient,proto3" json:"recipient,omitempty"` + Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` + Nonce int64 `protobuf:"varint,3,opt,name=nonce,proto3" json:"nonce,omitempty"` + LeaseId []byte `protobuf:"bytes,4,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` +} + +func (x *InvokeScriptResult_Lease) Reset() { + *x = InvokeScriptResult_Lease{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_invoke_script_result_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InvokeScriptResult_Lease) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InvokeScriptResult_Lease) ProtoMessage() {} + +func (x *InvokeScriptResult_Lease) ProtoReflect() protoreflect.Message { + mi := &file_waves_invoke_script_result_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InvokeScriptResult_Lease.ProtoReflect.Descriptor instead. +func (*InvokeScriptResult_Lease) Descriptor() ([]byte, []int) { + return file_waves_invoke_script_result_proto_rawDescGZIP(), []int{0, 5} +} + +func (x *InvokeScriptResult_Lease) GetRecipient() *Recipient { + if x != nil { + return x.Recipient + } + return nil +} + +func (x *InvokeScriptResult_Lease) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *InvokeScriptResult_Lease) GetNonce() int64 { + if x != nil { + return x.Nonce + } + return 0 +} + +func (x *InvokeScriptResult_Lease) GetLeaseId() []byte { + if x != nil { + return x.LeaseId + } + return nil +} + +type InvokeScriptResult_LeaseCancel struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LeaseId []byte `protobuf:"bytes,1,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` +} + +func (x *InvokeScriptResult_LeaseCancel) Reset() { + *x = InvokeScriptResult_LeaseCancel{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_invoke_script_result_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InvokeScriptResult_LeaseCancel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InvokeScriptResult_LeaseCancel) ProtoMessage() {} + +func (x *InvokeScriptResult_LeaseCancel) ProtoReflect() protoreflect.Message { + mi := &file_waves_invoke_script_result_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InvokeScriptResult_LeaseCancel.ProtoReflect.Descriptor instead. +func (*InvokeScriptResult_LeaseCancel) Descriptor() ([]byte, []int) { + return file_waves_invoke_script_result_proto_rawDescGZIP(), []int{0, 6} +} + +func (x *InvokeScriptResult_LeaseCancel) GetLeaseId() []byte { + if x != nil { + return x.LeaseId + } + return nil +} + type InvokeScriptResult_ErrorMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -455,7 +589,7 @@ type InvokeScriptResult_ErrorMessage struct { func (x *InvokeScriptResult_ErrorMessage) Reset() { *x = InvokeScriptResult_ErrorMessage{} if protoimpl.UnsafeEnabled { - mi := &file_waves_invoke_script_result_proto_msgTypes[6] + mi := &file_waves_invoke_script_result_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -468,7 +602,7 @@ func (x *InvokeScriptResult_ErrorMessage) String() string { func (*InvokeScriptResult_ErrorMessage) ProtoMessage() {} func (x *InvokeScriptResult_ErrorMessage) ProtoReflect() protoreflect.Message { - mi := &file_waves_invoke_script_result_proto_msgTypes[6] + mi := &file_waves_invoke_script_result_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -481,7 +615,7 @@ func (x *InvokeScriptResult_ErrorMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeScriptResult_ErrorMessage.ProtoReflect.Descriptor instead. func (*InvokeScriptResult_ErrorMessage) Descriptor() ([]byte, []int) { - return file_waves_invoke_script_result_proto_rawDescGZIP(), []int{0, 5} + return file_waves_invoke_script_result_proto_rawDescGZIP(), []int{0, 7} } func (x *InvokeScriptResult_ErrorMessage) GetCode() int32 { @@ -506,79 +640,99 @@ var file_waves_invoke_script_result_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x12, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x88, 0x08, 0x0a, 0x12, 0x49, 0x6e, 0x76, 0x6f, 0x6b, - 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x38, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3f, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x72, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xba, 0x0a, + 0x0a, 0x12, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3f, + 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, + 0x37, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, + 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x72, 0x65, 0x69, 0x73, + 0x73, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, - 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, - 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x52, - 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x52, 0x08, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, - 0x12, 0x34, 0x0a, 0x05, 0x62, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x52, - 0x05, 0x62, 0x75, 0x72, 0x6e, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x66, - 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x53, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x46, 0x65, 0x65, 0x52, - 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x46, 0x65, 0x65, 0x73, 0x1a, 0x4a, 0x0a, 0x07, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x25, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xda, 0x01, 0x0a, 0x05, 0x49, 0x73, 0x73, - 0x75, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, - 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, - 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, - 0x75, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x69, - 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, - 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x1a, 0x61, 0x0a, 0x07, 0x52, 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, - 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, - 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x52, 0x65, - 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, 0x65, 0x1a, 0x39, 0x0a, 0x04, 0x42, 0x75, 0x72, 0x6e, - 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x1a, 0x34, 0x0a, 0x0a, 0x53, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x46, 0x65, - 0x65, 0x12, 0x26, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x46, 0x65, 0x65, 0x1a, 0x36, 0x0a, 0x0c, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x42, 0x6b, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5a, 0x39, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x52, 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x52, 0x08, 0x72, + 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x05, 0x62, 0x75, 0x72, 0x6e, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, + 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x52, 0x05, 0x62, 0x75, 0x72, 0x6e, 0x73, 0x12, 0x4b, 0x0a, + 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, + 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0c, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x66, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x53, 0x70, 0x6f, 0x6e, + 0x73, 0x6f, 0x72, 0x46, 0x65, 0x65, 0x52, 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x46, + 0x65, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, + 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4c, + 0x65, 0x61, 0x73, 0x65, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0d, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, + 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4c, + 0x65, 0x61, 0x73, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x73, 0x1a, 0x4a, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xda, 0x01, 0x0a, 0x05, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, + 0x61, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, + 0x61, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, + 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6e, + 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, + 0x65, 0x1a, 0x61, 0x0a, 0x07, 0x52, 0x65, 0x69, 0x73, 0x73, 0x75, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x52, 0x65, 0x69, 0x73, 0x73, 0x75, + 0x61, 0x62, 0x6c, 0x65, 0x1a, 0x39, 0x0a, 0x04, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x1a, + 0x34, 0x0a, 0x0a, 0x53, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x46, 0x65, 0x65, 0x12, 0x26, 0x0a, + 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x6d, + 0x69, 0x6e, 0x46, 0x65, 0x65, 0x1a, 0x80, 0x01, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, + 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x0a, + 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x1a, 0x28, 0x0a, 0x0b, 0x4c, 0x65, 0x61, 0x73, + 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x1a, 0x36, 0x0a, 0x0c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x42, 0x6b, 0x0a, 0x26, 0x63, 0x6f, + 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, + 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0xaa, + 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -593,7 +747,7 @@ func file_waves_invoke_script_result_proto_rawDescGZIP() []byte { return file_waves_invoke_script_result_proto_rawDescData } -var file_waves_invoke_script_result_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_waves_invoke_script_result_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_waves_invoke_script_result_proto_goTypes = []interface{}{ (*InvokeScriptResult)(nil), // 0: waves.InvokeScriptResult (*InvokeScriptResult_Payment)(nil), // 1: waves.InvokeScriptResult.Payment @@ -601,25 +755,31 @@ var file_waves_invoke_script_result_proto_goTypes = []interface{}{ (*InvokeScriptResult_Reissue)(nil), // 3: waves.InvokeScriptResult.Reissue (*InvokeScriptResult_Burn)(nil), // 4: waves.InvokeScriptResult.Burn (*InvokeScriptResult_SponsorFee)(nil), // 5: waves.InvokeScriptResult.SponsorFee - (*InvokeScriptResult_ErrorMessage)(nil), // 6: waves.InvokeScriptResult.ErrorMessage - (*DataTransactionData_DataEntry)(nil), // 7: waves.DataTransactionData.DataEntry - (*Amount)(nil), // 8: waves.Amount + (*InvokeScriptResult_Lease)(nil), // 6: waves.InvokeScriptResult.Lease + (*InvokeScriptResult_LeaseCancel)(nil), // 7: waves.InvokeScriptResult.LeaseCancel + (*InvokeScriptResult_ErrorMessage)(nil), // 8: waves.InvokeScriptResult.ErrorMessage + (*DataTransactionData_DataEntry)(nil), // 9: waves.DataTransactionData.DataEntry + (*Amount)(nil), // 10: waves.Amount + (*Recipient)(nil), // 11: waves.Recipient } var file_waves_invoke_script_result_proto_depIdxs = []int32{ - 7, // 0: waves.InvokeScriptResult.data:type_name -> waves.DataTransactionData.DataEntry - 1, // 1: waves.InvokeScriptResult.transfers:type_name -> waves.InvokeScriptResult.Payment - 2, // 2: waves.InvokeScriptResult.issues:type_name -> waves.InvokeScriptResult.Issue - 3, // 3: waves.InvokeScriptResult.reissues:type_name -> waves.InvokeScriptResult.Reissue - 4, // 4: waves.InvokeScriptResult.burns:type_name -> waves.InvokeScriptResult.Burn - 6, // 5: waves.InvokeScriptResult.error_message:type_name -> waves.InvokeScriptResult.ErrorMessage - 5, // 6: waves.InvokeScriptResult.sponsor_fees:type_name -> waves.InvokeScriptResult.SponsorFee - 8, // 7: waves.InvokeScriptResult.Payment.amount:type_name -> waves.Amount - 8, // 8: waves.InvokeScriptResult.SponsorFee.min_fee:type_name -> waves.Amount - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 9, // 0: waves.InvokeScriptResult.data:type_name -> waves.DataTransactionData.DataEntry + 1, // 1: waves.InvokeScriptResult.transfers:type_name -> waves.InvokeScriptResult.Payment + 2, // 2: waves.InvokeScriptResult.issues:type_name -> waves.InvokeScriptResult.Issue + 3, // 3: waves.InvokeScriptResult.reissues:type_name -> waves.InvokeScriptResult.Reissue + 4, // 4: waves.InvokeScriptResult.burns:type_name -> waves.InvokeScriptResult.Burn + 8, // 5: waves.InvokeScriptResult.error_message:type_name -> waves.InvokeScriptResult.ErrorMessage + 5, // 6: waves.InvokeScriptResult.sponsor_fees:type_name -> waves.InvokeScriptResult.SponsorFee + 6, // 7: waves.InvokeScriptResult.leases:type_name -> waves.InvokeScriptResult.Lease + 7, // 8: waves.InvokeScriptResult.lease_cancels:type_name -> waves.InvokeScriptResult.LeaseCancel + 10, // 9: waves.InvokeScriptResult.Payment.amount:type_name -> waves.Amount + 10, // 10: waves.InvokeScriptResult.SponsorFee.min_fee:type_name -> waves.Amount + 11, // 11: waves.InvokeScriptResult.Lease.recipient:type_name -> waves.Recipient + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_waves_invoke_script_result_proto_init() } @@ -629,6 +789,7 @@ func file_waves_invoke_script_result_proto_init() { } file_waves_transaction_proto_init() file_waves_amount_proto_init() + file_waves_recipient_proto_init() if !protoimpl.UnsafeEnabled { file_waves_invoke_script_result_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InvokeScriptResult); i { @@ -703,6 +864,30 @@ func file_waves_invoke_script_result_proto_init() { } } file_waves_invoke_script_result_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InvokeScriptResult_Lease); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_invoke_script_result_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InvokeScriptResult_LeaseCancel); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_invoke_script_result_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InvokeScriptResult_ErrorMessage); i { case 0: return &v.state @@ -721,7 +906,7 @@ func file_waves_invoke_script_result_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_waves_invoke_script_result_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go index 1cf63987b..13ba60e76 100644 --- a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/node/grpc/accounts_api.proto package grpc @@ -9,13 +9,13 @@ package grpc import ( context "context" proto "github.com/golang/protobuf/proto" - wrappers "github.com/golang/protobuf/ptypes/wrappers" waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -386,6 +386,93 @@ func (x *ScriptData) GetComplexity() int64 { return 0 } +type LeaseResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LeaseId []byte `protobuf:"bytes,1,opt,name=leaseId,proto3" json:"leaseId,omitempty"` + OriginTransactionId []byte `protobuf:"bytes,2,opt,name=originTransactionId,proto3" json:"originTransactionId,omitempty"` + Sender []byte `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` + Recipient *waves.Recipient `protobuf:"bytes,4,opt,name=recipient,proto3" json:"recipient,omitempty"` + Amount int64 `protobuf:"varint,5,opt,name=amount,proto3" json:"amount,omitempty"` + Height int64 `protobuf:"varint,6,opt,name=height,proto3" json:"height,omitempty"` +} + +func (x *LeaseResponse) Reset() { + *x = LeaseResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaseResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaseResponse) ProtoMessage() {} + +func (x *LeaseResponse) ProtoReflect() protoreflect.Message { + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LeaseResponse.ProtoReflect.Descriptor instead. +func (*LeaseResponse) Descriptor() ([]byte, []int) { + return file_waves_node_grpc_accounts_api_proto_rawDescGZIP(), []int{6} +} + +func (x *LeaseResponse) GetLeaseId() []byte { + if x != nil { + return x.LeaseId + } + return nil +} + +func (x *LeaseResponse) GetOriginTransactionId() []byte { + if x != nil { + return x.OriginTransactionId + } + return nil +} + +func (x *LeaseResponse) GetSender() []byte { + if x != nil { + return x.Sender + } + return nil +} + +func (x *LeaseResponse) GetRecipient() *waves.Recipient { + if x != nil { + return x.Recipient + } + return nil +} + +func (x *LeaseResponse) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *LeaseResponse) GetHeight() int64 { + if x != nil { + return x.Height + } + return 0 +} + type BalanceResponse_WavesBalances struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -402,7 +489,7 @@ type BalanceResponse_WavesBalances struct { func (x *BalanceResponse_WavesBalances) Reset() { *x = BalanceResponse_WavesBalances{} if protoimpl.UnsafeEnabled { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -415,7 +502,7 @@ func (x *BalanceResponse_WavesBalances) String() string { func (*BalanceResponse_WavesBalances) ProtoMessage() {} func (x *BalanceResponse_WavesBalances) ProtoReflect() protoreflect.Message { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -479,94 +566,106 @@ var file_waves_node_grpc_accounts_api_proto_rawDesc = []byte{ 0x0a, 0x22, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x1a, 0x26, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x12, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, - 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2a, 0x0a, 0x0e, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x39, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x22, 0x43, 0x0a, 0x0f, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x1a, 0x12, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x15, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, + 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2a, 0x0a, 0x0e, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x39, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0xcb, 0x02, 0x0a, 0x0f, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x05, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x57, 0x61, 0x76, 0x65, - 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x12, 0x25, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x1a, 0xbd, 0x01, 0x0a, 0x0d, 0x57, 0x61, - 0x76, 0x65, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, - 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x72, 0x65, - 0x67, 0x75, 0x6c, 0x61, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x12, 0x1b, 0x0a, 0x09, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4f, 0x75, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x22, 0x69, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, - 0x70, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, - 0x0c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x65, 0x78, - 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, - 0x79, 0x32, 0xaa, 0x03, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x41, 0x70, - 0x69, 0x12, 0x53, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x49, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x5a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4c, 0x65, - 0x61, 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, - 0x0e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x30, 0x01, 0x12, 0x49, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x73, - 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, - 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, - 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x22, 0x43, 0x0a, 0x0f, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0xcb, 0x02, 0x0a, 0x0f, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x05, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x57, 0x61, 0x76, 0x65, 0x73, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x12, 0x25, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x1a, 0xbd, 0x01, 0x0a, 0x0d, 0x57, 0x61, 0x76, + 0x65, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, + 0x67, 0x75, 0x6c, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x72, 0x65, 0x67, + 0x75, 0x6c, 0x61, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4f, 0x75, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x22, 0x69, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, + 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x70, + 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x65, 0x78, 0x74, + 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, + 0x22, 0xd3, 0x01, 0x0a, 0x0d, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xa4, 0x03, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x73, 0x41, 0x70, 0x69, 0x12, 0x53, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x49, 0x0a, 0x09, 0x47, + 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1c, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x30, 0x01, 0x12, 0x49, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x73, 0x0a, + 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, + 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -581,7 +680,7 @@ func file_waves_node_grpc_accounts_api_proto_rawDescGZIP() []byte { return file_waves_node_grpc_accounts_api_proto_rawDescData } -var file_waves_node_grpc_accounts_api_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_waves_node_grpc_accounts_api_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_waves_node_grpc_accounts_api_proto_goTypes = []interface{}{ (*AccountRequest)(nil), // 0: waves.node.grpc.AccountRequest (*DataRequest)(nil), // 1: waves.node.grpc.DataRequest @@ -589,32 +688,34 @@ var file_waves_node_grpc_accounts_api_proto_goTypes = []interface{}{ (*BalanceResponse)(nil), // 3: waves.node.grpc.BalanceResponse (*DataEntryResponse)(nil), // 4: waves.node.grpc.DataEntryResponse (*ScriptData)(nil), // 5: waves.node.grpc.ScriptData - (*BalanceResponse_WavesBalances)(nil), // 6: waves.node.grpc.BalanceResponse.WavesBalances - (*waves.Amount)(nil), // 7: waves.Amount - (*waves.DataTransactionData_DataEntry)(nil), // 8: waves.DataTransactionData.DataEntry - (*wrappers.StringValue)(nil), // 9: google.protobuf.StringValue - (*TransactionResponse)(nil), // 10: waves.node.grpc.TransactionResponse - (*wrappers.BytesValue)(nil), // 11: google.protobuf.BytesValue + (*LeaseResponse)(nil), // 6: waves.node.grpc.LeaseResponse + (*BalanceResponse_WavesBalances)(nil), // 7: waves.node.grpc.BalanceResponse.WavesBalances + (*waves.Amount)(nil), // 8: waves.Amount + (*waves.DataTransactionData_DataEntry)(nil), // 9: waves.DataTransactionData.DataEntry + (*waves.Recipient)(nil), // 10: waves.Recipient + (*wrapperspb.StringValue)(nil), // 11: google.protobuf.StringValue + (*wrapperspb.BytesValue)(nil), // 12: google.protobuf.BytesValue } var file_waves_node_grpc_accounts_api_proto_depIdxs = []int32{ - 6, // 0: waves.node.grpc.BalanceResponse.waves:type_name -> waves.node.grpc.BalanceResponse.WavesBalances - 7, // 1: waves.node.grpc.BalanceResponse.asset:type_name -> waves.Amount - 8, // 2: waves.node.grpc.DataEntryResponse.entry:type_name -> waves.DataTransactionData.DataEntry - 2, // 3: waves.node.grpc.AccountsApi.GetBalances:input_type -> waves.node.grpc.BalancesRequest - 0, // 4: waves.node.grpc.AccountsApi.GetScript:input_type -> waves.node.grpc.AccountRequest - 0, // 5: waves.node.grpc.AccountsApi.GetActiveLeases:input_type -> waves.node.grpc.AccountRequest - 1, // 6: waves.node.grpc.AccountsApi.GetDataEntries:input_type -> waves.node.grpc.DataRequest - 9, // 7: waves.node.grpc.AccountsApi.ResolveAlias:input_type -> google.protobuf.StringValue - 3, // 8: waves.node.grpc.AccountsApi.GetBalances:output_type -> waves.node.grpc.BalanceResponse - 5, // 9: waves.node.grpc.AccountsApi.GetScript:output_type -> waves.node.grpc.ScriptData - 10, // 10: waves.node.grpc.AccountsApi.GetActiveLeases:output_type -> waves.node.grpc.TransactionResponse - 4, // 11: waves.node.grpc.AccountsApi.GetDataEntries:output_type -> waves.node.grpc.DataEntryResponse - 11, // 12: waves.node.grpc.AccountsApi.ResolveAlias:output_type -> google.protobuf.BytesValue - 8, // [8:13] is the sub-list for method output_type - 3, // [3:8] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 7, // 0: waves.node.grpc.BalanceResponse.waves:type_name -> waves.node.grpc.BalanceResponse.WavesBalances + 8, // 1: waves.node.grpc.BalanceResponse.asset:type_name -> waves.Amount + 9, // 2: waves.node.grpc.DataEntryResponse.entry:type_name -> waves.DataTransactionData.DataEntry + 10, // 3: waves.node.grpc.LeaseResponse.recipient:type_name -> waves.Recipient + 2, // 4: waves.node.grpc.AccountsApi.GetBalances:input_type -> waves.node.grpc.BalancesRequest + 0, // 5: waves.node.grpc.AccountsApi.GetScript:input_type -> waves.node.grpc.AccountRequest + 0, // 6: waves.node.grpc.AccountsApi.GetActiveLeases:input_type -> waves.node.grpc.AccountRequest + 1, // 7: waves.node.grpc.AccountsApi.GetDataEntries:input_type -> waves.node.grpc.DataRequest + 11, // 8: waves.node.grpc.AccountsApi.ResolveAlias:input_type -> google.protobuf.StringValue + 3, // 9: waves.node.grpc.AccountsApi.GetBalances:output_type -> waves.node.grpc.BalanceResponse + 5, // 10: waves.node.grpc.AccountsApi.GetScript:output_type -> waves.node.grpc.ScriptData + 6, // 11: waves.node.grpc.AccountsApi.GetActiveLeases:output_type -> waves.node.grpc.LeaseResponse + 4, // 12: waves.node.grpc.AccountsApi.GetDataEntries:output_type -> waves.node.grpc.DataEntryResponse + 12, // 13: waves.node.grpc.AccountsApi.ResolveAlias:output_type -> google.protobuf.BytesValue + 9, // [9:14] is the sub-list for method output_type + 4, // [4:9] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_waves_node_grpc_accounts_api_proto_init() } @@ -622,7 +723,6 @@ func file_waves_node_grpc_accounts_api_proto_init() { if File_waves_node_grpc_accounts_api_proto != nil { return } - file_waves_node_grpc_transactions_api_proto_init() if !protoimpl.UnsafeEnabled { file_waves_node_grpc_accounts_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AccountRequest); i { @@ -697,6 +797,18 @@ func file_waves_node_grpc_accounts_api_proto_init() { } } file_waves_node_grpc_accounts_api_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaseResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_node_grpc_accounts_api_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BalanceResponse_WavesBalances); i { case 0: return &v.state @@ -719,7 +831,7 @@ func file_waves_node_grpc_accounts_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_waves_node_grpc_accounts_api_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, @@ -749,7 +861,7 @@ type AccountsApiClient interface { GetScript(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (*ScriptData, error) GetActiveLeases(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (AccountsApi_GetActiveLeasesClient, error) GetDataEntries(ctx context.Context, in *DataRequest, opts ...grpc.CallOption) (AccountsApi_GetDataEntriesClient, error) - ResolveAlias(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.BytesValue, error) + ResolveAlias(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*wrapperspb.BytesValue, error) } type accountsApiClient struct { @@ -817,7 +929,7 @@ func (c *accountsApiClient) GetActiveLeases(ctx context.Context, in *AccountRequ } type AccountsApi_GetActiveLeasesClient interface { - Recv() (*TransactionResponse, error) + Recv() (*LeaseResponse, error) grpc.ClientStream } @@ -825,8 +937,8 @@ type accountsApiGetActiveLeasesClient struct { grpc.ClientStream } -func (x *accountsApiGetActiveLeasesClient) Recv() (*TransactionResponse, error) { - m := new(TransactionResponse) +func (x *accountsApiGetActiveLeasesClient) Recv() (*LeaseResponse, error) { + m := new(LeaseResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -865,8 +977,8 @@ func (x *accountsApiGetDataEntriesClient) Recv() (*DataEntryResponse, error) { return m, nil } -func (c *accountsApiClient) ResolveAlias(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.BytesValue, error) { - out := new(wrappers.BytesValue) +func (c *accountsApiClient) ResolveAlias(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*wrapperspb.BytesValue, error) { + out := new(wrapperspb.BytesValue) err := c.cc.Invoke(ctx, "/waves.node.grpc.AccountsApi/ResolveAlias", in, out, opts...) if err != nil { return nil, err @@ -880,7 +992,7 @@ type AccountsApiServer interface { GetScript(context.Context, *AccountRequest) (*ScriptData, error) GetActiveLeases(*AccountRequest, AccountsApi_GetActiveLeasesServer) error GetDataEntries(*DataRequest, AccountsApi_GetDataEntriesServer) error - ResolveAlias(context.Context, *wrappers.StringValue) (*wrappers.BytesValue, error) + ResolveAlias(context.Context, *wrapperspb.StringValue) (*wrapperspb.BytesValue, error) } // UnimplementedAccountsApiServer can be embedded to have forward compatible implementations. @@ -899,7 +1011,7 @@ func (*UnimplementedAccountsApiServer) GetActiveLeases(*AccountRequest, Accounts func (*UnimplementedAccountsApiServer) GetDataEntries(*DataRequest, AccountsApi_GetDataEntriesServer) error { return status.Errorf(codes.Unimplemented, "method GetDataEntries not implemented") } -func (*UnimplementedAccountsApiServer) ResolveAlias(context.Context, *wrappers.StringValue) (*wrappers.BytesValue, error) { +func (*UnimplementedAccountsApiServer) ResolveAlias(context.Context, *wrapperspb.StringValue) (*wrapperspb.BytesValue, error) { return nil, status.Errorf(codes.Unimplemented, "method ResolveAlias not implemented") } @@ -955,7 +1067,7 @@ func _AccountsApi_GetActiveLeases_Handler(srv interface{}, stream grpc.ServerStr } type AccountsApi_GetActiveLeasesServer interface { - Send(*TransactionResponse) error + Send(*LeaseResponse) error grpc.ServerStream } @@ -963,7 +1075,7 @@ type accountsApiGetActiveLeasesServer struct { grpc.ServerStream } -func (x *accountsApiGetActiveLeasesServer) Send(m *TransactionResponse) error { +func (x *accountsApiGetActiveLeasesServer) Send(m *LeaseResponse) error { return x.ServerStream.SendMsg(m) } @@ -989,7 +1101,7 @@ func (x *accountsApiGetDataEntriesServer) Send(m *DataEntryResponse) error { } func _AccountsApi_ResolveAlias_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(wrappers.StringValue) + in := new(wrapperspb.StringValue) if err := dec(in); err != nil { return nil, err } @@ -1001,7 +1113,7 @@ func _AccountsApi_ResolveAlias_Handler(srv interface{}, ctx context.Context, dec FullMethod: "/waves.node.grpc.AccountsApi/ResolveAlias", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AccountsApiServer).ResolveAlias(ctx, req.(*wrappers.StringValue)) + return srv.(AccountsApiServer).ResolveAlias(ctx, req.(*wrapperspb.StringValue)) } return interceptor(ctx, in, info, handler) } diff --git a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go index 0e385960a..5466a79ae 100644 --- a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/node/grpc/assets_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go index dd13a7215..65f6fac81 100644 --- a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/node/grpc/blockchain_api.proto package grpc @@ -9,12 +9,12 @@ package grpc import ( context "context" proto "github.com/golang/protobuf/proto" - empty "github.com/golang/protobuf/ptypes/empty" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) @@ -549,7 +549,7 @@ var file_waves_node_grpc_blockchain_api_proto_goTypes = []interface{}{ (*FeatureActivationStatus)(nil), // 4: waves.node.grpc.FeatureActivationStatus (*BaseTargetResponse)(nil), // 5: waves.node.grpc.BaseTargetResponse (*ScoreResponse)(nil), // 6: waves.node.grpc.ScoreResponse - (*empty.Empty)(nil), // 7: google.protobuf.Empty + (*emptypb.Empty)(nil), // 7: google.protobuf.Empty } var file_waves_node_grpc_blockchain_api_proto_depIdxs = []int32{ 4, // 0: waves.node.grpc.ActivationStatusResponse.features:type_name -> waves.node.grpc.FeatureActivationStatus @@ -669,8 +669,8 @@ const _ = grpc.SupportPackageIsVersion6 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type BlockchainApiClient interface { GetActivationStatus(ctx context.Context, in *ActivationStatusRequest, opts ...grpc.CallOption) (*ActivationStatusResponse, error) - GetBaseTarget(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*BaseTargetResponse, error) - GetCumulativeScore(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ScoreResponse, error) + GetBaseTarget(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*BaseTargetResponse, error) + GetCumulativeScore(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ScoreResponse, error) } type blockchainApiClient struct { @@ -690,7 +690,7 @@ func (c *blockchainApiClient) GetActivationStatus(ctx context.Context, in *Activ return out, nil } -func (c *blockchainApiClient) GetBaseTarget(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*BaseTargetResponse, error) { +func (c *blockchainApiClient) GetBaseTarget(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*BaseTargetResponse, error) { out := new(BaseTargetResponse) err := c.cc.Invoke(ctx, "/waves.node.grpc.BlockchainApi/GetBaseTarget", in, out, opts...) if err != nil { @@ -699,7 +699,7 @@ func (c *blockchainApiClient) GetBaseTarget(ctx context.Context, in *empty.Empty return out, nil } -func (c *blockchainApiClient) GetCumulativeScore(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ScoreResponse, error) { +func (c *blockchainApiClient) GetCumulativeScore(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ScoreResponse, error) { out := new(ScoreResponse) err := c.cc.Invoke(ctx, "/waves.node.grpc.BlockchainApi/GetCumulativeScore", in, out, opts...) if err != nil { @@ -711,8 +711,8 @@ func (c *blockchainApiClient) GetCumulativeScore(ctx context.Context, in *empty. // BlockchainApiServer is the server API for BlockchainApi service. type BlockchainApiServer interface { GetActivationStatus(context.Context, *ActivationStatusRequest) (*ActivationStatusResponse, error) - GetBaseTarget(context.Context, *empty.Empty) (*BaseTargetResponse, error) - GetCumulativeScore(context.Context, *empty.Empty) (*ScoreResponse, error) + GetBaseTarget(context.Context, *emptypb.Empty) (*BaseTargetResponse, error) + GetCumulativeScore(context.Context, *emptypb.Empty) (*ScoreResponse, error) } // UnimplementedBlockchainApiServer can be embedded to have forward compatible implementations. @@ -722,10 +722,10 @@ type UnimplementedBlockchainApiServer struct { func (*UnimplementedBlockchainApiServer) GetActivationStatus(context.Context, *ActivationStatusRequest) (*ActivationStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetActivationStatus not implemented") } -func (*UnimplementedBlockchainApiServer) GetBaseTarget(context.Context, *empty.Empty) (*BaseTargetResponse, error) { +func (*UnimplementedBlockchainApiServer) GetBaseTarget(context.Context, *emptypb.Empty) (*BaseTargetResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBaseTarget not implemented") } -func (*UnimplementedBlockchainApiServer) GetCumulativeScore(context.Context, *empty.Empty) (*ScoreResponse, error) { +func (*UnimplementedBlockchainApiServer) GetCumulativeScore(context.Context, *emptypb.Empty) (*ScoreResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetCumulativeScore not implemented") } @@ -752,7 +752,7 @@ func _BlockchainApi_GetActivationStatus_Handler(srv interface{}, ctx context.Con } func _BlockchainApi_GetBaseTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) + in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } @@ -764,13 +764,13 @@ func _BlockchainApi_GetBaseTarget_Handler(srv interface{}, ctx context.Context, FullMethod: "/waves.node.grpc.BlockchainApi/GetBaseTarget", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BlockchainApiServer).GetBaseTarget(ctx, req.(*empty.Empty)) + return srv.(BlockchainApiServer).GetBaseTarget(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } func _BlockchainApi_GetCumulativeScore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) + in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } @@ -782,7 +782,7 @@ func _BlockchainApi_GetCumulativeScore_Handler(srv interface{}, ctx context.Cont FullMethod: "/waves.node.grpc.BlockchainApi/GetCumulativeScore", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BlockchainApiServer).GetCumulativeScore(ctx, req.(*empty.Empty)) + return srv.(BlockchainApiServer).GetCumulativeScore(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } diff --git a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go index 01b2dcb96..27b9107d7 100644 --- a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/node/grpc/blocks_api.proto package grpc @@ -9,14 +9,14 @@ package grpc import ( context "context" proto "github.com/golang/protobuf/proto" - empty "github.com/golang/protobuf/ptypes/empty" - wrappers "github.com/golang/protobuf/ptypes/wrappers" waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -359,12 +359,12 @@ func file_waves_node_grpc_blocks_api_proto_rawDescGZIP() []byte { var file_waves_node_grpc_blocks_api_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_waves_node_grpc_blocks_api_proto_goTypes = []interface{}{ - (*BlockRequest)(nil), // 0: waves.node.grpc.BlockRequest - (*BlockRangeRequest)(nil), // 1: waves.node.grpc.BlockRangeRequest - (*BlockWithHeight)(nil), // 2: waves.node.grpc.BlockWithHeight - (*waves.Block)(nil), // 3: waves.Block - (*empty.Empty)(nil), // 4: google.protobuf.Empty - (*wrappers.UInt32Value)(nil), // 5: google.protobuf.UInt32Value + (*BlockRequest)(nil), // 0: waves.node.grpc.BlockRequest + (*BlockRangeRequest)(nil), // 1: waves.node.grpc.BlockRangeRequest + (*BlockWithHeight)(nil), // 2: waves.node.grpc.BlockWithHeight + (*waves.Block)(nil), // 3: waves.Block + (*emptypb.Empty)(nil), // 4: google.protobuf.Empty + (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value } var file_waves_node_grpc_blocks_api_proto_depIdxs = []int32{ 3, // 0: waves.node.grpc.BlockWithHeight.block:type_name -> waves.Block @@ -466,7 +466,7 @@ const _ = grpc.SupportPackageIsVersion6 type BlocksApiClient interface { GetBlock(ctx context.Context, in *BlockRequest, opts ...grpc.CallOption) (*BlockWithHeight, error) GetBlockRange(ctx context.Context, in *BlockRangeRequest, opts ...grpc.CallOption) (BlocksApi_GetBlockRangeClient, error) - GetCurrentHeight(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*wrappers.UInt32Value, error) + GetCurrentHeight(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.UInt32Value, error) } type blocksApiClient struct { @@ -518,8 +518,8 @@ func (x *blocksApiGetBlockRangeClient) Recv() (*BlockWithHeight, error) { return m, nil } -func (c *blocksApiClient) GetCurrentHeight(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*wrappers.UInt32Value, error) { - out := new(wrappers.UInt32Value) +func (c *blocksApiClient) GetCurrentHeight(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.UInt32Value, error) { + out := new(wrapperspb.UInt32Value) err := c.cc.Invoke(ctx, "/waves.node.grpc.BlocksApi/GetCurrentHeight", in, out, opts...) if err != nil { return nil, err @@ -531,7 +531,7 @@ func (c *blocksApiClient) GetCurrentHeight(ctx context.Context, in *empty.Empty, type BlocksApiServer interface { GetBlock(context.Context, *BlockRequest) (*BlockWithHeight, error) GetBlockRange(*BlockRangeRequest, BlocksApi_GetBlockRangeServer) error - GetCurrentHeight(context.Context, *empty.Empty) (*wrappers.UInt32Value, error) + GetCurrentHeight(context.Context, *emptypb.Empty) (*wrapperspb.UInt32Value, error) } // UnimplementedBlocksApiServer can be embedded to have forward compatible implementations. @@ -544,7 +544,7 @@ func (*UnimplementedBlocksApiServer) GetBlock(context.Context, *BlockRequest) (* func (*UnimplementedBlocksApiServer) GetBlockRange(*BlockRangeRequest, BlocksApi_GetBlockRangeServer) error { return status.Errorf(codes.Unimplemented, "method GetBlockRange not implemented") } -func (*UnimplementedBlocksApiServer) GetCurrentHeight(context.Context, *empty.Empty) (*wrappers.UInt32Value, error) { +func (*UnimplementedBlocksApiServer) GetCurrentHeight(context.Context, *emptypb.Empty) (*wrapperspb.UInt32Value, error) { return nil, status.Errorf(codes.Unimplemented, "method GetCurrentHeight not implemented") } @@ -592,7 +592,7 @@ func (x *blocksApiGetBlockRangeServer) Send(m *BlockWithHeight) error { } func _BlocksApi_GetCurrentHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) + in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } @@ -604,7 +604,7 @@ func _BlocksApi_GetCurrentHeight_Handler(srv interface{}, ctx context.Context, d FullMethod: "/waves.node.grpc.BlocksApi/GetCurrentHeight", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BlocksApiServer).GetCurrentHeight(ctx, req.(*empty.Empty)) + return srv.(BlocksApiServer).GetCurrentHeight(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } diff --git a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go index 23a563fad..e0e25a829 100644 --- a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/node/grpc/transactions_api.proto package grpc @@ -204,10 +204,11 @@ type TransactionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - Transaction *waves.SignedTransaction `protobuf:"bytes,3,opt,name=transaction,proto3" json:"transaction,omitempty"` - ApplicationStatus ApplicationStatus `protobuf:"varint,4,opt,name=application_status,json=applicationStatus,proto3,enum=waves.node.grpc.ApplicationStatus" json:"application_status,omitempty"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Transaction *waves.SignedTransaction `protobuf:"bytes,3,opt,name=transaction,proto3" json:"transaction,omitempty"` + ApplicationStatus ApplicationStatus `protobuf:"varint,4,opt,name=application_status,json=applicationStatus,proto3,enum=waves.node.grpc.ApplicationStatus" json:"application_status,omitempty"` + InvokeScriptResult *waves.InvokeScriptResult `protobuf:"bytes,5,opt,name=invoke_script_result,json=invokeScriptResult,proto3" json:"invoke_script_result,omitempty"` } func (x *TransactionResponse) Reset() { @@ -270,6 +271,13 @@ func (x *TransactionResponse) GetApplicationStatus() ApplicationStatus { return ApplicationStatus_UNKNOWN } +func (x *TransactionResponse) GetInvokeScriptResult() *waves.InvokeScriptResult { + if x != nil { + return x.InvokeScriptResult + } + return nil +} + type TransactionsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -573,7 +581,7 @@ var file_waves_node_grpc_transactions_api_proto_rawDesc = []byte{ 0x38, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, - 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x22, 0xcc, 0x01, 0x0a, 0x13, 0x54, 0x72, + 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x22, 0x99, 0x02, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -586,87 +594,92 @@ var file_waves_node_grpc_transactions_api_proto_rawDesc = []byte{ 0x0e, 0x32, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x13, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x73, 0x22, 0x42, 0x0a, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x14, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, - 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, - 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0x6f, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x34, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x22, 0x8b, 0x01, 0x0a, 0x1a, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3a, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, - 0x4c, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, - 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0x9a, 0x04, - 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x70, - 0x69, 0x12, 0x5f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x30, 0x01, 0x12, 0x66, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4b, 0x0a, 0x14, 0x69, 0x6e, 0x76, 0x6f, + 0x6b, 0x65, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, + 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x12, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x86, 0x01, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x42, + 0x0a, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, + 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x73, 0x22, 0x49, 0x0a, 0x14, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x46, + 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x6f, 0x0a, + 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0b, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x8b, + 0x01, 0x0a, 0x1a, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, + 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x4c, 0x0a, 0x11, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, + 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1b, 0x0a, + 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0x9f, 0x04, 0x0a, 0x0f, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x70, 0x69, 0x12, 0x5f, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, + 0x6b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, + 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, - 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, 0x5e, 0x0a, 0x0e, 0x47, + 0x65, 0x74, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x24, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, 0x5e, 0x0a, 0x0e, 0x47, 0x65, 0x74, - 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x24, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x04, 0x53, 0x69, 0x67, - 0x6e, 0x12, 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x42, 0x72, 0x6f, - 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x1a, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x73, 0x0a, 0x1a, 0x63, 0x6f, - 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, - 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, 0x02, 0x0f, - 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x04, 0x53, + 0x69, 0x67, 0x6e, 0x12, 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x42, + 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x73, 0x0a, 0x1a, + 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, + 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, + 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -694,36 +707,37 @@ var file_waves_node_grpc_transactions_api_proto_goTypes = []interface{}{ (*SignRequest)(nil), // 7: waves.node.grpc.SignRequest (*InvokeScriptResultResponse)(nil), // 8: waves.node.grpc.InvokeScriptResultResponse (*waves.SignedTransaction)(nil), // 9: waves.SignedTransaction - (*waves.Recipient)(nil), // 10: waves.Recipient - (*waves.Transaction)(nil), // 11: waves.Transaction - (*waves.InvokeScriptResult)(nil), // 12: waves.InvokeScriptResult + (*waves.InvokeScriptResult)(nil), // 10: waves.InvokeScriptResult + (*waves.Recipient)(nil), // 11: waves.Recipient + (*waves.Transaction)(nil), // 12: waves.Transaction } var file_waves_node_grpc_transactions_api_proto_depIdxs = []int32{ 1, // 0: waves.node.grpc.TransactionStatus.status:type_name -> waves.node.grpc.TransactionStatus.Status 0, // 1: waves.node.grpc.TransactionStatus.application_status:type_name -> waves.node.grpc.ApplicationStatus 9, // 2: waves.node.grpc.TransactionResponse.transaction:type_name -> waves.SignedTransaction 0, // 3: waves.node.grpc.TransactionResponse.application_status:type_name -> waves.node.grpc.ApplicationStatus - 10, // 4: waves.node.grpc.TransactionsRequest.recipient:type_name -> waves.Recipient - 11, // 5: waves.node.grpc.SignRequest.transaction:type_name -> waves.Transaction - 9, // 6: waves.node.grpc.InvokeScriptResultResponse.transaction:type_name -> waves.SignedTransaction - 12, // 7: waves.node.grpc.InvokeScriptResultResponse.result:type_name -> waves.InvokeScriptResult - 4, // 8: waves.node.grpc.TransactionsApi.GetTransactions:input_type -> waves.node.grpc.TransactionsRequest - 4, // 9: waves.node.grpc.TransactionsApi.GetStateChanges:input_type -> waves.node.grpc.TransactionsRequest - 5, // 10: waves.node.grpc.TransactionsApi.GetStatuses:input_type -> waves.node.grpc.TransactionsByIdRequest - 4, // 11: waves.node.grpc.TransactionsApi.GetUnconfirmed:input_type -> waves.node.grpc.TransactionsRequest - 7, // 12: waves.node.grpc.TransactionsApi.Sign:input_type -> waves.node.grpc.SignRequest - 9, // 13: waves.node.grpc.TransactionsApi.Broadcast:input_type -> waves.SignedTransaction - 3, // 14: waves.node.grpc.TransactionsApi.GetTransactions:output_type -> waves.node.grpc.TransactionResponse - 8, // 15: waves.node.grpc.TransactionsApi.GetStateChanges:output_type -> waves.node.grpc.InvokeScriptResultResponse - 2, // 16: waves.node.grpc.TransactionsApi.GetStatuses:output_type -> waves.node.grpc.TransactionStatus - 3, // 17: waves.node.grpc.TransactionsApi.GetUnconfirmed:output_type -> waves.node.grpc.TransactionResponse - 9, // 18: waves.node.grpc.TransactionsApi.Sign:output_type -> waves.SignedTransaction - 9, // 19: waves.node.grpc.TransactionsApi.Broadcast:output_type -> waves.SignedTransaction - 14, // [14:20] is the sub-list for method output_type - 8, // [8:14] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 10, // 4: waves.node.grpc.TransactionResponse.invoke_script_result:type_name -> waves.InvokeScriptResult + 11, // 5: waves.node.grpc.TransactionsRequest.recipient:type_name -> waves.Recipient + 12, // 6: waves.node.grpc.SignRequest.transaction:type_name -> waves.Transaction + 9, // 7: waves.node.grpc.InvokeScriptResultResponse.transaction:type_name -> waves.SignedTransaction + 10, // 8: waves.node.grpc.InvokeScriptResultResponse.result:type_name -> waves.InvokeScriptResult + 4, // 9: waves.node.grpc.TransactionsApi.GetTransactions:input_type -> waves.node.grpc.TransactionsRequest + 4, // 10: waves.node.grpc.TransactionsApi.GetStateChanges:input_type -> waves.node.grpc.TransactionsRequest + 5, // 11: waves.node.grpc.TransactionsApi.GetStatuses:input_type -> waves.node.grpc.TransactionsByIdRequest + 4, // 12: waves.node.grpc.TransactionsApi.GetUnconfirmed:input_type -> waves.node.grpc.TransactionsRequest + 7, // 13: waves.node.grpc.TransactionsApi.Sign:input_type -> waves.node.grpc.SignRequest + 9, // 14: waves.node.grpc.TransactionsApi.Broadcast:input_type -> waves.SignedTransaction + 3, // 15: waves.node.grpc.TransactionsApi.GetTransactions:output_type -> waves.node.grpc.TransactionResponse + 8, // 16: waves.node.grpc.TransactionsApi.GetStateChanges:output_type -> waves.node.grpc.InvokeScriptResultResponse + 2, // 17: waves.node.grpc.TransactionsApi.GetStatuses:output_type -> waves.node.grpc.TransactionStatus + 3, // 18: waves.node.grpc.TransactionsApi.GetUnconfirmed:output_type -> waves.node.grpc.TransactionResponse + 9, // 19: waves.node.grpc.TransactionsApi.Sign:output_type -> waves.SignedTransaction + 9, // 20: waves.node.grpc.TransactionsApi.Broadcast:output_type -> waves.SignedTransaction + 15, // [15:21] is the sub-list for method output_type + 9, // [9:15] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_waves_node_grpc_transactions_api_proto_init() } @@ -851,6 +865,7 @@ const _ = grpc.SupportPackageIsVersion6 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type TransactionsApiClient interface { GetTransactions(ctx context.Context, in *TransactionsRequest, opts ...grpc.CallOption) (TransactionsApi_GetTransactionsClient, error) + // Deprecated: Do not use. GetStateChanges(ctx context.Context, in *TransactionsRequest, opts ...grpc.CallOption) (TransactionsApi_GetStateChangesClient, error) GetStatuses(ctx context.Context, in *TransactionsByIdRequest, opts ...grpc.CallOption) (TransactionsApi_GetStatusesClient, error) GetUnconfirmed(ctx context.Context, in *TransactionsRequest, opts ...grpc.CallOption) (TransactionsApi_GetUnconfirmedClient, error) @@ -898,6 +913,7 @@ func (x *transactionsApiGetTransactionsClient) Recv() (*TransactionResponse, err return m, nil } +// Deprecated: Do not use. func (c *transactionsApiClient) GetStateChanges(ctx context.Context, in *TransactionsRequest, opts ...grpc.CallOption) (TransactionsApi_GetStateChangesClient, error) { stream, err := c.cc.NewStream(ctx, &_TransactionsApi_serviceDesc.Streams[1], "/waves.node.grpc.TransactionsApi/GetStateChanges", opts...) if err != nil { @@ -1015,6 +1031,7 @@ func (c *transactionsApiClient) Broadcast(ctx context.Context, in *waves.SignedT // TransactionsApiServer is the server API for TransactionsApi service. type TransactionsApiServer interface { GetTransactions(*TransactionsRequest, TransactionsApi_GetTransactionsServer) error + // Deprecated: Do not use. GetStateChanges(*TransactionsRequest, TransactionsApi_GetStateChangesServer) error GetStatuses(*TransactionsByIdRequest, TransactionsApi_GetStatusesServer) error GetUnconfirmed(*TransactionsRequest, TransactionsApi_GetUnconfirmedServer) error diff --git a/pkg/grpc/generated/waves/order.pb.go b/pkg/grpc/generated/waves/order.pb.go index 77b7f0c1b..97994da69 100644 --- a/pkg/grpc/generated/waves/order.pb.go +++ b/pkg/grpc/generated/waves/order.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/order.proto package waves diff --git a/pkg/grpc/generated/waves/recipient.pb.go b/pkg/grpc/generated/waves/recipient.pb.go index 80ef09fa1..48a88d88a 100644 --- a/pkg/grpc/generated/waves/recipient.pb.go +++ b/pkg/grpc/generated/waves/recipient.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/recipient.proto package waves diff --git a/pkg/grpc/generated/waves/transaction.pb.go b/pkg/grpc/generated/waves/transaction.pb.go index 88d5e2702..8ba418298 100644 --- a/pkg/grpc/generated/waves/transaction.pb.go +++ b/pkg/grpc/generated/waves/transaction.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.14.0 // source: waves/transaction.proto package waves diff --git a/pkg/grpc/protobuf-schemas b/pkg/grpc/protobuf-schemas index c37e88a02..41bcd5544 160000 --- a/pkg/grpc/protobuf-schemas +++ b/pkg/grpc/protobuf-schemas @@ -1 +1 @@ -Subproject commit c37e88a0272f31c832be082da3bcf0f6c363067a +Subproject commit 41bcd554482810f40bdc387b4cd29a96b213dedf diff --git a/pkg/grpc/server/accounts_api.go b/pkg/grpc/server/accounts_api.go index dd1dcf356..85162d623 100644 --- a/pkg/grpc/server/accounts_api.go +++ b/pkg/grpc/server/accounts_api.go @@ -166,11 +166,50 @@ type getActiveLeasesHandler struct { s *Server } -func (h *getActiveLeasesHandler) handle(tx proto.Transaction, failed bool) error { - res, err := h.s.transactionToTransactionResponse(tx, true, failed) +func (h *getActiveLeasesHandler) handle(tx proto.Transaction, _ bool) error { + var id []byte + var sender proto.Address + var recipient proto.Recipient + var amount int64 + var err error + switch ltx := tx.(type) { + case *proto.LeaseWithSig: + id = ltx.ID.Bytes() + sender, err = proto.NewAddressFromPublicKey(h.s.scheme, ltx.SenderPK) + if err != nil { + return err + } + recipient = ltx.Recipient + amount = int64(ltx.Amount) + case *proto.LeaseWithProofs: + id = ltx.ID.Bytes() + sender, err = proto.NewAddressFromPublicKey(h.s.scheme, ltx.SenderPK) + if err != nil { + return err + } + recipient = ltx.Recipient + amount = int64(ltx.Amount) + default: + return nil + } + + height, err := h.s.state.TransactionHeightByID(id) + if err != nil { + return errors.Wrap(err, "failed to get tx height by ID") + } + rcp, err := recipient.ToProtobuf() if err != nil { - return errors.Wrap(err, "failed to form transaction response") + return err } + res := &g.LeaseResponse{ + LeaseId: id, + OriginTransactionId: id, + Sender: sender.Body(), + Recipient: rcp, + Amount: amount, + Height: int64(height), + } + err = h.srv.Send(res) if err != nil { return errors.Wrap(err, "failed to send") diff --git a/pkg/grpc/server/accounts_api_test.go b/pkg/grpc/server/accounts_api_test.go index a17f34553..8315e1819 100644 --- a/pkg/grpc/server/accounts_api_test.go +++ b/pkg/grpc/server/accounts_api_test.go @@ -96,9 +96,20 @@ func TestGetActiveLeases(t *testing.T) { require.NoError(t, err) tx, err := st.TransactionByID(txId.Bytes()) require.NoError(t, err) - correctRes, err := server.transactionToTransactionResponse(tx, true, false) - require.NoError(t, err) - assertTransactionResponsesEqual(t, correctRes, res) + + ltx, ok := tx.(*proto.LeaseWithSig) + require.True(t, ok) + assert.Equal(t, ltx.ID.Bytes(), res.LeaseId) + assert.Equal(t, ltx.ID.Bytes(), res.OriginTransactionId) + assert.Equal(t, int(ltx.Amount), int(res.Amount)) + expRecipient, err := ltx.Recipient.ToProtobuf() + require.NoError(t, err) + assert.Equal(t, expRecipient, res.Recipient) + expSender := proto.MustAddressFromPublicKey(sets.AddressSchemeCharacter, ltx.SenderPK) + assert.Equal(t, expSender.Body(), res.Sender) + expHeight, err := st.TransactionHeightByID(txId.Bytes()) + require.NoError(t, err) + assert.Equal(t, int(expHeight), int(res.Height)) _, err = stream.Recv() assert.Equal(t, io.EOF, err) } diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index 4b5ea58e7..4fd7fa568 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -587,6 +587,46 @@ func (c *ProtobufConverter) SponsorshipScriptActions(sponsorships []*g.InvokeScr return res, nil } +func (c *ProtobufConverter) LeaseScriptActions(scheme byte, leases []*g.InvokeScriptResult_Lease) ([]*LeaseScriptAction, error) { + if c.err != nil { + return nil, c.err + } + res := make([]*LeaseScriptAction, len(leases)) + for i, x := range leases { + rcp, err := c.Recipient(scheme, x.Recipient) + if err != nil { + c.err = err + return nil, err + } + res[i] = &LeaseScriptAction{ + ID: c.digest(x.LeaseId), + Recipient: rcp, + Amount: x.Amount, + Nonce: x.Nonce, + } + if c.err != nil { + return nil, c.err + } + } + return res, nil +} + +func (c *ProtobufConverter) LeaseCancelScriptActions(cancels []*g.InvokeScriptResult_LeaseCancel) ([]*LeaseCancelScriptAction, error) { + if c.err != nil { + return nil, c.err + } + res := make([]*LeaseCancelScriptAction, len(cancels)) + for i, x := range cancels { + res[i] = &LeaseCancelScriptAction{ + LeaseID: c.digest(x.LeaseId), + } + if c.err != nil { + return nil, c.err + } + } + return res, nil +} + func (c *ProtobufConverter) ErrorMessage(msg *g.InvokeScriptResult_ErrorMessage) (*ScriptErrorMessage, error) { if c.err != nil { return nil, c.err diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index 69c930f47..3b1fe416d 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -150,6 +150,64 @@ func (a *SponsorshipScriptAction) ToProtobuf() *g.InvokeScriptResult_SponsorFee } } +// LeaseScriptAction is an action to lease Waves to given account. +type LeaseScriptAction struct { + ID crypto.Digest + Recipient Recipient + Amount int64 + Nonce int64 +} + +func (a LeaseScriptAction) scriptAction() {} + +func (a *LeaseScriptAction) ToProtobuf() (*g.InvokeScriptResult_Lease, error) { + rcp, err := a.Recipient.ToProtobuf() + if err != nil { + return nil, err + } + return &g.InvokeScriptResult_Lease{ + Recipient: rcp, + Amount: a.Amount, + Nonce: a.Nonce, + LeaseId: a.ID.Bytes(), + }, nil +} + +// GenerateLeaseScriptActionID implements ID generation used in RIDE to create new ID for a Lease action. +func GenerateLeaseScriptActionID(recipient Recipient, amount int64, nonce int64, txID crypto.Digest) crypto.Digest { + rl := AddressSize + if recipient.Alias != nil { + rl = 4 + len(recipient.Alias.Alias) + } + buf := make([]byte, rl+crypto.DigestSize+8+8) + pos := 0 + if recipient.Alias != nil { + PutStringWithUInt32Len(buf[pos:], recipient.Alias.Alias) + } else { + copy(buf[pos:], recipient.Address[:]) + } + pos += rl + copy(buf[pos:], txID[:]) + pos += crypto.DigestSize + binary.BigEndian.PutUint64(buf[pos:], uint64(amount)) + pos += 8 + binary.BigEndian.PutUint64(buf[pos:], uint64(nonce)) + return crypto.MustFastHash(buf) +} + +// LeaseCancelScriptAction is an action that cancels previously created lease. +type LeaseCancelScriptAction struct { + LeaseID crypto.Digest +} + +func (a *LeaseCancelScriptAction) scriptAction() {} + +func (a *LeaseCancelScriptAction) ToProtobuf() *g.InvokeScriptResult_LeaseCancel { + return &g.InvokeScriptResult_LeaseCancel{ + LeaseId: a.LeaseID.Bytes(), + } +} + type ScriptErrorMessage struct { Code TxFailureReason Text string @@ -169,6 +227,8 @@ type ScriptResult struct { Reissues []*ReissueScriptAction Burns []*BurnScriptAction Sponsorships []*SponsorshipScriptAction + Leases []*LeaseScriptAction + LeaseCancels []*LeaseCancelScriptAction ErrorMsg ScriptErrorMessage } @@ -180,6 +240,8 @@ func NewScriptResult(actions []ScriptAction, msg ScriptErrorMessage) (*ScriptRes reissues := make([]*ReissueScriptAction, 0) burns := make([]*BurnScriptAction, 0) sponsorships := make([]*SponsorshipScriptAction, 0) + leases := make([]*LeaseScriptAction, 0) + leaseCancels := make([]*LeaseCancelScriptAction, 0) for _, a := range actions { switch ta := a.(type) { case *DataEntryScriptAction: @@ -194,6 +256,10 @@ func NewScriptResult(actions []ScriptAction, msg ScriptErrorMessage) (*ScriptRes burns = append(burns, ta) case *SponsorshipScriptAction: sponsorships = append(sponsorships, ta) + case *LeaseScriptAction: + leases = append(leases, ta) + case *LeaseCancelScriptAction: + leaseCancels = append(leaseCancels, ta) default: return nil, errors.Errorf("unsupported action type '%T'", a) } @@ -205,6 +271,8 @@ func NewScriptResult(actions []ScriptAction, msg ScriptErrorMessage) (*ScriptRes Reissues: reissues, Burns: burns, Sponsorships: sponsorships, + Leases: leases, + LeaseCancels: leaseCancels, ErrorMsg: msg, }, nil } @@ -238,6 +306,17 @@ func (sr *ScriptResult) ToProtobuf() (*g.InvokeScriptResult, error) { for i := range sr.Sponsorships { sponsorships[i] = sr.Sponsorships[i].ToProtobuf() } + leases := make([]*g.InvokeScriptResult_Lease, len(sr.Leases)) + for i := range sr.Leases { + leases[i], err = sr.Leases[i].ToProtobuf() + if err != nil { + return nil, err + } + } + leaseCancels := make([]*g.InvokeScriptResult_LeaseCancel, len(sr.LeaseCancels)) + for i := range sr.LeaseCancels { + leaseCancels[i] = sr.LeaseCancels[i].ToProtobuf() + } return &g.InvokeScriptResult{ Data: data, Transfers: transfers, @@ -245,6 +324,8 @@ func (sr *ScriptResult) ToProtobuf() (*g.InvokeScriptResult, error) { Reissues: reissues, Burns: burns, SponsorFees: sponsorships, + Leases: leases, + LeaseCancels: leaseCancels, ErrorMessage: sr.ErrorMsg.ToProtobuf(), }, nil } @@ -284,6 +365,14 @@ func (sr *ScriptResult) FromProtobuf(scheme byte, msg *g.InvokeScriptResult) err if err != nil { return err } + sr.Leases, err = c.LeaseScriptActions(scheme, msg.Leases) + if err != nil { + return err + } + sr.LeaseCancels, err = c.LeaseCancelScriptActions(msg.LeaseCancels) + if err != nil { + return err + } errMsg, err := c.ErrorMessage(msg.ErrorMessage) if err != nil { return err @@ -386,6 +475,24 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr return errors.New("negative minimal fee") } + case *LeaseScriptAction: + otherActionsCount++ + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + } + if ta.Amount < 0 { + return errors.New("negative leasing amount") + } + if ta.Recipient.Address.Eq(restrictions.ScriptAddress) { + return errors.New("leasing to DApp itself are forbidden") + } + + case *LeaseCancelScriptAction: + otherActionsCount++ + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + } + default: return errors.Errorf("unsupported script action type '%T'", a) } diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index 626673ffb..19be83459 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -28,6 +28,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { emptyReissues := make([]*ReissueScriptAction, 0) emptyBurns := make([]*BurnScriptAction, 0) emptySponsorships := make([]*SponsorshipScriptAction, 0) + emptyLeases := make([]*LeaseScriptAction, 0) + emptyLeaseCancels := make([]*LeaseCancelScriptAction, 0) for i, test := range []ScriptResult{ { DataEntries: []*DataEntryScriptAction{ @@ -51,6 +53,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { Reissues: emptyReissues, Burns: emptyBurns, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: []*DataEntryScriptAction{ @@ -61,6 +65,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { Reissues: emptyReissues, Burns: emptyBurns, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: emptyDataEntries, @@ -73,6 +79,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { Reissues: emptyReissues, Burns: emptyBurns, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: emptyDataEntries, @@ -84,6 +92,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { Reissues: emptyReissues, Burns: emptyBurns, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: emptyDataEntries, @@ -98,6 +108,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { }, Burns: emptyBurns, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: emptyDataEntries, @@ -112,6 +124,8 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { {AssetID: asset0.ID, Quantity: 0}, }, Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, }, { DataEntries: emptyDataEntries, @@ -123,6 +137,44 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { {AssetID: asset0.ID, MinFee: 12345}, {AssetID: asset1.ID, MinFee: 0}, }, + Leases: emptyLeases, + LeaseCancels: emptyLeaseCancels, + }, + { + DataEntries: emptyDataEntries, + Transfers: emptyTransfers, + Issues: emptyIssues, + Reissues: emptyReissues, + Burns: emptyBurns, + Sponsorships: emptySponsorships, + Leases: []*LeaseScriptAction{ + { + ID: asset0.ID, + Recipient: rcp, + Amount: 12345, + Nonce: 67890, + }, + { + ID: asset1.ID, + Recipient: rcp, + Amount: 0, + Nonce: 0, + }, + }, + LeaseCancels: emptyLeaseCancels, + }, + { + DataEntries: emptyDataEntries, + Transfers: emptyTransfers, + Issues: emptyIssues, + Reissues: emptyReissues, + Burns: emptyBurns, + Sponsorships: emptySponsorships, + Leases: emptyLeases, + LeaseCancels: []*LeaseCancelScriptAction{ + {LeaseID: asset0.ID}, + {LeaseID: asset1.ID}, + }, }, } { if msg, err := test.ToProtobuf(); assert.NoError(t, err) { @@ -169,6 +221,13 @@ func TestActionsValidation(t *testing.T) { &DataEntryScriptAction{Entry: &DeleteDataEntry{Key: "xxx"}}, &TransferScriptAction{Recipient: rcp0, Amount: 100, Asset: OptionalAsset{}}, }, restrictions: ActionsValidationRestrictions{DisableSelfTransfers: true, ScriptAddress: addr0}, valid: false}, + {actions: []ScriptAction{ + &LeaseScriptAction{Recipient: rcp0, Amount: 100}, + }, restrictions: ActionsValidationRestrictions{ScriptAddress: addr0}, valid: false}, + {actions: []ScriptAction{ + &LeaseScriptAction{Recipient: rcp0, Amount: 0}, + &LeaseScriptAction{Recipient: rcp0, Amount: -100}, + }, restrictions: ActionsValidationRestrictions{}, valid: false}, } { err := ValidateActions(test.actions, test.restrictions) if test.valid { diff --git a/pkg/ride/constants.go b/pkg/ride/constants.go index 77e11e098..3c2fce558 100644 --- a/pkg/ride/constants.go +++ b/pkg/ride/constants.go @@ -90,60 +90,58 @@ func checkConstantV4(name string) (uint16, bool) { return 0, false } -func newSha384(RideEnvironment) rideType { - return rideNamedType{name: "Sha384"} -} +var ConstantsV5 = []string{"Buy", "CEILING", "DOWN", "FLOOR", "HALFDOWN", "HALFEVEN", "HALFUP", "MD5", "NOALG", "SHA1", "SHA224", "SHA256", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHA384", "SHA512", "Sell", "UP", "height", "lastBlock", "nil", "this", "tx", "unit"} -func createSha384(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha384"}, nil -} +const _constants_V5 = "BuyCEILINGDOWNFLOORHALFDOWNHALFEVENHALFUPMD5NOALGSHA1SHA224SHA256SHA3224SHA3256SHA3384SHA3512SHA384SHA512SellUPheightlastBlocknilthistxunit" -func newCeiling(RideEnvironment) rideType { - return rideNamedType{name: "Ceiling"} -} +var _constructors_V5 = [...]rideConstructor{newBuy, newCeiling, newDown, newFloor, newHalfDown, newHalfEven, newHalfUp, newMd5, newNoAlg, newSha1, newSha224, newSha256, newSha3224, newSha3256, newSha3384, newSha3512, newSha384, newSha512, newSell, newUp, newHeight, newLastBlock, newNil, newThis, newTx, newUnit} +var _c_index_V5 = [...]int{0, 3, 10, 14, 19, 27, 35, 41, 44, 49, 53, 59, 65, 72, 79, 86, 93, 99, 105, 109, 111, 117, 126, 129, 133, 135, 139} -func createCeiling(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Ceiling"}, nil -} - -func newUp(RideEnvironment) rideType { - return rideNamedType{name: "Up"} +func constantV5(id int) rideConstructor { + if id < 0 || id > 25 { + return nil + } + return _constructors_V5[id] } - -func createUp(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Up"}, nil +func checkConstantV5(name string) (uint16, bool) { + for i := 0; i <= 25; i++ { + if _constants_V5[_c_index_V5[i]:_c_index_V5[i+1]] == name { + return uint16(i), true + } + } + return 0, false } -func newNoAlg(RideEnvironment) rideType { - return rideNamedType{name: "NoAlg"} +func newSha3384(RideEnvironment) rideType { + return rideNamedType{name: "Sha3384"} } -func createNoAlg(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "NoAlg"}, nil +func createSha3384(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3384"}, nil } -func newSha1(RideEnvironment) rideType { - return rideNamedType{name: "Sha1"} +func newCeiling(RideEnvironment) rideType { + return rideNamedType{name: "Ceiling"} } -func createSha1(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha1"}, nil +func createCeiling(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Ceiling"}, nil } -func newSha224(RideEnvironment) rideType { - return rideNamedType{name: "Sha224"} +func newSha256(RideEnvironment) rideType { + return rideNamedType{name: "Sha256"} } -func createSha224(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha224"}, nil +func createSha256(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha256"}, nil } -func newSha3256(RideEnvironment) rideType { - return rideNamedType{name: "Sha3256"} +func newSha512(RideEnvironment) rideType { + return rideNamedType{name: "Sha512"} } -func createSha3256(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3256"}, nil +func createSha512(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha512"}, nil } func newSha3224(RideEnvironment) rideType { @@ -154,28 +152,36 @@ func createSha3224(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3224"}, nil } -func newSha3384(RideEnvironment) rideType { - return rideNamedType{name: "Sha3384"} +func newSha3512(RideEnvironment) rideType { + return rideNamedType{name: "Sha3512"} } -func createSha3384(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3384"}, nil +func createSha3512(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3512"}, nil } -func newBuy(RideEnvironment) rideType { - return rideNamedType{name: "Buy"} +func newSell(RideEnvironment) rideType { + return rideNamedType{name: "Sell"} } -func createBuy(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Buy"}, nil +func createSell(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sell"}, nil } -func newFloor(RideEnvironment) rideType { - return rideNamedType{name: "Floor"} +func newHalfEven(RideEnvironment) rideType { + return rideNamedType{name: "HalfEven"} } -func createFloor(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Floor"}, nil +func createHalfEven(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "HalfEven"}, nil +} + +func newHalfUp(RideEnvironment) rideType { + return rideNamedType{name: "HalfUp"} +} + +func createHalfUp(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "HalfUp"}, nil } func newHalfDown(RideEnvironment) rideType { @@ -186,44 +192,52 @@ func createHalfDown(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "HalfDown"}, nil } -func newSha256(RideEnvironment) rideType { - return rideNamedType{name: "Sha256"} +func newMd5(RideEnvironment) rideType { + return rideNamedType{name: "Md5"} } -func createSha256(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha256"}, nil +func createMd5(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Md5"}, nil } -func newSha512(RideEnvironment) rideType { - return rideNamedType{name: "Sha512"} +func newSha384(RideEnvironment) rideType { + return rideNamedType{name: "Sha384"} } -func createSha512(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha512"}, nil +func createSha384(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha384"}, nil } -func newSha3512(RideEnvironment) rideType { - return rideNamedType{name: "Sha3512"} +func newUp(RideEnvironment) rideType { + return rideNamedType{name: "Up"} } -func createSha3512(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3512"}, nil +func createUp(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Up"}, nil } -func newSell(RideEnvironment) rideType { - return rideNamedType{name: "Sell"} +func newSha3256(RideEnvironment) rideType { + return rideNamedType{name: "Sha3256"} } -func createSell(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sell"}, nil +func createSha3256(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3256"}, nil } -func newHalfEven(RideEnvironment) rideType { - return rideNamedType{name: "HalfEven"} +func newBuy(RideEnvironment) rideType { + return rideNamedType{name: "Buy"} } -func createHalfEven(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "HalfEven"}, nil +func createBuy(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Buy"}, nil +} + +func newFloor(RideEnvironment) rideType { + return rideNamedType{name: "Floor"} +} + +func createFloor(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Floor"}, nil } func newDown(RideEnvironment) rideType { @@ -234,18 +248,26 @@ func createDown(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "Down"}, nil } -func newHalfUp(RideEnvironment) rideType { - return rideNamedType{name: "HalfUp"} +func newNoAlg(RideEnvironment) rideType { + return rideNamedType{name: "NoAlg"} } -func createHalfUp(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "HalfUp"}, nil +func createNoAlg(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "NoAlg"}, nil } -func newMd5(RideEnvironment) rideType { - return rideNamedType{name: "Md5"} +func newSha1(RideEnvironment) rideType { + return rideNamedType{name: "Sha1"} } -func createMd5(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Md5"}, nil +func createSha1(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha1"}, nil +} + +func newSha224(RideEnvironment) rideType { + return rideNamedType{name: "Sha224"} +} + +func createSha224(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha224"}, nil } diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index f8331184e..a26f0d25c 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -1235,6 +1235,43 @@ func convertToAction(env RideEnvironment, obj rideType) (proto.ScriptAction, err MinFee: int64(fee), }, nil + case "Lease": + recipient, err := recipientProperty(obj, "recipient") + if err != nil { + return nil, errors.Wrap(err, "failed to convert Lease to LeaseScriptAction") + } + amount, err := intProperty(obj, "amount") + if err != nil { + return nil, errors.Wrap(err, "failed to convert Lease to LeaseScriptAction") + } + nonce, err := intProperty(obj, "nonce") + if err != nil { + return nil, errors.Wrap(err, "failed to convert Lease to LeaseScriptAction") + } + id, err := calcLeaseID(env, recipient, amount, nonce) + if err != nil { + return nil, errors.Wrap(err, "failed to convert Lease to LeaseScriptAction") + } + d, err := crypto.NewDigestFromBytes(id) + if err != nil { + return nil, errors.Wrap(err, "failed to convert Lease to LeaseScriptAction") + } + return &proto.LeaseScriptAction{ + ID: d, + Recipient: recipient, + Amount: int64(amount), + Nonce: int64(nonce), + }, nil + + case "LeaseCancel": + id, err := digestProperty(obj, "leaseId") + if err != nil { + return nil, errors.Wrap(err, "failed to convert LeaseCancel to LeaseCancelScriptAction") + } + return &proto.LeaseCancelScriptAction{ + LeaseID: id, + }, nil + default: return nil, errors.Errorf("unexpected type '%s'", obj.instanceOf()) } diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 8530d9550..841890d1d 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -106,3 +106,38 @@ func costV4(id int) int { } return _catalogue_V4[id] } + +var _functions_V5 = [...]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} + +const _names_V5 = "!!=-011001001100410051006100710081011021031041040104110421043105105010511052105310610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" + +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 277, 280, 283, 286, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 597, 614, 631, 648, 665, 682, 699, 716, 733, 761, 781, 802, 823, 843, 850, 855, 864, 875, 887, 891, 894, 901, 916, 927, 931, 936, 944, 952, 958, 970, 981, 984, 989, 996, 1010, 1014, 1018, 1024, 1030, 1037, 1044, 1051, 1058, 1064, 1070, 1080, 1091, 1095, 1097, 1117, 1134, 1142, 1157, 1166, 1180, 1187, 1196, 1206, 1216, 1225, 1234, 1247, 1256, 1270, 1275, 1280, 1291, 1310} + +func functionNameV5(i int) string { + if i < 0 || i > 227 { + return "" + } + return _names_V5[_index_V5[i]:_index_V5[i+1]] +} +func functionV5(id int) rideFunction { + if id < 0 || id > 227 { + return nil + } + return _functions_V5[id] +} +func checkFunctionV5(name string) (uint16, bool) { + for i := 0; i <= 227; i++ { + if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { + return uint16(i), true + } + } + return 0, false +} +func costV5(id int) int { + if id < 0 || id > 227 { + return -1 + } + return _catalogue_V5[id] +} diff --git a/pkg/ride/functions_generated.go b/pkg/ride/functions_generated.go index 3178158f9..27b364f0a 100644 --- a/pkg/ride/functions_generated.go +++ b/pkg/ride/functions_generated.go @@ -32,7 +32,7 @@ func bls12Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_1") } return rideBoolean(ok), nil } @@ -58,7 +58,7 @@ func bls12Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_2") } return rideBoolean(ok), nil } @@ -84,7 +84,7 @@ func bls12Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_3") } return rideBoolean(ok), nil } @@ -110,7 +110,7 @@ func bls12Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_4") } return rideBoolean(ok), nil } @@ -136,7 +136,7 @@ func bls12Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_5") } return rideBoolean(ok), nil } @@ -162,7 +162,7 @@ func bls12Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_6") } return rideBoolean(ok), nil } @@ -188,7 +188,7 @@ func bls12Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_7") } return rideBoolean(ok), nil } @@ -214,7 +214,7 @@ func bls12Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_8") } return rideBoolean(ok), nil } @@ -240,7 +240,7 @@ func bls12Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_9") } return rideBoolean(ok), nil } @@ -266,7 +266,7 @@ func bls12Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_10") } return rideBoolean(ok), nil } @@ -292,7 +292,7 @@ func bls12Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_11") } return rideBoolean(ok), nil } @@ -318,7 +318,7 @@ func bls12Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_12") } return rideBoolean(ok), nil } @@ -344,7 +344,7 @@ func bls12Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_13") } return rideBoolean(ok), nil } @@ -370,7 +370,7 @@ func bls12Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_14") } return rideBoolean(ok), nil } @@ -396,7 +396,7 @@ func bls12Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bls12Groth16Verify_15") } return rideBoolean(ok), nil } @@ -422,7 +422,7 @@ func bn256Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_1") } return rideBoolean(ok), nil } @@ -448,7 +448,7 @@ func bn256Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_2") } return rideBoolean(ok), nil } @@ -474,7 +474,7 @@ func bn256Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_3") } return rideBoolean(ok), nil } @@ -500,7 +500,7 @@ func bn256Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_4") } return rideBoolean(ok), nil } @@ -526,7 +526,7 @@ func bn256Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_5") } return rideBoolean(ok), nil } @@ -552,7 +552,7 @@ func bn256Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_6") } return rideBoolean(ok), nil } @@ -578,7 +578,7 @@ func bn256Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_7") } return rideBoolean(ok), nil } @@ -604,7 +604,7 @@ func bn256Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_8") } return rideBoolean(ok), nil } @@ -630,7 +630,7 @@ func bn256Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, erro } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_9") } return rideBoolean(ok), nil } @@ -656,7 +656,7 @@ func bn256Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_10") } return rideBoolean(ok), nil } @@ -682,7 +682,7 @@ func bn256Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_11") } return rideBoolean(ok), nil } @@ -708,7 +708,7 @@ func bn256Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_12") } return rideBoolean(ok), nil } @@ -734,7 +734,7 @@ func bn256Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_13") } return rideBoolean(ok), nil } @@ -760,7 +760,7 @@ func bn256Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_14") } return rideBoolean(ok), nil } @@ -786,7 +786,7 @@ func bn256Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, err } ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) if err != nil { - return rideUnit{}, err + return nil, errors.Wrap(err, "bn256Groth16Verify_15") } return rideBoolean(ok), nil } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 638d611f4..4d20acacb 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -569,50 +569,50 @@ func simplifiedIssue(_ RideEnvironment, args ...rideType) (rideType, error) { } name, ok := args[0].(rideString) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[0].instanceOf()) + return nil, errors.Errorf("simplifiedIssue: unexpected argument type '%s'", args[0].instanceOf()) } description, ok := args[1].(rideString) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[1].instanceOf()) + return nil, errors.Errorf("simplifiedIssue: unexpected argument type '%s'", args[1].instanceOf()) } quantity, ok := args[2].(rideInt) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[2].instanceOf()) + return nil, errors.Errorf("simplifiedIssue: unexpected argument type '%s'", args[2].instanceOf()) } decimals, ok := args[3].(rideInt) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[3].instanceOf()) + return nil, errors.Errorf("simplifiedIssue: unexpected argument type '%s'", args[3].instanceOf()) } reissuable, ok := args[4].(rideBoolean) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[4].instanceOf()) + return nil, errors.Errorf("simplifiedIssue: unexpected argument type '%s'", args[4].instanceOf()) } return newIssue(name, description, quantity, decimals, reissuable, rideUnit{}, 0), nil } func fullIssue(_ RideEnvironment, args ...rideType) (rideType, error) { if err := checkArgs(args, 7); err != nil { - return nil, errors.Wrap(err, "simplifiedIssue") + return nil, errors.Wrap(err, "fullIssue") } name, ok := args[0].(rideString) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[0].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[0].instanceOf()) } description, ok := args[1].(rideString) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[1].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[1].instanceOf()) } quantity, ok := args[2].(rideInt) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[2].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[2].instanceOf()) } decimals, ok := args[3].(rideInt) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[3].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[3].instanceOf()) } reissuable, ok := args[4].(rideBoolean) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[4].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[4].instanceOf()) } var script rideType switch s := args[5].(type) { @@ -621,11 +621,11 @@ func fullIssue(_ RideEnvironment, args ...rideType) (rideType, error) { case rideUnit: script = s default: - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[5].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[5].instanceOf()) } nonce, ok := args[6].(rideInt) if !ok { - return nil, errors.Errorf("calculateAssetID: unexpected argument type '%s'", args[6].instanceOf()) + return nil, errors.Errorf("fullIssue: unexpected argument type '%s'", args[6].instanceOf()) } return newIssue(name, description, quantity, decimals, reissuable, script, nonce), nil } @@ -674,14 +674,50 @@ func rebuildMerkleRoot(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(root[:]), nil } -func bls12Groth16Verify(_ RideEnvironment, _ ...rideType) (rideType, error) { - //TODO: implement - return rideBoolean(true), nil +func bls12Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 3); err != nil { + return nil, errors.Wrap(err, "bls12Groth16Verify") + } + key, ok := args[0].(rideBytes) + if !ok { + return nil, errors.Errorf("bls12Groth16Verify: unexpected argument type '%s'", args[0].instanceOf()) + } + proof, ok := args[1].(rideBytes) + if !ok { + return nil, errors.Errorf("bls12Groth16Verify: unexpected argument type '%s'", args[1].instanceOf()) + } + inputs, ok := args[2].(rideBytes) + if !ok { + return nil, errors.Errorf("bls12Groth16Verify: unexpected argument type '%s'", args[2].instanceOf()) + } + ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs) + if err != nil { + return nil, errors.Wrap(err, "bls12Groth16Verify") + } + return rideBoolean(ok), nil } -func bn256Groth16Verify(_ RideEnvironment, _ ...rideType) (rideType, error) { - //TODO: implement - return rideBoolean(true), nil +func bn256Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 3); err != nil { + return nil, errors.Wrap(err, "bn256Groth16Verify") + } + key, ok := args[0].(rideBytes) + if !ok { + return nil, errors.Errorf("bn256Groth16Verify: unexpected argument type '%s'", args[0].instanceOf()) + } + proof, ok := args[1].(rideBytes) + if !ok { + return nil, errors.Errorf("bn256Groth16Verify: unexpected argument type '%s'", args[1].instanceOf()) + } + inputs, ok := args[2].(rideBytes) + if !ok { + return nil, errors.Errorf("bn256Groth16Verify: unexpected argument type '%s'", args[2].instanceOf()) + } + ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs) + if err != nil { + return nil, errors.Wrap(err, "bn256Groth16Verify") + } + return rideBoolean(ok), nil } func ecRecover(_ RideEnvironment, args ...rideType) (rideType, error) { @@ -1149,3 +1185,102 @@ func checkAsset(v rideType) (rideType, bool) { return nil, false } } + +func calcLeaseID(env RideEnvironment, recipient proto.Recipient, amount, nonce rideInt) (rideBytes, error) { + pid, ok := env.txID().(rideBytes) + if !ok { + return nil, errors.New("calcLeaseID: no parent transaction ID found") + } + d, err := crypto.NewDigestFromBytes(pid) + if err != nil { + return nil, errors.Wrap(err, "calcLeaseID") + } + id := proto.GenerateLeaseScriptActionID(recipient, int64(amount), int64(nonce), d) + return id.Bytes(), nil +} + +func calculateLeaseID(env RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 1); err != nil { + return nil, errors.Wrap(err, "calculateLeaseID") + } + if t := args[0].instanceOf(); t != "Lease" { + return nil, errors.Errorf("calculateLeaseID: unexpected argument type '%s'", t) + } + lease, ok := args[0].(rideObject) + if !ok { + return nil, errors.New("calculateLeaseID: not an object") + } + if lease.instanceOf() != "Lease" { + return nil, errors.Errorf("calculateLeaseID: unexpected object type '%s'", lease.instanceOf()) + } + recipient, err := recipientProperty(lease, "recipient") + if err != nil { + return nil, errors.Wrap(err, "calculateLeaseID") + } + amount, err := intProperty(lease, "amount") + if err != nil { + return nil, errors.Wrap(err, "calculateLeaseID") + } + nonce, err := intProperty(lease, "nonce") + if err != nil { + return nil, errors.Wrap(err, "calculateLeaseID") + } + return calcLeaseID(env, recipient, amount, nonce) +} + +func newLease(recipient rideRecipient, amount, nonce rideInt) rideObject { + r := make(rideObject) + r[instanceFieldName] = rideString("Lease") + r["recipient"] = recipient + r["amount"] = amount + r["nonce"] = nonce + return r +} + +func simplifiedLease(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 2); err != nil { + return nil, errors.Wrap(err, "simplifiedLease") + } + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Wrap(err, "simplifiedLease") + } + amount, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("simplifiedLease: unexpected argument type '%s'", args[1].instanceOf()) + } + return newLease(rideRecipient(recipient), amount, 0), nil +} + +func fullLease(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 3); err != nil { + return nil, errors.Wrap(err, "fullLease") + } + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Wrap(err, "simplifiedLease") + } + amount, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("fullLease: unexpected argument type '%s'", args[1].instanceOf()) + } + nonce, ok := args[2].(rideInt) + if !ok { + return nil, errors.Errorf("fullLease: unexpected argument type '%s'", args[6].instanceOf()) + } + return newLease(rideRecipient(recipient), amount, nonce), nil +} + +func leaseCancel(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 1); err != nil { + return nil, errors.Wrap(err, "leaseCancel") + } + id, ok := args[0].(rideBytes) + if !ok { + return nil, errors.Errorf("leaseCancel: unexpected argument type '%s'", args[0].instanceOf()) + } + obj := make(rideObject) + obj[instanceFieldName] = rideString("LeaseCancel") + obj["leaseId"] = id + return obj, nil +} diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 3e378d270..4c2d4abfc 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -459,6 +459,24 @@ func catalogueV4() map[string]int { return m } +func functionsV5() map[string]string { + m := functionsV4() + m["1081"] = "calculateLeaseID" + m["1092"] = "simplifiedLease" + m["1093"] = "fullLease" + m["LeaseCancel"] = "leaseCancel" + return m +} + +func catalogueV5() map[string]int { + m := catalogueV4() + m["1081"] = 1 //TODO: put actual value here + m["1092"] = 1 + m["1093"] = 1 + m["LeaseCancel"] = 1 + return m +} + type constantDescription struct { typeName string constructor string @@ -512,6 +530,10 @@ func constantsV4() map[string]constantDescription { return constantsV3() } +func constantsV5() map[string]constantDescription { + return constantsV4() +} + func constructorsFromConstants(m map[string]string, c map[string]constantDescription) { for _, v := range c { if v.constructor == "" { @@ -733,6 +755,7 @@ func main() { createFunctionsList(sb, "V2", functionsV2(), catalogueV2()) createFunctionsList(sb, "V3", functionsV3(), catalogueV3()) createFunctionsList(sb, "V4", functionsV4(), catalogueV4()) + createFunctionsList(sb, "V5", functionsV5(), catalogueV5()) code := sb.String() b, err := format.Source([]byte(code)) if err != nil { @@ -751,6 +774,7 @@ func main() { createConstants(sb, "V2", constantsV2()) createConstants(sb, "V3", constantsV3()) createConstants(sb, "V4", constantsV4()) + createConstants(sb, "V5", constantsV5()) createConstructors(sb, constantsV4()) code = sb.String() b, err = format.Source([]byte(code)) @@ -797,7 +821,7 @@ func main() { sb.WriteString("}\n") sb.WriteString("ok, err := crypto.Bls12381{}.Groth16Verify(key, proof, inputs)\n") sb.WriteString("if err != nil {\n") - sb.WriteString("return rideUnit{}, err\n") + sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") sb.WriteString("return rideBoolean(ok), nil\n") sb.WriteString("}\n\n") @@ -825,7 +849,7 @@ func main() { sb.WriteString("}\n") sb.WriteString("ok, err := crypto.Bn256{}.Groth16Verify(key, proof, inputs)\n") sb.WriteString("if err != nil {\n") - sb.WriteString("return rideUnit{}, err\n") + sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") sb.WriteString("return rideBoolean(ok), nil\n") sb.WriteString("}\n\n") diff --git a/pkg/ride/selectors.go b/pkg/ride/selectors.go index 37869f59b..049846d8a 100644 --- a/pkg/ride/selectors.go +++ b/pkg/ride/selectors.go @@ -10,6 +10,8 @@ func selectFunctions(v int) (func(id int) rideFunction, error) { return functionV3, nil case 4: return functionV4, nil + case 5: + return functionV5, nil default: return nil, errors.Errorf("unsupported library version '%d'", v) } @@ -23,6 +25,8 @@ func selectFunctionChecker(v int) (func(name string) (uint16, bool), error) { return checkFunctionV3, nil case 4: return checkFunctionV4, nil + case 5: + return checkFunctionV5, nil default: return nil, errors.Errorf("unsupported library version '%d'", v) } @@ -36,24 +40,13 @@ func selectFunctionNameProvider(v int) (func(int) string, error) { return functionNameV3, nil case 4: return functionNameV4, nil + case 5: + return functionNameV5, nil default: return nil, errors.Errorf("unsupported library version '%d'", v) } } -//func selectCostProvider(v int) (func(int) int, error) { -// switch v { -// case 1, 2: -// return costV2, nil -// case 3: -// return costV3, nil -// case 4: -// return costV4, nil -// default: -// return nil, errors.Errorf("unsupported library version '%d'", v) -// } -//} -// func selectConstants(v int) (func(int) rideConstructor, error) { switch v { case 1: @@ -64,6 +57,8 @@ func selectConstants(v int) (func(int) rideConstructor, error) { return constantV3, nil case 4: return constantV4, nil + case 5: + return constantV5, nil default: return nil, errors.Errorf("unsupported library version '%d'", v) } @@ -79,6 +74,8 @@ func selectConstantsChecker(v int) (func(name string) (uint16, bool), error) { return checkConstantV3, nil case 4: return checkConstantV4, nil + case 5: + return checkConstantV5, nil default: return nil, errors.Errorf("unsupported library version '%d'", v) } diff --git a/pkg/ride/tree_estimatorV1.go b/pkg/ride/tree_estimatorV1.go index 65367d65a..77a7bf1af 100644 --- a/pkg/ride/tree_estimatorV1.go +++ b/pkg/ride/tree_estimatorV1.go @@ -85,6 +85,8 @@ func newTreeEstimatorV1(tree *Tree) (*treeEstimatorV1, error) { r.scope = newEstimationScopeV1(ConstantsV3, CatalogueV3) case 4: r.scope = newEstimationScopeV1(ConstantsV4, CatalogueV4) + case 5: + r.scope = newEstimationScopeV1(ConstantsV4, CatalogueV5) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_estimatorV2.go b/pkg/ride/tree_estimatorV2.go index 9ec7cf5fe..e54d4d40a 100644 --- a/pkg/ride/tree_estimatorV2.go +++ b/pkg/ride/tree_estimatorV2.go @@ -100,6 +100,8 @@ func newTreeEstimatorV2(tree *Tree) (*treeEstimatorV2, error) { r.scope = newEstimationScopeV2(ConstantsV3, CatalogueV3) case 4: r.scope = newEstimationScopeV2(ConstantsV4, CatalogueV4) + case 5: + r.scope = newEstimationScopeV2(ConstantsV4, CatalogueV5) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_estimatorV3.go b/pkg/ride/tree_estimatorV3.go index de4a443e7..1137ab596 100644 --- a/pkg/ride/tree_estimatorV3.go +++ b/pkg/ride/tree_estimatorV3.go @@ -128,6 +128,8 @@ func newTreeEstimatorV3(tree *Tree) (*treeEstimatorV3, error) { r.scope = newEstimationScopeV3(CatalogueV3) case 4: r.scope = newEstimationScopeV3(CatalogueV4) + case 5: + r.scope = newEstimationScopeV3(CatalogueV5) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index f6d615426..ed96d38ac 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -535,6 +535,8 @@ func TestDappCallable(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), }, sr, ) @@ -602,6 +604,8 @@ func TestDappDefaultFunc(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), }, sr, ) @@ -730,6 +734,8 @@ func TestTransferSet(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), }, sr, ) @@ -781,6 +787,8 @@ func TestScriptResult(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), }, sr, ) @@ -1161,6 +1169,8 @@ func TestWhaleDApp(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -1299,6 +1309,8 @@ func TestExchangeDApp(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -1597,6 +1609,8 @@ func TestLigaDApp1(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) @@ -1783,6 +1797,8 @@ func TestLigaDApp1(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -1909,6 +1925,8 @@ func TestTestingDApp(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2022,6 +2040,8 @@ func TestDropElementDApp(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2143,6 +2163,8 @@ func TestMathDApp(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2269,6 +2291,8 @@ func TestDAppWithInvalidAddress(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2392,6 +2416,8 @@ func Test8Ball(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2746,6 +2772,8 @@ func TestBadType(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -2915,6 +2943,8 @@ func TestNoDeclaration(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -3107,6 +3137,8 @@ func TestZeroReissue(t *testing.T) { Reissues: expectedReissues, Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } @@ -3320,6 +3352,8 @@ func TestStageNet2(t *testing.T) { Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedResult, sr) } diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index 618cb315c..6f030c088 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -174,6 +174,8 @@ func selectConstantNames(v int) ([]string, error) { return ConstantsV3, nil case 4: return ConstantsV4, nil + case 5: + return ConstantsV5, nil default: return nil, errors.Errorf("unsupported library version %d", v) } @@ -195,6 +197,8 @@ func selectFunctionNames(v int) ([]string, error) { return keys(CatalogueV3), nil case 4: return keys(CatalogueV4), nil + case 5: + return keys(CatalogueV5), nil default: return nil, errors.Errorf("unsupported library version %d", v) } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index cf67a2a2d..6c23d19df 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -131,22 +131,56 @@ func (ia *invokeApplier) newTxDiffFromScriptBurn(scriptAddr *proto.Address, acti return diff, nil } +func (ia *invokeApplier) newTxDiffFromScriptLease(scriptAddr, recipientAddress *proto.Address, action *proto.LeaseScriptAction) (txDiff, error) { + diff := newTxDiff() + senderKey := wavesBalanceKey{address: *scriptAddr} + receiverKey := wavesBalanceKey{address: *recipientAddress} + if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, action.Amount, false)); err != nil { + return nil, err + } + if err := diff.appendBalanceDiff(receiverKey.bytes(), newBalanceDiff(0, action.Amount, 0, false)); err != nil { + return nil, err + } + return diff, nil +} + +func (ia *invokeApplier) newTxDiffFromScriptLeaseCancel(scriptAddr *proto.Address, leaseInfo *leasing) (txDiff, error) { + diff := newTxDiff() + senderKey := wavesBalanceKey{address: *scriptAddr} + senderLeaseOutDiff := -int64(leaseInfo.leaseAmount) + if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, senderLeaseOutDiff, false)); err != nil { + return nil, err + } + receiverKey := wavesBalanceKey{address: leaseInfo.recipient} + receiverLeaseInDiff := -int64(leaseInfo.leaseAmount) + if err := diff.appendBalanceDiff(receiverKey.bytes(), newBalanceDiff(0, receiverLeaseInDiff, 0, false)); err != nil { + return nil, err + } + return diff, nil +} + func (ia *invokeApplier) saveIntermediateDiff(diff txDiff) error { return ia.invokeDiffStor.saveTxDiff(diff) } func (ia *invokeApplier) resolveAliases(actions []proto.ScriptAction, initialisation bool) error { for i, a := range actions { - tr, ok := a.(proto.TransferScriptAction) - if !ok { - continue - } - addr, err := recipientToAddress(tr.Recipient, ia.stor.aliases, !initialisation) - if err != nil { - return err + switch ta := a.(type) { + case proto.TransferScriptAction: + addr, err := recipientToAddress(ta.Recipient, ia.stor.aliases, !initialisation) + if err != nil { + return err + } + ta.Recipient = proto.NewRecipientFromAddress(*addr) + actions[i] = ta + case proto.LeaseScriptAction: + addr, err := recipientToAddress(ta.Recipient, ia.stor.aliases, !initialisation) + if err != nil { + return err + } + ta.Recipient = proto.NewRecipientFromAddress(*addr) + actions[i] = ta } - tr.Recipient = proto.NewRecipientFromAddress(*addr) - actions[i] = tr } return nil } @@ -246,7 +280,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in } // Validate produced actions. var keySizeValidationVersion byte = 1 - if info.libVersion == 4 { + if info.libVersion >= 4 { keySizeValidationVersion = 2 } restrictions := proto.ActionsValidationRestrictions{ @@ -285,6 +319,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in case *proto.DataEntryScriptAction: // Perform data storage writes. ia.stor.accountsDataStor.appendEntryUncertain(*info.scriptAddr, a.Entry) + case *proto.TransferScriptAction: // Perform transfers. addr := a.Recipient.Address @@ -331,6 +366,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, err } } + case *proto.IssueScriptAction: // Create asset's info. assetInfo := &assetInfo{ @@ -365,6 +401,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, err } } + case *proto.ReissueScriptAction: // Check validity of reissue. assetInfo, err := ia.stor.assets.newestAssetInfo(a.AssetID, !info.initialisation) @@ -410,6 +447,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, err } } + case *proto.BurnScriptAction: // Check burn. assetInfo, err := ia.stor.assets.newestAssetInfo(a.AssetID, !info.initialisation) @@ -457,6 +495,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, err } } + case *proto.SponsorshipScriptAction: assetInfo, err := ia.stor.assets.newestAssetInfo(a.AssetID, !info.initialisation) if err != nil { @@ -477,6 +516,63 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, errors.Errorf("can not sponsor smart asset %s", a.AssetID.String()) } ia.stor.sponsoredAssets.sponsorAssetUncertain(a.AssetID, uint64(a.MinFee)) + + case *proto.LeaseScriptAction: + recipientAddress := a.Recipient.Address + if recipientAddress == nil { + return proto.DAppError, info.failedChanges, errors.New("transfer has unresolved aliases") + } + if info.scriptAddr == recipientAddress { + return proto.DAppError, info.failedChanges, errors.New("leasing to itself is not allowed") + } + if a.Amount <= 0 { + return proto.DAppError, info.failedChanges, errors.New("non-positive leasing amount") + } + totalChanges.appendAddr(*recipientAddress) + + // Add new leasing info + l := &leasing{true, uint64(a.Amount), *recipientAddress, *info.scriptAddr} + ia.stor.leases.addLeasingUncertain(a.ID, l) + + txDiff, err := ia.newTxDiffFromScriptLease(info.scriptAddr, recipientAddress, a) + if err != nil { + return proto.DAppError, info.failedChanges, err + } + if err := ia.saveIntermediateDiff(txDiff); err != nil { + return proto.DAppError, info.failedChanges, err + } + for key, balanceDiff := range txDiff { + if err := totalChanges.diff.appendBalanceDiffStr(key, balanceDiff); err != nil { + return proto.DAppError, info.failedChanges, err + } + } + + case *proto.LeaseCancelScriptAction: + li, err := ia.stor.leases.newestLeasingInfo(a.LeaseID, !info.initialisation) + if err != nil { + return proto.DAppError, info.failedChanges, err + } + + // Update leasing info + if err := ia.stor.leases.cancelLeasingUncertain(a.LeaseID, !info.initialisation); err != nil { + return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to cancel leasing") + } + + totalChanges.appendAddr(li.sender) + totalChanges.appendAddr(li.recipient) + txDiff, err := ia.newTxDiffFromScriptLeaseCancel(info.scriptAddr, li) + if err != nil { + return proto.DAppError, info.failedChanges, err + } + if err := ia.saveIntermediateDiff(txDiff); err != nil { + return proto.DAppError, info.failedChanges, err + } + for key, balanceDiff := range txDiff { + if err := totalChanges.diff.appendBalanceDiffStr(key, balanceDiff); err != nil { + return proto.DAppError, info.failedChanges, err + } + } + default: return proto.DAppError, info.failedChanges, errors.Errorf("unsupported script action '%T'", a) } diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 2ac712466..25a05c251 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -141,6 +141,13 @@ type rcpKey struct { key string } +type fullBalance struct { + regular uint64 + generating uint64 + available uint64 + effective uint64 +} + type invokeApplierTestData struct { // Indicates that invocation should happen multiple times. invokeMultipleTimes bool @@ -156,9 +163,10 @@ type invokeApplierTestData struct { failRes bool // Result state. - correctBalances map[rcpAsset]uint64 - dataEntries map[rcpKey]proto.DataEntry - correctAddrs []proto.Address + correctBalances map[rcpAsset]uint64 + correctFullBalances map[proto.Recipient]fullBalance + dataEntries map[rcpKey]proto.DataEntry + correctAddrs []proto.Address } func (id *invokeApplierTestData) applyTest(t *testing.T, to *invokeApplierTestObjects, info *fallibleValidationParams) { @@ -181,7 +189,15 @@ func (id *invokeApplierTestData) applyTest(t *testing.T, to *invokeApplierTestOb for aa, correct := range id.correctBalances { balance, err := to.state.NewestAccountBalance(aa.rcp, aa.asset()) assert.NoError(t, err) - assert.Equal(t, correct, balance) + assert.Equal(t, int(correct), int(balance)) + } + for aa, correct := range id.correctFullBalances { + fb, err := to.state.NewestFullWavesBalance(aa) + assert.NoError(t, err) + assert.Equal(t, int(correct.available), int(fb.Available)) + assert.Equal(t, int(correct.effective), int(fb.Effective)) + assert.Equal(t, int(correct.generating), int(fb.Generating)) + assert.Equal(t, int(correct.regular), int(fb.Regular)) } for ak, correct := range id.dataEntries { entry, err := to.state.RetrieveNewestEntry(ak.rcp, ak.key) @@ -200,8 +216,16 @@ func (id *invokeApplierTestData) applyTest(t *testing.T, to *invokeApplierTestOb for aa, correct := range id.correctBalances { balance, err := to.state.AccountBalance(aa.rcp, aa.asset()) assert.NoError(t, err) - assert.Equal(t, correct, balance) + assert.Equal(t, int(correct), int(balance)) } + //for aa, correct := range id.correctFullBalances { + // fb, err := to.state.FullWavesBalance(aa) + // assert.NoError(t, err) + // assert.Equal(t, correct.available, fb.Available) + // assert.Equal(t, correct.effective, fb.Effective) + // assert.Equal(t, correct.generating, fb.Generating) + // assert.Equal(t, correct.regular, fb.Regular) + //} for ak, correct := range id.dataEntries { entry, err := to.state.RetrieveEntry(ak.rcp, ak.key) assert.NoError(t, err) @@ -702,6 +726,173 @@ func TestFailedApplyInvokeScript(t *testing.T) { } } +// Tests on leasing actions use the following script +/* +{-# STDLIB_VERSION 5 #-} +{-# SCRIPT_TYPE ACCOUNT #-} +{-# CONTENT_TYPE DAPP #-} + +@Callable(i) +func simpleLeaseToAddress(rcp: String, amount: Int) = { + let addr = addressFromStringValue(rcp) + [Lease(addr, amount)] +} + +@Callable(i) +func detailedLeaseToAddress(rcp: String, amount: Int) = { + let addr = addressFromStringValue(rcp) + let lease = Lease(addr, amount, 0) + let id = calculateLeaseId(lease) + [lease] +} + +@Callable(i) +func simpleLeaseToAlias(rcp: String, amount: Int) = { + let alias = Alias(rcp) + [Lease(alias, amount)] +} + +@Callable(i) +func detailedLeaseToAlias(rcp: String, amount: Int) = { + let alias = Alias(rcp) + let lease = Lease(alias, amount, 0) + let id = calculateLeaseId(lease) + [lease] +} + +@Callable(i) +func simpleLeaseToSender(amount: Int) = { + [Lease(i.caller, amount)] +} + +@Callable(i) +func detailedLeaseToSender(amount: Int) = { + let lease = Lease(i.caller, amount, 0) + let id = calculateLeaseId(lease) + [lease] +} + +@Callable(i) +func cancel(id: ByteVector) = [LeaseCancel(id)] + +*/ + +func TestApplyInvokeScriptWithLease(t *testing.T) { + to, path := createInvokeApplierTestObjects(t) + to.activateFeature(t, int16(settings.ContinuationTransaction)) + + defer func() { + err := to.state.Close() + require.NoError(t, err, "state.Close() failed") + err = os.RemoveAll(path) + require.NoError(t, err, "failed to remove test data dir") + }() + + info := to.fallibleValidationParams(t) + to.setDApp(t, "ride5_leasing.base64", testGlobal.recipientInfo) + + var thousandWaves int64 = 1_000 * 100_000_000 + // Invoker pays only fee, but receives a leasing of 1000 waves + to.setAndCheckInitialWavesBalance(t, testGlobal.senderInfo.addr, invokeFee) + to.setAndCheckInitialWavesBalance(t, testGlobal.recipientInfo.addr, uint64(2*thousandWaves)) + + sender, dapp := invokeSenderRecipient() + fc := proto.FunctionCall{ + Name: "simpleLeaseToSender", + Arguments: []proto.Argument{&proto.IntegerArgument{Value: thousandWaves}}, + } + tests := []invokeApplierTestData{ + { + payments: []proto.ScriptPayment{}, + fc: fc, + errorRes: false, + failRes: false, + correctBalances: map[rcpAsset]uint64{ + {sender, nil}: 0, + }, + correctFullBalances: map[proto.Recipient]fullBalance{ + sender: {regular: 0, generating: 0, available: 0, effective: uint64(thousandWaves)}, + dapp: {regular: uint64(2 * thousandWaves), generating: 0, available: uint64(thousandWaves), effective: uint64(thousandWaves)}, + }, + correctAddrs: []proto.Address{ + testGlobal.senderInfo.addr, testGlobal.recipientInfo.addr, + }, + }, + } + for _, tc := range tests { + tc.applyTest(t, to, info) + } +} + +func TestApplyInvokeScriptWithLeaseAndLeaseCancel(t *testing.T) { + to, path := createInvokeApplierTestObjects(t) + to.activateFeature(t, int16(settings.ContinuationTransaction)) + + defer func() { + err := to.state.Close() + require.NoError(t, err, "state.Close() failed") + err = os.RemoveAll(path) + require.NoError(t, err, "failed to remove test data dir") + }() + + info := to.fallibleValidationParams(t) + to.setDApp(t, "ride5_leasing.base64", testGlobal.recipientInfo) + + var thousandWaves int64 = 1_000 * 100_000_000 + // Invoker pays only fee, but receives a leasing of 1000 waves + to.setAndCheckInitialWavesBalance(t, testGlobal.senderInfo.addr, 2*invokeFee) + to.setAndCheckInitialWavesBalance(t, testGlobal.recipientInfo.addr, uint64(2*thousandWaves)) + + sender, dapp := invokeSenderRecipient() + fc1 := proto.FunctionCall{ + Name: "simpleLeaseToSender", + Arguments: []proto.Argument{&proto.IntegerArgument{Value: thousandWaves}}, + } + tx := createInvokeScriptWithProofs(t, []proto.ScriptPayment{}, fc1, feeAsset, invokeFee) + id := proto.GenerateLeaseScriptActionID(sender, thousandWaves, 0, *tx.ID) + fc2 := proto.FunctionCall{ + Name: "cancel", + Arguments: []proto.Argument{&proto.BinaryArgument{Value: id.Bytes()}}, + } + tests := []invokeApplierTestData{ + { + payments: []proto.ScriptPayment{}, + fc: fc1, + errorRes: false, + failRes: false, + correctBalances: map[rcpAsset]uint64{ + {sender, nil}: invokeFee, + }, + correctFullBalances: map[proto.Recipient]fullBalance{ + sender: {regular: invokeFee, generating: 0, available: invokeFee, effective: uint64(thousandWaves) + invokeFee}, + dapp: {regular: uint64(2 * thousandWaves), generating: 0, available: uint64(thousandWaves), effective: uint64(thousandWaves)}, + }, + correctAddrs: []proto.Address{ + testGlobal.senderInfo.addr, testGlobal.recipientInfo.addr, + }, + }, + { + payments: []proto.ScriptPayment{}, + fc: fc2, + errorRes: false, + failRes: false, + correctBalances: map[rcpAsset]uint64{ + {sender, nil}: 0, + }, + correctFullBalances: map[proto.Recipient]fullBalance{ + sender: {regular: 0, generating: 0, available: 0, effective: 0}, + dapp: {regular: uint64(2 * thousandWaves), generating: 0, available: uint64(2 * thousandWaves), effective: uint64(2 * thousandWaves)}, + }, + correctAddrs: []proto.Address{ + testGlobal.senderInfo.addr, testGlobal.recipientInfo.addr, + }, + }, + } + for _, tc := range tests { + tc.applyTest(t, to, info) + } +} + // TODO: add test on sponsorship made by DApp: create new DApp that will issue and sponsor asset, // test also the function call that issues and sets sponsorship in one turn. diff --git a/pkg/state/invoke_results_test.go b/pkg/state/invoke_results_test.go index f616b6b2c..2a51bdea1 100644 --- a/pkg/state/invoke_results_test.go +++ b/pkg/state/invoke_results_test.go @@ -93,6 +93,14 @@ func TestSaveResult(t *testing.T) { {AssetID: testGlobal.asset0.asset.ID, MinFee: 12345}, {AssetID: testGlobal.asset0.asset.ID, MinFee: 0}, }, + Leases: []*proto.LeaseScriptAction{ + {ID: testGlobal.asset0.asset.ID, Recipient: rcp, Amount: 100500, Nonce: 10}, + {ID: testGlobal.asset1.asset.ID, Recipient: rcp, Amount: 12345, Nonce: 67890}, + }, + LeaseCancels: []*proto.LeaseCancelScriptAction{ + {LeaseID: invokeID}, + {LeaseID: testGlobal.asset0.asset.ID}, + }, } err = to.invokeResults.saveResult(invokeID, savedRes, blockID0) require.NoError(t, err) diff --git a/pkg/state/leases.go b/pkg/state/leases.go index e4413e2a5..d8e20ed45 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -74,12 +74,19 @@ func (l *leasingRecord) unmarshalBinary(data []byte) error { type leases struct { hs *historyStorage + uncertainLeases map[crypto.Digest]*leasing + calculateHashes bool hasher *stateHasher } func newLeases(hs *historyStorage, calcHashes bool) *leases { - return &leases{hs: hs, calculateHashes: calcHashes, hasher: newStateHasher()} + return &leases{ + hs: hs, + uncertainLeases: make(map[crypto.Digest]*leasing), + calculateHashes: calcHashes, + hasher: newStateHasher(), + } } func (l *leases) cancelLeases(bySenders map[proto.Address]struct{}, blockID proto.BlockID) error { @@ -155,6 +162,10 @@ func (l *leases) validLeaseIns() (map[proto.Address]int64, error) { // Leasing info from DB or local storage. func (l *leases) newestLeasingInfo(id crypto.Digest, filter bool) (*leasing, error) { + if leasing, ok := l.uncertainLeases[id]; ok { + return leasing, nil + } + key := leaseKey{leaseID: id} recordBytes, err := l.hs.newestTopEntryData(key.bytes(), filter) if err != nil { @@ -217,6 +228,10 @@ func (l *leases) addLeasing(id crypto.Digest, leasing *leasing, blockID proto.Bl return nil } +func (l *leases) addLeasingUncertain(id crypto.Digest, leasing *leasing) { + l.uncertainLeases[id] = leasing +} + func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, filter bool) error { leasing, err := l.newestLeasingInfo(id, filter) if err != nil { @@ -226,6 +241,16 @@ func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, filter b return l.addLeasing(id, leasing, blockID) } +func (l *leases) cancelLeasingUncertain(id crypto.Digest, filter bool) error { + leasing, err := l.newestLeasingInfo(id, filter) + if err != nil { + return errors.Errorf("failed to get leasing info: %v", err) + } + leasing.isActive = false + l.addLeasingUncertain(id, leasing) + return nil +} + func (l *leases) prepareHashes() error { return l.hasher.stop() } @@ -233,3 +258,16 @@ func (l *leases) prepareHashes() error { func (l *leases) reset() { l.hasher.reset() } + +func (l *leases) commitUncertain(blockID proto.BlockID) error { + for id, leasing := range l.uncertainLeases { + if err := l.addLeasing(id, leasing, blockID); err != nil { + return err + } + } + return nil +} + +func (l *leases) dropUncertain() { + l.uncertainLeases = make(map[crypto.Digest]*leasing) +} diff --git a/pkg/state/state.go b/pkg/state/state.go index e9ca0a9e5..45821d475 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -179,6 +179,9 @@ func (s *blockchainEntitiesStorage) commitUncertain(blockID proto.BlockID) error if err := s.scriptsStorage.commitUncertain(blockID); err != nil { return err } + if err := s.leases.commitUncertain(blockID); err != nil { + return err + } if err := s.sponsoredAssets.commitUncertain(blockID); err != nil { return err } @@ -189,6 +192,7 @@ func (s *blockchainEntitiesStorage) dropUncertain() { s.assets.dropUncertain() s.accountsDataStor.dropUncertain() s.scriptsStorage.dropUncertain() + s.leases.dropUncertain() s.sponsoredAssets.dropUncertain() } diff --git a/pkg/state/testdata/scripts/ride5_leasing.base64 b/pkg/state/testdata/scripts/ride5_leasing.base64 new file mode 100644 index 000000000..55f40bae6 --- /dev/null +++ b/pkg/state/testdata/scripts/ride5_leasing.base64 @@ -0,0 +1 @@ +AAIFAAAAAAAAACkIAhIECgIIARIECgIIARIECgIIARIECgIIARIDCgEBEgMKAQESAwoBAgAAAAAAAAAHAAAAAWkBAAAAFHNpbXBsZUxlYXNlVG9BZGRyZXNzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAARhZGRyCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAANyY3AJAARMAAAAAgkABEQAAAACBQAAAARhZGRyBQAAAAZhbW91bnQFAAAAA25pbAAAAAFpAQAAABZkZXRhaWxlZExlYXNlVG9BZGRyZXNzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAARhZGRyCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAANyY3AEAAAABWxlYXNlCQAERQAAAAMFAAAABGFkZHIFAAAABmFtb3VudAAAAAAAAAAAAAQAAAACaWQJAAQ5AAAAAQUAAAAFbGVhc2UJAARMAAAAAgUAAAAFbGVhc2UFAAAAA25pbAAAAAFpAQAAABJzaW1wbGVMZWFzZVRvQWxpYXMAAAACAAAAA3JjcAAAAAZhbW91bnQEAAAABWFsaWFzCQEAAAAFQWxpYXMAAAABBQAAAANyY3AJAARMAAAAAgkABEQAAAACBQAAAAVhbGlhcwUAAAAGYW1vdW50BQAAAANuaWwAAAABaQEAAAAUZGV0YWlsZWRMZWFzZVRvQWxpYXMAAAACAAAAA3JjcAAAAAZhbW91bnQEAAAABWFsaWFzCQEAAAAFQWxpYXMAAAABBQAAAANyY3AEAAAABWxlYXNlCQAERQAAAAMFAAAABWFsaWFzBQAAAAZhbW91bnQAAAAAAAAAAAAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwAAAABaQEAAAATc2ltcGxlTGVhc2VUb1NlbmRlcgAAAAEAAAAGYW1vdW50CQAETAAAAAIJAAREAAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQFAAAAA25pbAAAAAFpAQAAABVkZXRhaWxlZExlYXNlVG9TZW5kZXIAAAABAAAABmFtb3VudAQAAAAFbGVhc2UJAARFAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQAAAAAAAAAAAAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwAAAABaQEAAAAGY2FuY2VsAAAAAQAAAAJpZAkABEwAAAACCQEAAAALTGVhc2VDYW5jZWwAAAABBQAAAAJpZAUAAAADbmlsAAAAABW3T5I= \ No newline at end of file diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 5ee0c51b4..59febd218 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -68,6 +68,10 @@ func (tc *transactionChecker) scriptActivation(libVersion int, hasBlockV2 bool) if err != nil { return err } + continuationActivated, err := tc.stor.features.newestIsActivated(int16(settings.ContinuationTransaction)) + if err != nil { + return err + } if libVersion == 3 && !rideForDAppsActivated { return errors.New("Ride4DApps feature must be activated for scripts version 3") } @@ -77,6 +81,9 @@ func (tc *transactionChecker) scriptActivation(libVersion int, hasBlockV2 bool) if libVersion == 4 && !blockV5Activated { return errors.New("MultiPaymentInvokeScript feature must be activated for scripts version 4") } + if libVersion == 5 && !continuationActivated { + return errors.New("ContinuationTransaction feature must be activated for scripts version 5") + } return nil } From cc8216bed94d076803dba444e02445ce4db1873b Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 29 Dec 2020 13:43:55 +0300 Subject: [PATCH 03/52] Ride invoke dApp from dApp (#387) * added processCall * Added invokeFunctionFromDApp * cut packages by interfaces * Deleted tree argument from types and state * Moved the check of function name to evaluator * All implemention was moved to ride package * added struct for undestanding that it is invoke DApp from DApp * Added out from stack invocation * Moved invocation * Added attribute ScriptAction[] into evaluator * Added check for alias and ability to get script by alias * added idle tests * Fixed tests and code * corrected code * deleted useless interface * Added check script actions for tests * Added check script actions for tests * Fixed style * Added map and loop for test test convenience * Fixed tests * Added constructor AttachedPayment * Added interlayer * set stub * Added interlayer methods * deleted comments * commented out * fixed codestyle * Added case for DataEntryActions * Added implementation for DataEntry's interlayer of state * Added implementation for NewestAccount and NewestFullWaves balance * Added implementation for all methods in interlayer * added one more implementation for FullAssetInfo * Fixed codestyle * remarks for review * For review * added test for actions * Added func for sub from sender * Fixed fmt error * Added tests for diff dapp from dapp * Implementation of wrapped state was isolated from main functionality * Invoke() * fixed actions * Fixed Invoke func, added 1script test * Fixed the initialization loop issue in generated code. Sorting of constructors added to prevent order of generation constructor functions. (#403) * Added full implementation for Invoke func * Deleted useless test * Added test script 2 * deleted useless calls * added test script 3 * Started to go through 4 script test * passed 4 test script * passed test script 5 * 6 test script addded - 10 is limit * Fixed dapp versions in tests * Added replacement of invocation parameter * Test script updated Co-authored-by: Alexandr Dolgavin Co-authored-by: Alexandr Dolgavin Co-authored-by: Alexey Kiselev --- pkg/ride/constants.go | 144 +- pkg/ride/diff_state.go | 172 + pkg/ride/environment.go | 484 +- pkg/ride/functions.go | 60 +- pkg/ride/functions_proto.go | 127 +- pkg/ride/functions_test.go | 2 +- pkg/ride/generate/main.go | 21 +- pkg/ride/result.go | 15 +- pkg/ride/runtime.go | 8 + pkg/ride/runtime_moq_test.go | 324 ++ pkg/ride/tree_evaluation.go | 25 + pkg/ride/tree_evaluation_test.go | 4267 ++++++++++++++++- pkg/ride/tree_evaluator.go | 77 +- pkg/ride/types_moq_test.go | 178 + pkg/state/invoke_applier.go | 2 +- pkg/state/invoke_applier_test.go | 14 +- pkg/state/scripts_storage.go | 2 +- pkg/state/state.go | 48 +- .../testdata/scripts/ride5_leasing.base64 | 2 +- pkg/types/types.go | 7 +- 20 files changed, 5654 insertions(+), 325 deletions(-) create mode 100644 pkg/ride/diff_state.go diff --git a/pkg/ride/constants.go b/pkg/ride/constants.go index 3c2fce558..15fc28ecf 100644 --- a/pkg/ride/constants.go +++ b/pkg/ride/constants.go @@ -112,12 +112,12 @@ func checkConstantV5(name string) (uint16, bool) { return 0, false } -func newSha3384(RideEnvironment) rideType { - return rideNamedType{name: "Sha3384"} +func newBuy(RideEnvironment) rideType { + return rideNamedType{name: "Buy"} } -func createSha3384(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3384"}, nil +func createBuy(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Buy"}, nil } func newCeiling(RideEnvironment) rideType { @@ -128,44 +128,28 @@ func createCeiling(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "Ceiling"}, nil } -func newSha256(RideEnvironment) rideType { - return rideNamedType{name: "Sha256"} -} - -func createSha256(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha256"}, nil -} - -func newSha512(RideEnvironment) rideType { - return rideNamedType{name: "Sha512"} -} - -func createSha512(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha512"}, nil -} - -func newSha3224(RideEnvironment) rideType { - return rideNamedType{name: "Sha3224"} +func newDown(RideEnvironment) rideType { + return rideNamedType{name: "Down"} } -func createSha3224(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3224"}, nil +func createDown(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Down"}, nil } -func newSha3512(RideEnvironment) rideType { - return rideNamedType{name: "Sha3512"} +func newFloor(RideEnvironment) rideType { + return rideNamedType{name: "Floor"} } -func createSha3512(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha3512"}, nil +func createFloor(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Floor"}, nil } -func newSell(RideEnvironment) rideType { - return rideNamedType{name: "Sell"} +func newHalfDown(RideEnvironment) rideType { + return rideNamedType{name: "HalfDown"} } -func createSell(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sell"}, nil +func createHalfDown(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "HalfDown"}, nil } func newHalfEven(RideEnvironment) rideType { @@ -184,14 +168,6 @@ func createHalfUp(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "HalfUp"}, nil } -func newHalfDown(RideEnvironment) rideType { - return rideNamedType{name: "HalfDown"} -} - -func createHalfDown(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "HalfDown"}, nil -} - func newMd5(RideEnvironment) rideType { return rideNamedType{name: "Md5"} } @@ -200,20 +176,44 @@ func createMd5(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "Md5"}, nil } -func newSha384(RideEnvironment) rideType { - return rideNamedType{name: "Sha384"} +func newNoAlg(RideEnvironment) rideType { + return rideNamedType{name: "NoAlg"} } -func createSha384(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha384"}, nil +func createNoAlg(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "NoAlg"}, nil } -func newUp(RideEnvironment) rideType { - return rideNamedType{name: "Up"} +func newSha1(RideEnvironment) rideType { + return rideNamedType{name: "Sha1"} } -func createUp(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Up"}, nil +func createSha1(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha1"}, nil +} + +func newSha224(RideEnvironment) rideType { + return rideNamedType{name: "Sha224"} +} + +func createSha224(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha224"}, nil +} + +func newSha256(RideEnvironment) rideType { + return rideNamedType{name: "Sha256"} +} + +func createSha256(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha256"}, nil +} + +func newSha3224(RideEnvironment) rideType { + return rideNamedType{name: "Sha3224"} +} + +func createSha3224(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3224"}, nil } func newSha3256(RideEnvironment) rideType { @@ -224,50 +224,50 @@ func createSha3256(env RideEnvironment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3256"}, nil } -func newBuy(RideEnvironment) rideType { - return rideNamedType{name: "Buy"} +func newSha3384(RideEnvironment) rideType { + return rideNamedType{name: "Sha3384"} } -func createBuy(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Buy"}, nil +func createSha3384(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3384"}, nil } -func newFloor(RideEnvironment) rideType { - return rideNamedType{name: "Floor"} +func newSha3512(RideEnvironment) rideType { + return rideNamedType{name: "Sha3512"} } -func createFloor(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Floor"}, nil +func createSha3512(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha3512"}, nil } -func newDown(RideEnvironment) rideType { - return rideNamedType{name: "Down"} +func newSha384(RideEnvironment) rideType { + return rideNamedType{name: "Sha384"} } -func createDown(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Down"}, nil +func createSha384(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha384"}, nil } -func newNoAlg(RideEnvironment) rideType { - return rideNamedType{name: "NoAlg"} +func newSha512(RideEnvironment) rideType { + return rideNamedType{name: "Sha512"} } -func createNoAlg(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "NoAlg"}, nil +func createSha512(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sha512"}, nil } -func newSha1(RideEnvironment) rideType { - return rideNamedType{name: "Sha1"} +func newSell(RideEnvironment) rideType { + return rideNamedType{name: "Sell"} } -func createSha1(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha1"}, nil +func createSell(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Sell"}, nil } -func newSha224(RideEnvironment) rideType { - return rideNamedType{name: "Sha224"} +func newUp(RideEnvironment) rideType { + return rideNamedType{name: "Up"} } -func createSha224(env RideEnvironment, args ...rideType) (rideType, error) { - return rideNamedType{name: "Sha224"}, nil +func createUp(env RideEnvironment, args ...rideType) (rideType, error) { + return rideNamedType{name: "Up"}, nil } diff --git a/pkg/ride/diff_state.go b/pkg/ride/diff_state.go new file mode 100644 index 000000000..24b923047 --- /dev/null +++ b/pkg/ride/diff_state.go @@ -0,0 +1,172 @@ +package ride + +import ( + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/types" +) + +type diffDataEntries struct { + diffInteger map[string]proto.IntegerDataEntry // map[key + address.String()] + diffBool map[string]proto.BooleanDataEntry + diffString map[string]proto.StringDataEntry + diffBinary map[string]proto.BinaryDataEntry + diffDDelete map[string]proto.DeleteDataEntry +} + +type diffBalance struct { + assetID crypto.Digest + amount int64 +} + +type diffSponsorship struct { + MinFee int64 +} + +type diffNewAssetInfo struct { + dAppIssuer proto.Address + name string + description string + quantity int64 + decimals int32 + reissuable bool + script []byte + nonce int64 +} + +type diffOldAssetInfo struct { + diffQuantity int64 +} + +type diffState struct { + state types.SmartState + dataEntries diffDataEntries + balances map[string]diffBalance // map[address.String() + Digest.String()] or map[address.String()] only + sponsorships map[string]diffSponsorship // map[Digest.String()] + newAssetsInfo map[string]diffNewAssetInfo // map[assetID.String()] + oldAssetsInfo map[string]diffOldAssetInfo // map[assetID.String()] +} + +func (diffSt *diffState) addBalanceTo(searchAddress string, amount int64) { + oldDiffBalance := diffSt.balances[searchAddress] + oldDiffBalance.amount += amount + diffSt.balances[searchAddress] = oldDiffBalance +} + +func (diffSt *diffState) reissueNewAsset(assetID crypto.Digest, quantity int64, reissuable bool) { + + asset := diffSt.newAssetsInfo[assetID.String()] + asset.reissuable = reissuable + asset.quantity += quantity + diffSt.newAssetsInfo[assetID.String()] = asset +} + +func (diffSt *diffState) burnNewAsset(assetID crypto.Digest, quantity int64) { + + asset := diffSt.newAssetsInfo[assetID.String()] + asset.quantity -= quantity + diffSt.newAssetsInfo[assetID.String()] = asset +} + +func (diffSt *diffState) changeBalance(searchBalance *diffBalance, searchAddress string, amount int64, assetID crypto.Digest, account proto.Recipient) error { + if searchBalance != nil { + diffSt.addBalanceTo(searchAddress, amount) + return nil + } + + address, err := diffSt.state.NewestRecipientToAddress(account) + if err != nil { + return err + } + + var balance diffBalance + balance.assetID = assetID + balance.amount = amount + + diffSt.balances[address.String()+assetID.String()] = balance + return nil +} + +func (diffSt *diffState) findIntFromDataEntryByKey(key string, address string) *proto.IntegerDataEntry { + if integerEntry, ok := diffSt.dataEntries.diffInteger[key+address]; ok { + return &integerEntry + } + return nil +} + +func (diffSt *diffState) findBoolFromDataEntryByKey(key string, address string) *proto.BooleanDataEntry { + if boolEntry, ok := diffSt.dataEntries.diffBool[key+address]; ok { + return &boolEntry + } + return nil +} + +func (diffSt *diffState) findStringFromDataEntryByKey(key string, address string) *proto.StringDataEntry { + if stringEntry, ok := diffSt.dataEntries.diffString[key+address]; ok { + return &stringEntry + } + return nil +} + +func (diffSt *diffState) findBinaryFromDataEntryByKey(key string, address string) *proto.BinaryDataEntry { + if binaryEntry, ok := diffSt.dataEntries.diffBinary[key+address]; ok { + return &binaryEntry + } + return nil +} + +func (diffSt *diffState) findDeleteFromDataEntryByKey(key string, address string) *proto.DeleteDataEntry { + if deleteEntry, ok := diffSt.dataEntries.diffDDelete[key+address]; ok { + return &deleteEntry + } + return nil +} + +func (diffSt *diffState) findBalance(recipient proto.Recipient, asset []byte) (*diffBalance, string, error) { + address, err := diffSt.state.NewestRecipientToAddress(recipient) + if err != nil { + return nil, "", errors.Errorf("cannot get address from recipient") + } + if asset == nil { + if balance, ok := diffSt.balances[address.String()]; ok { + return &balance, address.String(), nil + } + emptyAsset := crypto.Digest{} + if balance, ok := diffSt.balances[address.String()+emptyAsset.String()]; ok { + return &balance, address.String(), nil + } + return nil, "", nil + } + + assetID, err := crypto.NewDigestFromBytes(asset) + if err != nil { + return nil, "", err + } + if balance, ok := diffSt.balances[address.String()+assetID.String()]; ok { + return &balance, address.String() + assetID.String(), nil + } + + return nil, "", nil +} + +func (diffSt *diffState) findSponsorship(assetID crypto.Digest) *int64 { + if sponsorship, ok := diffSt.sponsorships[assetID.String()]; ok { + return &sponsorship.MinFee + } + return nil +} + +func (diffSt *diffState) findNewAsset(assetID crypto.Digest) *diffNewAssetInfo { + if newAsset, ok := diffSt.newAssetsInfo[assetID.String()]; ok { + return &newAsset + } + return nil +} + +func (diffSt *diffState) findOldAsset(assetID crypto.Digest) *diffOldAssetInfo { + if oldAsset, ok := diffSt.oldAssetsInfo[assetID.String()]; ok { + return &oldAsset + } + return nil +} diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index f96da2847..21b53be22 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1,21 +1,427 @@ package ride import ( + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/types" ) +func (wrappedSt *wrappedState) AddingBlockHeight() (uint64, error) { + return wrappedSt.diff.state.AddingBlockHeight() +} + +func (wrappedSt *wrappedState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return wrappedSt.diff.state.NewestScriptPKByAddr(addr, filter) +} +func (wrappedSt *wrappedState) NewestTransactionByID(id []byte) (proto.Transaction, error) { + return wrappedSt.diff.state.NewestTransactionByID(id) +} +func (wrappedSt *wrappedState) NewestTransactionHeightByID(id []byte) (uint64, error) { + return wrappedSt.diff.state.NewestTransactionHeightByID(id) +} +func (wrappedSt *wrappedState) GetByteTree(recipient proto.Recipient) (proto.Script, error) { + return wrappedSt.diff.state.GetByteTree(recipient) +} +func (wrappedSt *wrappedState) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { + return wrappedSt.diff.state.NewestRecipientToAddress(recipient) +} + +func (wrappedSt *wrappedState) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) { + return wrappedSt.diff.state.NewestAddrByAlias(alias) +} + +func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) { + balance, err := wrappedSt.diff.state.NewestAccountBalance(account, asset) + if err != nil { + return 0, err + } + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return balance, nil +} + +func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance, err := wrappedSt.diff.state.NewestFullWavesBalance(account) + if err != nil { + return nil, err + } + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance.Regular) + resGenerating := wavesBalanceDiff.amount + int64(balance.Generating) + resAvailable := wavesBalanceDiff.amount + int64(balance.Available) + resEffective := wavesBalanceDiff.amount + int64(balance.Effective) + + return &proto.FullWavesBalance{Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: balance.LeaseIn, + LeaseOut: balance.LeaseOut}, nil + + } + return balance, nil +} + +func (wrappedSt *wrappedState) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return wrappedSt.diff.state.RetrieveNewestIntegerEntry(account, key) +} +func (wrappedSt *wrappedState) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return wrappedSt.diff.state.RetrieveNewestBooleanEntry(account, key) +} +func (wrappedSt *wrappedState) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return wrappedSt.diff.state.RetrieveNewestStringEntry(account, key) +} +func (wrappedSt *wrappedState) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return wrappedSt.diff.state.RetrieveNewestBinaryEntry(account, key) +} +func (wrappedSt *wrappedState) NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return wrappedSt.diff.state.NewestAssetIsSponsored(assetID) +} +func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore, err := wrappedSt.diff.state.NewestAssetInfo(assetID) + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return assetFromStore, nil + } + + return assetFromStore, nil + } + + issuerPK, err := wrappedSt.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") + } + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + sponsored, err := wrappedSt.NewestAssetIsSponsored(assetID) + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: sponsored, + }, nil +} +func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore, err := wrappedSt.diff.state.NewestFullAssetInfo(assetID) + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return assetFromStore, nil + } + + issuerPK, err := wrappedSt.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") + } + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + sponsored, err := wrappedSt.NewestAssetIsSponsored(assetID) + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: sponsored, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil +} + +func (wrappedSt *wrappedState) NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { + return wrappedSt.diff.state.NewestHeaderByHeight(height) +} +func (wrappedSt *wrappedState) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) { + return wrappedSt.diff.state.BlockVRF(blockHeader, height) +} + +func (wrappedSt *wrappedState) EstimatorVersion() (int, error) { + return wrappedSt.diff.state.EstimatorVersion() +} +func (wrappedSt *wrappedState) IsNotFound(err error) bool { + return wrappedSt.diff.state.IsNotFound(err) +} + +func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil +} + +type wrappedState struct { + diff diffState + envThis rideAddress +} + type Environment struct { - sch proto.Scheme - st types.SmartState - h rideInt - tx rideObject - id rideType - th rideType - b rideObject - check func(int) bool - inv rideObject + sch proto.Scheme + st types.SmartState + act []proto.ScriptAction + h rideInt + tx rideObject + id rideType + th rideType + b rideObject + check func(int) bool + inv rideObject + invokeCount uint64 +} + +func newWrappedState(state types.SmartState, envThis rideType) types.SmartState { + var dataEntries diffDataEntries + + dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} + dataEntries.diffBool = map[string]proto.BooleanDataEntry{} + dataEntries.diffString = map[string]proto.StringDataEntry{} + dataEntries.diffBinary = map[string]proto.BinaryDataEntry{} + dataEntries.diffDDelete = map[string]proto.DeleteDataEntry{} + + balances := map[string]diffBalance{} + sponsorships := map[string]diffSponsorship{} + newAssetInfo := map[string]diffNewAssetInfo{} + oldAssetInfo := map[string]diffOldAssetInfo{} + + diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo} + wrappedSt := wrappedState{diff: *diffSt, envThis: envThis.(rideAddress)} + return &wrappedSt } func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*Environment, error) { @@ -23,16 +429,19 @@ func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*Environment, if err != nil { return nil, err } + return &Environment{ - sch: scheme, - st: state, - h: rideInt(height), - tx: nil, - id: nil, - th: nil, - b: nil, - check: func(int) bool { return true }, - inv: nil, + sch: scheme, + st: state, + act: nil, + h: rideInt(height), + tx: nil, + id: nil, + th: nil, + b: nil, + check: func(int) bool { return true }, + inv: nil, + invokeCount: 0, }, nil } @@ -66,6 +475,7 @@ func (e *Environment) SetTransactionFromScriptTransfer(transfer *proto.FullScrip } func (e *Environment) SetTransactionWithoutProofs(tx proto.Transaction) error { + err := e.SetTransaction(tx) if err != nil { return err @@ -143,6 +553,32 @@ func (e *Environment) state() types.SmartState { return e.st } +func (e *Environment) actions() []proto.ScriptAction { + return e.act +} + +func (e *Environment) setNewDAppAddress(address proto.Address) { + e.SetThisFromAddress(address) +} + +func (e *Environment) applyToState(actions []proto.ScriptAction) error { + return e.st.ApplyToState(actions) +} + +func (e *Environment) appendActions(actions []proto.ScriptAction) { + e.act = append(e.act, actions...) +} + +func (e *Environment) smartAppendActions(actions []proto.ScriptAction) error { + _, ok := e.st.(*wrappedState) + if !ok { + wrappedSt := newWrappedState(e.state(), e.this()) + e.st = wrappedSt + } + e.appendActions(actions) + + return e.applyToState(actions) +} func (e *Environment) checkMessageLength(l int) bool { return e.check(l) } @@ -150,3 +586,15 @@ func (e *Environment) checkMessageLength(l int) bool { func (e *Environment) invocation() rideObject { return e.inv } + +func (e *Environment) SetInvocation(inv rideObject) { + e.inv = inv +} + +func (e *Environment) invCount() uint64 { + return e.invokeCount +} + +func (e *Environment) incrementInvCount() { + e.invokeCount++ +} diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 841890d1d..25785b34b 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -2,7 +2,12 @@ package ride -var _functions_V2 = [...]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionByID, transactionHeightByID, assetBalanceV3, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, fraction, throw, sizeBytes, takeBytes, dropBytes, concatBytes, concatStrings, takeString, dropString, sizeString, sizeList, getList, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, toBase58, fromBase58, toBase64, fromBase64, address, alias, assetPair, dataEntry, dataTransaction, addressFromPublicKey, addressFromString, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, takeRightString, takeRightBytes, throw0, wavesBalanceV3} +var _functions_V2 [68]rideFunction + +func init() { + _functions_V2 = [68]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionByID, transactionHeightByID, assetBalanceV3, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, fraction, throw, sizeBytes, takeBytes, dropBytes, concatBytes, concatStrings, takeString, dropString, sizeString, sizeList, getList, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, toBase58, fromBase58, toBase64, fromBase64, address, alias, assetPair, dataEntry, dataTransaction, addressFromPublicKey, addressFromString, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, takeRightString, takeRightBytes, throw0, wavesBalanceV3} +} + var _catalogue_V2 = [...]int{11, 26, 9, 1, 1, 1, 100, 100, 100, 1, 1, 1, 1, 10, 10, 10, 10, 1, 100, 100, 100, 100, 1, 100, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 100, 10, 10, 10, 10, 10, 10, 10, 1, 1, 2, 2, 9, 82, 124, 19, 19, 13, 30, 30, 30, 30, 35, 19, 19, 2, 109} var CatalogueV2 = map[string]int{"!": 11, "!=": 26, "-": 9, "0": 1, "1": 1, "100": 1, "1000": 100, "1001": 100, "1003": 100, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 100, "1051": 100, "1052": 100, "1053": 100, "106": 1, "1060": 100, "107": 1, "2": 1, "200": 1, "201": 1, "202": 1, "203": 10, "300": 10, "303": 1, "304": 1, "305": 1, "400": 2, "401": 2, "410": 1, "411": 1, "412": 1, "420": 1, "421": 1, "500": 100, "501": 10, "502": 10, "503": 10, "600": 10, "601": 10, "602": 10, "603": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "DataEntry": 2, "DataTransaction": 9, "addressFromPublicKey": 82, "addressFromString": 124, "dropRight": 19, "dropRightBytes": 19, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 35, "takeRight": 19, "takeRightBytes": 19, "throw": 2, "wavesBalance": 109} @@ -37,7 +42,12 @@ func costV2(id int) int { return _catalogue_V2[id] } -var _functions_V3 = [...]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetBalanceV3, assetInfoV3, blockInfoByHeight, transferByID, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, fraction, pow, log, createList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, throw, sizeBytes, takeBytes, dropBytes, concatBytes, concatStrings, takeString, dropString, sizeString, sizeList, getList, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, checkMerkleProof, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, createBuy, createCeiling, dataEntry, dataTransaction, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, createMd5, createNoAlg, scriptResult, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, transferSet, unit, createUp, writeSet, addressFromPublicKey, addressFromString, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrErrorMessage, wavesBalanceV3} +var _functions_V3 [128]rideFunction + +func init() { + _functions_V3 = [128]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetBalanceV3, assetInfoV3, blockInfoByHeight, transferByID, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, fraction, pow, log, createList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, throw, sizeBytes, takeBytes, dropBytes, concatBytes, concatStrings, takeString, dropString, sizeString, sizeList, getList, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, checkMerkleProof, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, createBuy, createCeiling, dataEntry, dataTransaction, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, createMd5, createNoAlg, scriptResult, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, transferSet, unit, createUp, writeSet, addressFromPublicKey, addressFromString, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrErrorMessage, wavesBalanceV3} +} + var _catalogue_V3 = [...]int{1, 1, 1, 1, 1, 1, 100, 100, 100, 100, 100, 1, 1, 1, 1, 10, 10, 10, 10, 1, 100, 100, 100, 100, 1, 100, 10, 1, 100, 100, 2, 20, 10, 10, 20, 20, 100, 20, 20, 20, 1, 1, 1, 1, 10, 10, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 100, 10, 10, 10, 300, 10, 10, 10, 10, 10, 10, 30, 10, 10, 10, 10, 100, 100, 100, 100, 124, 10, 10, 10, 10, 1, 1, 2, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 82, 124, 19, 19, 13, 30, 30, 30, 30, 1, 20, 19, 19, 1, 13, 13, 109} var CatalogueV3 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1003": 100, "1004": 100, "1005": 100, "1006": 100, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 100, "1051": 100, "1052": 100, "1053": 100, "106": 1, "1060": 100, "1061": 10, "107": 1, "108": 100, "109": 100, "1100": 2, "1200": 20, "1201": 10, "1202": 10, "1203": 20, "1204": 20, "1205": 100, "1206": 20, "1207": 20, "1208": 20, "2": 1, "200": 1, "201": 1, "202": 1, "203": 10, "300": 10, "303": 1, "304": 1, "305": 1, "400": 2, "401": 2, "410": 1, "411": 1, "412": 1, "420": 1, "421": 1, "500": 100, "501": 10, "502": 10, "503": 10, "504": 300, "600": 10, "601": 10, "602": 10, "603": 10, "604": 10, "605": 10, "700": 30, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 100, "@extrNative(1051)": 100, "@extrNative(1052)": 100, "@extrNative(1053)": 100, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "Buy": 0, "Ceiling": 0, "DataEntry": 2, "DataTransaction": 9, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "Md5": 0, "NoAlg": 0, "ScriptResult": 2, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "TransferSet": 1, "Unit": 0, "Up": 0, "WriteSet": 1, "addressFromPublicKey": 82, "addressFromString": 124, "dropRight": 19, "dropRightBytes": 19, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 20, "takeRight": 19, "takeRightBytes": 19, "throw": 1, "value": 13, "valueOrErrorMessage": 13, "wavesBalance": 109} @@ -72,28 +82,33 @@ func costV3(id int) int { return _catalogue_V3[id] } -var _functions_V4 = [...]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} -var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _functions_V4 [226]rideFunction -const _names_V4 = "!!=-011001001100410051006100710081011021031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +func init() { + _functions_V4 = [226]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} +} + +var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} + +const _names_V4 = "!!=-0110010011004100510061007100810110210201031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 265, 268, 271, 274, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 585, 602, 619, 636, 653, 670, 687, 704, 721, 749, 769, 790, 811, 831, 838, 843, 852, 863, 875, 879, 882, 889, 904, 915, 919, 924, 932, 940, 946, 958, 961, 966, 973, 987, 991, 995, 1001, 1007, 1014, 1021, 1028, 1035, 1041, 1047, 1057, 1068, 1072, 1074, 1094, 1111, 1119, 1134, 1143, 1157, 1164, 1173, 1183, 1193, 1202, 1211, 1224, 1233, 1247, 1252, 1257, 1268, 1287} +var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 43, 46, 49, 53, 57, 61, 65, 68, 72, 76, 80, 84, 87, 91, 95, 99, 102, 106, 109, 113, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 269, 272, 275, 278, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 488, 491, 494, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 589, 606, 623, 640, 657, 674, 691, 708, 725, 753, 773, 794, 815, 835, 842, 847, 856, 871, 882, 894, 898, 901, 908, 923, 934, 938, 943, 951, 959, 965, 977, 980, 985, 992, 1006, 1010, 1014, 1020, 1026, 1033, 1040, 1047, 1054, 1060, 1066, 1076, 1087, 1091, 1093, 1113, 1130, 1138, 1153, 1162, 1176, 1183, 1192, 1202, 1212, 1221, 1230, 1243, 1252, 1266, 1271, 1276, 1287, 1306} func functionNameV4(i int) string { - if i < 0 || i > 223 { + if i < 0 || i > 225 { return "" } return _names_V4[_index_V4[i]:_index_V4[i+1]] } func functionV4(id int) rideFunction { - if id < 0 || id > 223 { + if id < 0 || id > 225 { return nil } return _functions_V4[id] } func checkFunctionV4(name string) (uint16, bool) { - for i := 0; i <= 223; i++ { + for i := 0; i <= 225; i++ { if _names_V4[_index_V4[i]:_index_V4[i+1]] == name { return uint16(i), true } @@ -101,34 +116,39 @@ func checkFunctionV4(name string) (uint16, bool) { return 0, false } func costV4(id int) int { - if id < 0 || id > 223 { + if id < 0 || id > 225 { return -1 } return _catalogue_V4[id] } -var _functions_V5 = [...]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _functions_V5 [230]rideFunction + +func init() { + _functions_V5 = [230]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} +} + +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-011001001100410051006100710081011021031041040104110421043105105010511052105310610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-0110010011004100510061007100810110210201031041040104110421043105105010511052105310610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 277, 280, 283, 286, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 597, 614, 631, 648, 665, 682, 699, 716, 733, 761, 781, 802, 823, 843, 850, 855, 864, 875, 887, 891, 894, 901, 916, 927, 931, 936, 944, 952, 958, 970, 981, 984, 989, 996, 1010, 1014, 1018, 1024, 1030, 1037, 1044, 1051, 1058, 1064, 1070, 1080, 1091, 1095, 1097, 1117, 1134, 1142, 1157, 1166, 1180, 1187, 1196, 1206, 1216, 1225, 1234, 1247, 1256, 1270, 1275, 1280, 1291, 1310} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 43, 46, 49, 53, 57, 61, 65, 68, 72, 76, 80, 84, 87, 91, 95, 99, 102, 106, 109, 113, 117, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 281, 284, 287, 290, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 601, 618, 635, 652, 669, 686, 703, 720, 737, 765, 785, 806, 827, 847, 854, 859, 868, 883, 894, 906, 910, 913, 920, 935, 946, 950, 955, 963, 971, 977, 989, 1000, 1003, 1008, 1015, 1029, 1033, 1037, 1043, 1049, 1056, 1063, 1070, 1077, 1083, 1089, 1099, 1110, 1114, 1116, 1136, 1153, 1161, 1176, 1185, 1199, 1206, 1215, 1225, 1235, 1244, 1253, 1266, 1275, 1289, 1294, 1299, 1310, 1329} func functionNameV5(i int) string { - if i < 0 || i > 227 { + if i < 0 || i > 229 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 227 { + if id < 0 || id > 229 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 227; i++ { + for i := 0; i <= 229; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -136,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 227 { + if id < 0 || id > 229 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 4d20acacb..d0494703e 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -6,13 +6,113 @@ import ( "crypto/rsa" sh256 "crypto/sha256" "crypto/x509" - "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" c2 "github.com/wavesplatform/gowaves/pkg/ride/crypto" + "github.com/wavesplatform/gowaves/pkg/util/common" ) +func invoke(env RideEnvironment, args ...rideType) (rideType, error) { + env.incrementInvCount() + if env.invCount() > 9 { + return rideUnit{}, nil + } + oldAddress := env.this() + + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[0].instanceOf()) + } + + fnName, ok := args[1].(rideString) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[1].instanceOf()) + } + listArg, ok := args[2].(rideList) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[2].instanceOf()) + } + + var attachedPayments proto.ScriptPayments + + payments := args[3].(rideList) + + invocationParam := env.invocation() + invocationParam["caller"] = oldAddress.(rideAddress) + callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(oldAddress.(rideAddress)), false) + if err != nil { + return nil, errors.Wrapf(err, "failed to get caller public key by address") + } + invocationParam["callerPublicKey"] = rideBytes(common.Dup(callerPublicKey.Bytes())) + invocationParam["payments"] = payments + env.SetInvocation(invocationParam) + + for _, value := range payments { + payment, ok := value.(rideObject) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", payment.instanceOf()) + } + + assetID := payment["assetId"] + amount := payment["amount"] + + intAmount, ok := amount.(rideInt) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", amount.instanceOf()) + } + var asset crypto.Digest + + switch asID := assetID.(type) { + case rideBytes: + asset, _ = crypto.NewDigestFromBytes(asID) + case rideUnit: + asset = crypto.Digest{} + default: + return nil, errors.Errorf("attachedPayment: unexpected argument type '%s'", args[0].instanceOf()) + } + optAsset := proto.OptionalAsset{ID: asset} + + attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: optAsset, Amount: uint64(intAmount)}) + } + + var paymentActions []proto.ScriptAction + for _, payment := range attachedPayments { + action := &proto.TransferScriptAction{Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} + paymentActions = append(paymentActions, action) + } + + err = env.applyToState(paymentActions) + if err != nil { + return nil, errors.Wrapf(err, "Failed to apply attachedPayments") + } + + res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) + + if err != nil { + return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + } + + if res.Result() { + if res.UserError() != "" { + return nil, errors.Errorf(res.UserError()) + } + + err = env.smartAppendActions(res.ScriptActions()) + env.setNewDAppAddress(proto.Address(oldAddress.(rideAddress))) + if err != nil { + return nil, err + } + + if res.UserResult() == nil { + return rideUnit{}, nil + } + return res.UserResult(), nil + } + + return nil, errors.Errorf("Result of Invoke is false") +} + func addressFromString(env RideEnvironment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { @@ -1069,6 +1169,31 @@ func sponsorship(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } +func attachedPayment(_ RideEnvironment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 2); err != nil { + return nil, errors.Wrap(err, "attachedPayment") + } + + r := make(rideObject) + r[instanceFieldName] = rideString("AttachedPayment") + + var assetID rideType + switch assID := args[0].(type) { + case rideBytes, rideUnit: + assetID = assID + default: + return nil, errors.Errorf("attachedPayment: unexpected argument type '%s'", args[0].instanceOf()) + } + r["assetId"] = assetID + + amount, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("attachedPayment: unexpected argument type '%s'", args[1].instanceOf()) + } + r["amount"] = amount + return r, nil +} + func extractRecipient(v rideType) (proto.Recipient, error) { var r proto.Recipient switch a := v.(type) { diff --git a/pkg/ride/functions_test.go b/pkg/ride/functions_test.go index 8bf4d97ed..972d059e5 100644 --- a/pkg/ride/functions_test.go +++ b/pkg/ride/functions_test.go @@ -11,7 +11,7 @@ func TestNames(t *testing.T) { assert.Equal(t, "!", functionNameV2(0)) assert.Equal(t, "!=", functionNameV3(1)) assert.Equal(t, "wavesBalance", functionNameV2(67)) - assert.Equal(t, "DeleteEntry", functionNameV4(180)) + assert.Equal(t, "DeleteEntry", functionNameV4(182)) } func TestCheckFunction(t *testing.T) { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 4c2d4abfc..60a26b756 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -295,6 +295,7 @@ func functionsV4() map[string]string { m["Reissue"] = "reissue" m["Burn"] = "burn" m["SponsorFee"] = "sponsorship" + m["AttachedPayment"] = "attachedPayment" // Functions delete(m, "wavesBalance") // Remove wavesBalanceV3 @@ -324,6 +325,7 @@ func functionsV4() map[string]string { m["1103"] = "indexOfList" m["1104"] = "lastIndexOfList" m["1209"] = "makeString" + m["1020"] = "invoke" for i, l := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} { m[strconv.Itoa(2400+i)] = fmt.Sprintf("bls12Groth16Verify_%d", l) } @@ -360,6 +362,7 @@ func catalogueV4() map[string]int { m["Reissue"] = 3 m["Burn"] = 2 m["SponsorFee"] = 2 + m["AttachedPayment"] = 2 m["201"] = 6 m["202"] = 6 @@ -413,6 +416,7 @@ func catalogueV4() map[string]int { m["1207"] = 3 m["1208"] = 3 m["1209"] = 30 + m["1020"] = 1 // TODO write true value for i, c := range []int{1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600} { m[strconv.Itoa(2400+i)] = c } @@ -599,9 +603,15 @@ func createConstants(sb *strings.Builder, ver string, c map[string]constantDescr } func createConstructors(sb *strings.Builder, c map[string]constantDescription) { - for _, v := range c { - if v.constructor == "" { - tn := v.typeName + keys := make([]string, 0, len(c)) + for k := range c { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + if c[k].constructor == "" { + tn := c[k].typeName sb.WriteString(fmt.Sprintf("func new%s(RideEnvironment) rideType {\n", tn)) sb.WriteString(fmt.Sprintf("return rideNamedType{name: \"%s\"}\n", tn)) sb.WriteString("}\n\n") @@ -620,7 +630,9 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c sort.Strings(keys) // Create sorted list of functions - sb.WriteString(fmt.Sprintf("var _functions_%s = [...]rideFunction{", ver)) + sb.WriteString(fmt.Sprintf("var _functions_%s [%d]rideFunction\n", ver, len(keys))) + sb.WriteString("func init() {\n") + sb.WriteString(fmt.Sprintf("_functions_%s = [%d]rideFunction{", ver, len(keys))) for i, k := range keys { sb.WriteString(m[k]) if i < len(m)-1 { @@ -628,6 +640,7 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c } } sb.WriteString("}\n") + sb.WriteString("}\n") // Create list of costs sb.WriteString(fmt.Sprintf("var _catalogue_%s = [...]int{", ver)) diff --git a/pkg/ride/result.go b/pkg/ride/result.go index 703ed35e3..a7a302ab6 100644 --- a/pkg/ride/result.go +++ b/pkg/ride/result.go @@ -5,18 +5,24 @@ import "github.com/wavesplatform/gowaves/pkg/proto" type RideResult interface { Result() bool UserError() string + UserResult() rideType ScriptActions() []proto.ScriptAction } type ScriptResult struct { - res bool - msg string + res bool + msg string + param rideType } func (r ScriptResult) Result() bool { return r.res } +func (r ScriptResult) UserResult() rideType { + return r.param +} + func (r ScriptResult) UserError() string { return r.msg } @@ -29,12 +35,17 @@ type DAppResult struct { res bool // true - success, false - call failed, read msg actions []proto.ScriptAction msg string + param rideType } func (r DAppResult) Result() bool { return r.res } +func (r DAppResult) UserResult() rideType { + return r.param +} + func (r DAppResult) UserError() string { return r.msg } diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index f12850dd1..c800324d4 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -341,8 +341,16 @@ type RideEnvironment interface { block() rideObject txID() rideType // Invoke transaction ID state() types.SmartState + applyToState(actions []proto.ScriptAction) error + appendActions(actions []proto.ScriptAction) + smartAppendActions(actions []proto.ScriptAction) error + actions() []proto.ScriptAction + invCount() uint64 + incrementInvCount() + setNewDAppAddress(address proto.Address) checkMessageLength(int) bool invocation() rideObject // Invocation object made of invoke transaction + SetInvocation(inv rideObject) } type rideConstructor func(RideEnvironment) rideType diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index ce0b328b2..543ee6c9f 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -4,6 +4,7 @@ package ride import ( + "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/types" "sync" ) @@ -18,6 +19,18 @@ var _ RideEnvironment = &MockRideEnvironment{} // // // make and configure a mocked RideEnvironment // mockedRideEnvironment := &MockRideEnvironment{ +// SetInvocationFunc: func(inv rideObject) { +// panic("mock out the SetInvocation method") +// }, +// actionsFunc: func() []proto.ScriptAction { +// panic("mock out the actions method") +// }, +// appendActionsFunc: func(actions []proto.ScriptAction) { +// panic("mock out the appendActions method") +// }, +// applyToStateFunc: func(actions []proto.ScriptAction) error { +// panic("mock out the applyToState method") +// }, // blockFunc: func() rideObject { // panic("mock out the block method") // }, @@ -27,12 +40,24 @@ var _ RideEnvironment = &MockRideEnvironment{} // heightFunc: func() rideInt { // panic("mock out the height method") // }, +// incrementInvCountFunc: func() { +// panic("mock out the incrementInvCount method") +// }, +// invCountFunc: func() uint64 { +// panic("mock out the invCount method") +// }, // invocationFunc: func() rideObject { // panic("mock out the invocation method") // }, // schemeFunc: func() byte { // panic("mock out the scheme method") // }, +// setNewDAppAddressFunc: func(address proto.Address) { +// panic("mock out the setNewDAppAddress method") +// }, +// smartAppendActionsFunc: func(actions []proto.ScriptAction) error { +// panic("mock out the smartAppendActions method") +// }, // stateFunc: func() types.SmartState { // panic("mock out the state method") // }, @@ -52,6 +77,18 @@ var _ RideEnvironment = &MockRideEnvironment{} // // } type MockRideEnvironment struct { + // SetInvocationFunc mocks the SetInvocation method. + SetInvocationFunc func(inv rideObject) + + // actionsFunc mocks the actions method. + actionsFunc func() []proto.ScriptAction + + // appendActionsFunc mocks the appendActions method. + appendActionsFunc func(actions []proto.ScriptAction) + + // applyToStateFunc mocks the applyToState method. + applyToStateFunc func(actions []proto.ScriptAction) error + // blockFunc mocks the block method. blockFunc func() rideObject @@ -61,12 +98,24 @@ type MockRideEnvironment struct { // heightFunc mocks the height method. heightFunc func() rideInt + // incrementInvCountFunc mocks the incrementInvCount method. + incrementInvCountFunc func() + + // invCountFunc mocks the invCount method. + invCountFunc func() uint64 + // invocationFunc mocks the invocation method. invocationFunc func() rideObject // schemeFunc mocks the scheme method. schemeFunc func() byte + // setNewDAppAddressFunc mocks the setNewDAppAddress method. + setNewDAppAddressFunc func(address proto.Address) + + // smartAppendActionsFunc mocks the smartAppendActions method. + smartAppendActionsFunc func(actions []proto.ScriptAction) error + // stateFunc mocks the state method. stateFunc func() types.SmartState @@ -81,6 +130,24 @@ type MockRideEnvironment struct { // calls tracks calls to the methods. calls struct { + // SetInvocation holds details about calls to the SetInvocation method. + SetInvocation []struct { + // Inv is the inv argument value. + Inv rideObject + } + // actions holds details about calls to the actions method. + actions []struct { + } + // appendActions holds details about calls to the appendActions method. + appendActions []struct { + // Actions is the actions argument value. + Actions []proto.ScriptAction + } + // applyToState holds details about calls to the applyToState method. + applyToState []struct { + // Actions is the actions argument value. + Actions []proto.ScriptAction + } // block holds details about calls to the block method. block []struct { } @@ -92,12 +159,28 @@ type MockRideEnvironment struct { // height holds details about calls to the height method. height []struct { } + // incrementInvCount holds details about calls to the incrementInvCount method. + incrementInvCount []struct { + } + // invCount holds details about calls to the invCount method. + invCount []struct { + } // invocation holds details about calls to the invocation method. invocation []struct { } // scheme holds details about calls to the scheme method. scheme []struct { } + // setNewDAppAddress holds details about calls to the setNewDAppAddress method. + setNewDAppAddress []struct { + // Address is the address argument value. + Address proto.Address + } + // smartAppendActions holds details about calls to the smartAppendActions method. + smartAppendActions []struct { + // Actions is the actions argument value. + Actions []proto.ScriptAction + } // state holds details about calls to the state method. state []struct { } @@ -111,17 +194,144 @@ type MockRideEnvironment struct { txID []struct { } } + lockSetInvocation sync.RWMutex + lockactions sync.RWMutex + lockappendActions sync.RWMutex + lockapplyToState sync.RWMutex lockblock sync.RWMutex lockcheckMessageLength sync.RWMutex lockheight sync.RWMutex + lockincrementInvCount sync.RWMutex + lockinvCount sync.RWMutex lockinvocation sync.RWMutex lockscheme sync.RWMutex + locksetNewDAppAddress sync.RWMutex + locksmartAppendActions sync.RWMutex lockstate sync.RWMutex lockthis sync.RWMutex locktransaction sync.RWMutex locktxID sync.RWMutex } +// SetInvocation calls SetInvocationFunc. +func (mock *MockRideEnvironment) SetInvocation(inv rideObject) { + if mock.SetInvocationFunc == nil { + panic("MockRideEnvironment.SetInvocationFunc: method is nil but RideEnvironment.SetInvocation was just called") + } + callInfo := struct { + Inv rideObject + }{ + Inv: inv, + } + mock.lockSetInvocation.Lock() + mock.calls.SetInvocation = append(mock.calls.SetInvocation, callInfo) + mock.lockSetInvocation.Unlock() + mock.SetInvocationFunc(inv) +} + +// SetInvocationCalls gets all the calls that were made to SetInvocation. +// Check the length with: +// len(mockedRideEnvironment.SetInvocationCalls()) +func (mock *MockRideEnvironment) SetInvocationCalls() []struct { + Inv rideObject +} { + var calls []struct { + Inv rideObject + } + mock.lockSetInvocation.RLock() + calls = mock.calls.SetInvocation + mock.lockSetInvocation.RUnlock() + return calls +} + +// actions calls actionsFunc. +func (mock *MockRideEnvironment) actions() []proto.ScriptAction { + if mock.actionsFunc == nil { + panic("MockRideEnvironment.actionsFunc: method is nil but RideEnvironment.actions was just called") + } + callInfo := struct { + }{} + mock.lockactions.Lock() + mock.calls.actions = append(mock.calls.actions, callInfo) + mock.lockactions.Unlock() + return mock.actionsFunc() +} + +// actionsCalls gets all the calls that were made to actions. +// Check the length with: +// len(mockedRideEnvironment.actionsCalls()) +func (mock *MockRideEnvironment) actionsCalls() []struct { +} { + var calls []struct { + } + mock.lockactions.RLock() + calls = mock.calls.actions + mock.lockactions.RUnlock() + return calls +} + +// appendActions calls appendActionsFunc. +func (mock *MockRideEnvironment) appendActions(actions []proto.ScriptAction) { + if mock.appendActionsFunc == nil { + panic("MockRideEnvironment.appendActionsFunc: method is nil but RideEnvironment.appendActions was just called") + } + callInfo := struct { + Actions []proto.ScriptAction + }{ + Actions: actions, + } + mock.lockappendActions.Lock() + mock.calls.appendActions = append(mock.calls.appendActions, callInfo) + mock.lockappendActions.Unlock() + mock.appendActionsFunc(actions) +} + +// appendActionsCalls gets all the calls that were made to appendActions. +// Check the length with: +// len(mockedRideEnvironment.appendActionsCalls()) +func (mock *MockRideEnvironment) appendActionsCalls() []struct { + Actions []proto.ScriptAction +} { + var calls []struct { + Actions []proto.ScriptAction + } + mock.lockappendActions.RLock() + calls = mock.calls.appendActions + mock.lockappendActions.RUnlock() + return calls +} + +// applyToState calls applyToStateFunc. +func (mock *MockRideEnvironment) applyToState(actions []proto.ScriptAction) error { + if mock.applyToStateFunc == nil { + panic("MockRideEnvironment.applyToStateFunc: method is nil but RideEnvironment.applyToState was just called") + } + callInfo := struct { + Actions []proto.ScriptAction + }{ + Actions: actions, + } + mock.lockapplyToState.Lock() + mock.calls.applyToState = append(mock.calls.applyToState, callInfo) + mock.lockapplyToState.Unlock() + return mock.applyToStateFunc(actions) +} + +// applyToStateCalls gets all the calls that were made to applyToState. +// Check the length with: +// len(mockedRideEnvironment.applyToStateCalls()) +func (mock *MockRideEnvironment) applyToStateCalls() []struct { + Actions []proto.ScriptAction +} { + var calls []struct { + Actions []proto.ScriptAction + } + mock.lockapplyToState.RLock() + calls = mock.calls.applyToState + mock.lockapplyToState.RUnlock() + return calls +} + // block calls blockFunc. func (mock *MockRideEnvironment) block() rideObject { if mock.blockFunc == nil { @@ -205,6 +415,58 @@ func (mock *MockRideEnvironment) heightCalls() []struct { return calls } +// incrementInvCount calls incrementInvCountFunc. +func (mock *MockRideEnvironment) incrementInvCount() { + if mock.incrementInvCountFunc == nil { + panic("MockRideEnvironment.incrementInvCountFunc: method is nil but RideEnvironment.incrementInvCount was just called") + } + callInfo := struct { + }{} + mock.lockincrementInvCount.Lock() + mock.calls.incrementInvCount = append(mock.calls.incrementInvCount, callInfo) + mock.lockincrementInvCount.Unlock() + mock.incrementInvCountFunc() +} + +// incrementInvCountCalls gets all the calls that were made to incrementInvCount. +// Check the length with: +// len(mockedRideEnvironment.incrementInvCountCalls()) +func (mock *MockRideEnvironment) incrementInvCountCalls() []struct { +} { + var calls []struct { + } + mock.lockincrementInvCount.RLock() + calls = mock.calls.incrementInvCount + mock.lockincrementInvCount.RUnlock() + return calls +} + +// invCount calls invCountFunc. +func (mock *MockRideEnvironment) invCount() uint64 { + if mock.invCountFunc == nil { + panic("MockRideEnvironment.invCountFunc: method is nil but RideEnvironment.invCount was just called") + } + callInfo := struct { + }{} + mock.lockinvCount.Lock() + mock.calls.invCount = append(mock.calls.invCount, callInfo) + mock.lockinvCount.Unlock() + return mock.invCountFunc() +} + +// invCountCalls gets all the calls that were made to invCount. +// Check the length with: +// len(mockedRideEnvironment.invCountCalls()) +func (mock *MockRideEnvironment) invCountCalls() []struct { +} { + var calls []struct { + } + mock.lockinvCount.RLock() + calls = mock.calls.invCount + mock.lockinvCount.RUnlock() + return calls +} + // invocation calls invocationFunc. func (mock *MockRideEnvironment) invocation() rideObject { if mock.invocationFunc == nil { @@ -257,6 +519,68 @@ func (mock *MockRideEnvironment) schemeCalls() []struct { return calls } +// setNewDAppAddress calls setNewDAppAddressFunc. +func (mock *MockRideEnvironment) setNewDAppAddress(address proto.Address) { + if mock.setNewDAppAddressFunc == nil { + panic("MockRideEnvironment.setNewDAppAddressFunc: method is nil but RideEnvironment.setNewDAppAddress was just called") + } + callInfo := struct { + Address proto.Address + }{ + Address: address, + } + mock.locksetNewDAppAddress.Lock() + mock.calls.setNewDAppAddress = append(mock.calls.setNewDAppAddress, callInfo) + mock.locksetNewDAppAddress.Unlock() + mock.setNewDAppAddressFunc(address) +} + +// setNewDAppAddressCalls gets all the calls that were made to setNewDAppAddress. +// Check the length with: +// len(mockedRideEnvironment.setNewDAppAddressCalls()) +func (mock *MockRideEnvironment) setNewDAppAddressCalls() []struct { + Address proto.Address +} { + var calls []struct { + Address proto.Address + } + mock.locksetNewDAppAddress.RLock() + calls = mock.calls.setNewDAppAddress + mock.locksetNewDAppAddress.RUnlock() + return calls +} + +// smartAppendActions calls smartAppendActionsFunc. +func (mock *MockRideEnvironment) smartAppendActions(actions []proto.ScriptAction) error { + if mock.smartAppendActionsFunc == nil { + panic("MockRideEnvironment.smartAppendActionsFunc: method is nil but RideEnvironment.smartAppendActions was just called") + } + callInfo := struct { + Actions []proto.ScriptAction + }{ + Actions: actions, + } + mock.locksmartAppendActions.Lock() + mock.calls.smartAppendActions = append(mock.calls.smartAppendActions, callInfo) + mock.locksmartAppendActions.Unlock() + return mock.smartAppendActionsFunc(actions) +} + +// smartAppendActionsCalls gets all the calls that were made to smartAppendActions. +// Check the length with: +// len(mockedRideEnvironment.smartAppendActionsCalls()) +func (mock *MockRideEnvironment) smartAppendActionsCalls() []struct { + Actions []proto.ScriptAction +} { + var calls []struct { + Actions []proto.ScriptAction + } + mock.locksmartAppendActions.RLock() + calls = mock.calls.smartAppendActions + mock.locksmartAppendActions.RUnlock() + return calls +} + // state calls stateFunc. func (mock *MockRideEnvironment) state() types.SmartState { if mock.stateFunc == nil { diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index 8112b46e5..4994740e9 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -13,6 +13,31 @@ func CallVerifier(env RideEnvironment, tree *Tree) (RideResult, error) { return e.evaluate() } +func invokeFunctionFromDApp(env RideEnvironment, recipient proto.Recipient, fnName rideString, listArgs rideList) (RideResult, error) { + + address, err := env.state().NewestRecipientToAddress(recipient) + if err != nil { + return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") + } + env.setNewDAppAddress(*address) + + newScript, err := env.state().GetByteTree(recipient) + if err != nil { + return nil, errors.Wrap(err, "Failed to get script by recipient") + } + + tree, err := Parse(newScript) + if err != nil { + return nil, errors.Wrap(err, "Failed to get tree by script") + } + + e, err := treeFunctionEvaluatorForInvokeDAppFromDApp(env, tree, string(fnName), listArgs) + if err != nil { + return nil, errors.Wrapf(err, "failed to call function '%s'", fnName) + } + return e.evaluate() +} + func CallFunction(env RideEnvironment, tree *Tree, name string, args proto.Arguments) (RideResult, error) { if name == "" { name = "default" diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index ed96d38ac..404c6552e 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -26,6 +26,9 @@ func TestSimpleScriptEvaluation(t *testing.T) { stateFunc: func() types.SmartState { return state }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return 'T' }, @@ -99,6 +102,9 @@ func TestFunctionsEvaluation(t *testing.T) { data := newDataTransaction() require.NoError(t, err) env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return nil + }, checkMessageLengthFunc: v3check, schemeFunc: func() byte { return 'W' @@ -417,6 +423,9 @@ func TestDataFunctions(t *testing.T) { transactionFunc: func() rideObject { return txObj }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, heightFunc: func() rideInt { return rideInt(100500) }, @@ -470,6 +479,9 @@ func testInvokeEnv(verifier bool) (RideEnvironment, *proto.InvokeScriptWithProof } return txo }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -577,196 +589,4039 @@ func TestDappDefaultFunc(t *testing.T) { addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, tx.SenderPK) require.NoError(t, err) - code := "AAIDAAAAAAAAAAAAAAABAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEAAAAHYWRkcmVzcwUAAAAHYWRkcmVzcwAAAAIAAAABaQEAAAAGdGVsbG1lAAAAAQAAAAhxdWVzdGlvbgQAAAAGYW5zd2VyCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAABBQAAAAhxdWVzdGlvbgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9xBQAAAAhxdWVzdGlvbgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9hBQAAAAZhbnN3ZXIFAAAAA25pbAAAAAppbnZvY2F0aW9uAQAAAAdkZWZhdWx0AAAAAAQAAAAHc2VuZGVyMAgIBQAAAAppbnZvY2F0aW9uAAAABmNhbGxlcgAAAAVieXRlcwkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAABYQIAAAABYgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAAGc2VuZGVyBQAAAAdzZW5kZXIwBQAAAANuaWwAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAACQAAAAAAAAIJAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEJAAQlAAAAAQgFAAAAAnR4AAAABnNlbmRlcgIAAAABMcP91gY=" - src, err := base64.StdEncoding.DecodeString(code) - require.NoError(t, err) + code := "AAIDAAAAAAAAAAAAAAABAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEAAAAHYWRkcmVzcwUAAAAHYWRkcmVzcwAAAAIAAAABaQEAAAAGdGVsbG1lAAAAAQAAAAhxdWVzdGlvbgQAAAAGYW5zd2VyCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAABBQAAAAhxdWVzdGlvbgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9xBQAAAAhxdWVzdGlvbgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9hBQAAAAZhbnN3ZXIFAAAAA25pbAAAAAppbnZvY2F0aW9uAQAAAAdkZWZhdWx0AAAAAAQAAAAHc2VuZGVyMAgIBQAAAAppbnZvY2F0aW9uAAAABmNhbGxlcgAAAAVieXRlcwkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAABYQIAAAABYgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAAGc2VuZGVyBQAAAAdzZW5kZXIwBQAAAANuaWwAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAACQAAAAAAAAIJAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEJAAQlAAAAAQgFAAAAAnR4AAAABnNlbmRlcgIAAAABMcP91gY=" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "", proto.Arguments{}) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + require.EqualValues(t, + &proto.ScriptResult{ + DataEntries: []*proto.DataEntryScriptAction{ + {Entry: &proto.StringDataEntry{Key: "a", Value: "b"}}, + {Entry: &proto.BinaryDataEntry{Key: "sender", Value: addr.Bytes()}}, + }, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + }, + sr, + ) +} + +func TestDappVerify(t *testing.T) { + /* + {-# STDLIB_VERSION 3 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + func getPreviousAnswer(address: String) = { + address + } + + @Callable(i) + func tellme(question: String) = { + let answer = getPreviousAnswer(question) + + WriteSet([ + DataEntry(answer + "_q", question), + DataEntry(answer + "_a", answer) + ]) + } + + @Callable(invocation) + func default() = { + let sender0 = invocation.caller.bytes + WriteSet([DataEntry("a", "b"), DataEntry("sender", sender0)]) + } + + @Verifier(tx) + func verify() = { + getPreviousAnswer(toString(tx.sender)) == "1" + } + */ + env, _ := testInvokeEnv(true) + code := "AAIDAAAAAAAAAAAAAAABAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEAAAAHYWRkcmVzcwUAAAAHYWRkcmVzcwAAAAIAAAABaQEAAAAGdGVsbG1lAAAAAQAAAAhxdWVzdGlvbgQAAAAGYW5zd2VyCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAABBQAAAAhxdWVzdGlvbgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9xBQAAAAhxdWVzdGlvbgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9hBQAAAAZhbnN3ZXIFAAAAA25pbAAAAAppbnZvY2F0aW9uAQAAAAdkZWZhdWx0AAAAAAQAAAAHc2VuZGVyMAgIBQAAAAppbnZvY2F0aW9uAAAABmNhbGxlcgAAAAVieXRlcwkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAABYQIAAAABYgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAAGc2VuZGVyBQAAAAdzZW5kZXIwBQAAAANuaWwAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAACQAAAAAAAAIJAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEJAAQlAAAAAQgFAAAAAnR4AAAABnNlbmRlcgIAAAABMcP91gY=" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallVerifier(env, tree) + require.NoError(t, err) + r, ok := res.(ScriptResult) + require.True(t, ok) + assert.False(t, r.Result()) +} + +func TestDappVerifySuccessful(t *testing.T) { + /*{-# STDLIB_VERSION 3 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let x = 100500 + + func getPreviousAnswer() = { + x + } + + @Verifier(tx) + func verify() = { + getPreviousAnswer() == 100500 + } + */ + env, _ := testInvokeEnv(true) + code := "AAIDAAAAAAAAAAAAAAACAAAAAAF4AAAAAAAAAYiUAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAAFAAAAAXgAAAAAAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAkAAAAAAAACCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAAAAAAAAAAAAYiUa4pU5Q==" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallVerifier(env, tree) + require.NoError(t, err) + r, ok := res.(ScriptResult) + require.True(t, ok) + assert.True(t, r.Result()) +} + +func TestTransferSet(t *testing.T) { + /* + {-# STDLIB_VERSION 3 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func tellme(question: String) = { + TransferSet([ScriptTransfer(i.caller, 100, unit)]) + } + */ + env, tx := testInvokeEnv(false) + addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, tx.SenderPK) + require.NoError(t, err) + code := "AAIDAAAAAAAAAAAAAAAAAAAAAQAAAAFpAQAAAAZ0ZWxsbWUAAAABAAAACHF1ZXN0aW9uCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgAAAAAAAAAAZAUAAAAEdW5pdAUAAAADbmlsAAAAAH5a2L0=" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "tellme", proto.Arguments{proto.NewIntegerArgument(100500)}) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + scriptTransfer := proto.TransferScriptAction{ + Recipient: proto.NewRecipientFromAddress(addr), + Amount: 100, + Asset: proto.OptionalAsset{Present: false}, + } + require.NoError(t, err) + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + require.EqualValues(t, + &proto.ScriptResult{ + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: []*proto.TransferScriptAction{&scriptTransfer}, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + }, + sr, + ) +} + +func TestScriptResult(t *testing.T) { + /* + {-# STDLIB_VERSION 3 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func tellme(question: String) = { + ScriptResult( + WriteSet([DataEntry("key", 100)]), + TransferSet([ScriptTransfer(i.caller, 100500, unit)]) + ) + } + */ + env, tx := testInvokeEnv(false) + addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, tx.SenderPK) + require.NoError(t, err) + code := "AAIDAAAAAAAAAAAAAAAAAAAAAQAAAAFpAQAAAAZ0ZWxsbWUAAAABAAAACHF1ZXN0aW9uCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAABkBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyAAAAAAAAAYiUBQAAAAR1bml0BQAAAANuaWwAAAAARKRntw==" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "tellme", proto.Arguments{proto.NewIntegerArgument(100)}) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + scriptTransfer := proto.TransferScriptAction{ + Recipient: proto.NewRecipientFromAddress(addr), + Amount: 100500, + Asset: proto.OptionalAsset{Present: false}, + } + require.Equal(t, + &proto.ScriptResult{ + DataEntries: []*proto.DataEntryScriptAction{{Entry: &proto.IntegerDataEntry{Key: "key", Value: 100}}}, + Transfers: []*proto.TransferScriptAction{&scriptTransfer}, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + }, + sr, + ) +} + +func initWrappedState(state types.SmartState, envThis rideAddress) *wrappedState { + var dataEntries diffDataEntries + + dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} + dataEntries.diffBool = map[string]proto.BooleanDataEntry{} + dataEntries.diffString = map[string]proto.StringDataEntry{} + dataEntries.diffBinary = map[string]proto.BinaryDataEntry{} + dataEntries.diffDDelete = map[string]proto.DeleteDataEntry{} + + balances := map[string]diffBalance{} + sponsorships := map[string]diffSponsorship{} + newAssetInfo := map[string]diffNewAssetInfo{} + oldAssetInfo := map[string]diffOldAssetInfo{} + + diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo} + wrappedSt := wrappedState{diff: *diffSt, envThis: envThis} + return &wrappedSt +} + +func TestInvokeDAppFromDAppAllActions(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func test() = { + let res = Invoke(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), "testActions",[], [AttachedPayment(base58'', 1234), AttachedPayment(base58'', 1234)]) + if res == 17 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Bad returned value") + } + */ + + /* script 2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func testActions() = { + let asset = Issue("CatCoin", "", 1, 0, true, unit, 0) + let assetId = asset.calculateAssetId() + + ([ + ScriptTransfer(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), 1, unit), + BinaryEntry("bin", base58''), + BooleanEntry("bool", true), + IntegerEntry("int", 1), + StringEntry("str", ""), + DeleteEntry("str"), + asset, + Reissue(assetId, 10, false), + Burn(assetId, 5) + ], 17) + } + */ + var assetIDIssue crypto.Digest + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" + secondScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVyOzrRJck6TK7Dn+T0bWzVZNLfsQ+2OYegAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAANzdHICAAAAAAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABAgAAAANzdHIJAARMAAAAAgUAAAAFYXNzZXQJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAdhc3NldElkAAAAAAAAAAAKBwkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAAB2Fzc2V0SWQAAAAAAAAAAAUFAAAAA25pbAAAAAAAAAAAEQAAAACaHEHX" + + id := bytes.Repeat([]byte{0}, 32) + + assetExp := proto.OptionalAsset{ID: crypto.Digest{}, Present: false} + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + assetIDIssue = res.ID + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == address.String() { + script, err = base64.StdEncoding.DecodeString(secondScript) + require.NoError(t, err) + return script, nil + } + + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return &address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + var invCount uint64 + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + SetInvocationFunc: func(inv rideObject) { + }, + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(envActions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(address) + }, + setNewDAppAddressFunc: func(address proto.Address) { + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + // new test + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + balance := diffBalance{amount: 0, assetID: assetExp.ID} + expectedDiffResult.balances[address.String()+assetExp.ID.String()] = balance + + intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+address.String()] = intEntry1 + + boolEntry := proto.BooleanDataEntry{Key: "bool", Value: true} + expectedDiffResult.dataEntries.diffBool["bool"+address.String()] = boolEntry + + stringEntry := proto.StringDataEntry{Key: "str", Value: ""} + expectedDiffResult.dataEntries.diffString["str"+address.String()] = stringEntry + + binaryEntry := proto.BinaryDataEntry{Key: "bin", Value: []byte("")} + expectedDiffResult.dataEntries.diffBinary["bin"+address.String()] = binaryEntry + + deleteEntry := proto.DeleteDataEntry{Key: "str"} + expectedDiffResult.dataEntries.diffDDelete["str"+address.String()] = deleteEntry + + newAsset := diffNewAssetInfo{dAppIssuer: address, name: "CatCoin", description: "", quantity: 6, decimals: 0, reissuable: false, script: nil, nonce: 0} + expectedDiffResult.newAssetsInfo[assetIDIssue.String()] = newAsset + + assert.Equal(t, expectedDiffResult.newAssetsInfo, wrappedSt.diff.newAssetsInfo) + assert.Equal(t, expectedDiffResult.oldAssetsInfo, wrappedSt.diff.oldAssetsInfo) + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + assert.Equal(t, expectedDiffResult.sponsorships, wrappedSt.diff.sponsorships) + +} + +func TestInvokeDAppFromDAppScript1(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5#-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar() = { + ([IntegerEntry("bar", 1)], "return") + } + + @Callable(i) + func foo() = { + let r = Invoke(this, "bar", [], []) + if r == "return" + then + let data = getIntegerValue(this, "bar") + if data == 1 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Bad state") + else + throw("Bad returned value") + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAANiYXIAAAAACQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQUAAAADbmlsAgAAAAZyZXR1cm4AAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANiYXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyAgAAAAZyZXR1cm4EAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIFAAAABHRoaXMCAAAAA2JhcgMJAAAAAAAAAgUAAAAEZGF0YQAAAAAAAAAAAQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAADz23Fz" + + id := bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == address.String() { + script, err = base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + return script, nil + } + + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return &address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + + var invCount uint64 + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + SetInvocationFunc: func(inv rideObject) { + }, + + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(envActions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(address) + }, + setNewDAppAddressFunc: func(address proto.Address) { + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + intEntry1 := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+address.String()] = intEntry1 + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + +} + +func TestInvokeDAppFromDAppScript2(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) + if b1 == b1 && ob1 == ob1 + then + let r = Invoke(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) + if data == 1 + then + if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + } + */ + + /* + script2 + + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector) = { + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + addressCallable, err := proto.NewAddressFromString("3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW") + require.NoError(t, err) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAALVWK3g==" + secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" + + id := bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + script, err = base64.StdEncoding.DecodeString(secondScript) + require.NoError(t, err) + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return recipient.Address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + isNewDapp := false + + var invCount uint64 + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + SetInvocationFunc: func(inv rideObject) { + }, + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(actions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + if isNewDapp { + return rideAddress(addressCallable) + } + return rideAddress(address) + }, + setNewDAppAddressFunc: func(address proto.Address) { + wrappedSt.envThis = rideAddress(address) + isNewDapp = true + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -14} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 14} + intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry + expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + +} + +func TestInvokeDAppFromDAppScript3(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if b1 == b1 && ob1 == ob1 + then + let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if data == 1 + then + if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 + then + let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) + if r1 == r1 + then + let b3 = wavesBalance(this) + let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Bad balance after second invoke") + else + throw("Imposible") + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + } + + */ + + /* + script2 + + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector) = { + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + addressCallable, err := proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + require.NoError(t, err) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" + secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" + + id := bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + script, err = base64.StdEncoding.DecodeString(secondScript) + require.NoError(t, err) + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return recipient.Address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + thisAddr := address + + var invCount uint64 + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + SetInvocationFunc: func(inv rideObject) { + }, + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(actions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(thisAddr) + }, + setNewDAppAddressFunc: func(address proto.Address) { + wrappedSt.envThis = rideAddress(address) + thisAddr = address + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry + expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + +} + +func TestInvokeDAppFromDAppScript4(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func back() = { + [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 2, unit)] + } + + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + if b1 == b1 && ob1 == ob1 + then + let r = Invoke(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar") + let tdata = getIntegerValue(this, "key") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + if data == 1 && tdata == 0 + then + if ob1.regular+16 == ob2.regular && b1.regular == b2.regular+16 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + } + */ + + /* + script2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector) = { + let r = Invoke(Address(a), "back", [], []) + if r == r + then + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + else + throw("Imposible") + } + + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + addressCallable, err := proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + require.NoError(t, err) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAACP+w2w=" + secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" + + id := bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == address.String() { + script, err = base64.StdEncoding.DecodeString(firstScript) + } + if recipient.Address.String() == addressCallable.String() { + script, err = base64.StdEncoding.DecodeString(secondScript) + } + + require.NoError(t, err) + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return recipient.Address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + thisAddress := address + var invCount uint64 + + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + SetInvocationFunc: func(inv rideObject) { + }, + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(actions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(thisAddress) + }, + setNewDAppAddressFunc: func(address proto.Address) { + wrappedSt.envThis = rideAddress(address) + thisAddress = address + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -16} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 16} + intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} + intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["key"+address.String()] = intEntry1 + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 + expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + +} + +func TestInvokeDAppFromDAppScript5(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if b1 == b1 && ob1 == ob1 + then + let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if data == 1 + then + if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 + then + let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) + if r1 == r1 + then + let b3 = wavesBalance(this) + let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Bad balance after second invoke") + else + throw("Imposible") + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + } + + */ + + /* + script2 + + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector) = { + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + addressCallable, err := proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + require.NoError(t, err) + //recipientCallable := proto.NewRecipientFromAddress(address) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" + secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" + + id := bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == address.String() { + script, err = base64.StdEncoding.DecodeString(firstScript) + } + if recipient.Address.String() == addressCallable.String() { + script, err = base64.StdEncoding.DecodeString(secondScript) + } + + require.NoError(t, err) + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return recipient.Address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } + + var envActions []proto.ScriptAction + thisAddress := address + + var invCount uint64 + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + SetInvocationFunc: func(inv rideObject) { + }, + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) + + return smartState().ApplyToState(actions) + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(thisAddress) + }, + setNewDAppAddressFunc: func(address proto.Address) { + wrappedSt.envThis = rideAddress(address) + thisAddress = address + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + } + + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry + expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + +} + +func TestInvokeDAppFromDAppScript6(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let r = Invoke(this, "foo", [], []) + if r == r + then + [ + ] + else + throw("Imposible") + } + + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" + + id := bytes.Repeat([]byte{0}, 32) + + var wrappedSt wrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) error { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + case *proto.StringDataEntry: + stringEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + addr := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + default: + + } + + case *proto.TransferScriptAction: + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return err + } + + senderAddr := proto.Address(wrappedSt.envThis) + senderRecip := proto.Recipient{Address: &senderAddr} + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + if err != nil { + return err + } + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + default: + } + + } + return nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == address.String() { + script, err = base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + return script, nil + } + + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return &address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } - res, err := CallFunction(env, tree, "", proto.Arguments{}) - require.NoError(t, err) - r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) + return &assetFromStore, nil + } - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - require.EqualValues(t, - &proto.ScriptResult{ - DataEntries: []*proto.DataEntryScriptAction{ - {Entry: &proto.StringDataEntry{Key: "a", Value: "b"}}, - {Entry: &proto.BinaryDataEntry{Key: "sender", Value: addr.Bytes()}}, - }, - Transfers: make([]*proto.TransferScriptAction, 0), - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - }, - sr, - ) -} + issuerPK := crypto.PublicKey{} -func TestDappVerify(t *testing.T) { - /* - {-# STDLIB_VERSION 3 #-} - {-# CONTENT_TYPE DAPP #-} - {-# SCRIPT_TYPE ACCOUNT #-} + scripted := false + if searchNewAsset.script != nil { + scripted = true + } - func getPreviousAnswer(address: String) = { - address - } + if err != nil { + return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") + } - @Callable(i) - func tellme(question: String) = { - let answer = getPreviousAnswer(question) + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil - WriteSet([ - DataEntry(answer + "_q", question), - DataEntry(answer + "_a", answer) - ]) - } + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - @Callable(invocation) - func default() = { - let sender0 = invocation.caller.bytes - WriteSet([DataEntry("a", "b"), DataEntry("sender", sender0)]) - } + if searchNewAsset == nil { - @Verifier(tx) - func verify() = { - getPreviousAnswer(toString(tx.sender)) == "1" - } - */ - env, _ := testInvokeEnv(true) - code := "AAIDAAAAAAAAAAAAAAABAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEAAAAHYWRkcmVzcwUAAAAHYWRkcmVzcwAAAAIAAAABaQEAAAAGdGVsbG1lAAAAAQAAAAhxdWVzdGlvbgQAAAAGYW5zd2VyCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAABBQAAAAhxdWVzdGlvbgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9xBQAAAAhxdWVzdGlvbgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkAASwAAAACBQAAAAZhbnN3ZXICAAAAAl9hBQAAAAZhbnN3ZXIFAAAAA25pbAAAAAppbnZvY2F0aW9uAQAAAAdkZWZhdWx0AAAAAAQAAAAHc2VuZGVyMAgIBQAAAAppbnZvY2F0aW9uAAAABmNhbGxlcgAAAAVieXRlcwkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAABYQIAAAABYgkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAAGc2VuZGVyBQAAAAdzZW5kZXIwBQAAAANuaWwAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAACQAAAAAAAAIJAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAEJAAQlAAAAAQgFAAAAAnR4AAAABnNlbmRlcgIAAAABMcP91gY=" - src, err := base64.StdEncoding.DecodeString(code) - require.NoError(t, err) + assetFromStore := proto.FullAssetInfo{} + if err != nil { + return nil, errors.Wrap(err, "failed to get asset's info from store") + } - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - res, err := CallVerifier(env, tree) - require.NoError(t, err) - r, ok := res.(ScriptResult) - require.True(t, ok) - assert.False(t, r.Result()) -} + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } -func TestDappVerifySuccessful(t *testing.T) { - /*{-# STDLIB_VERSION 3 #-} - {-# CONTENT_TYPE DAPP #-} - {-# SCRIPT_TYPE ACCOUNT #-} + return nil, errors.Errorf("quantity of the asset is negative") + } - let x = 100500 + return &assetFromStore, nil + } - func getPreviousAnswer() = { - x - } + issuerPK := crypto.PublicKey{} - @Verifier(tx) - func verify() = { - getPreviousAnswer() == 100500 - } - */ - env, _ := testInvokeEnv(true) - code := "AAIDAAAAAAAAAAAAAAACAAAAAAF4AAAAAAAAAYiUAQAAABFnZXRQcmV2aW91c0Fuc3dlcgAAAAAFAAAAAXgAAAAAAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAkAAAAAAAACCQEAAAARZ2V0UHJldmlvdXNBbnN3ZXIAAAAAAAAAAAAAAYiUa4pU5Q==" - src, err := base64.StdEncoding.DecodeString(code) - require.NoError(t, err) + scripted := false + if searchNewAsset.script != nil { + scripted = true + } - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } - res, err := CallVerifier(env, tree) - require.NoError(t, err) - r, ok := res.(ScriptResult) - require.True(t, ok) - assert.True(t, r.Result()) -} + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } -func TestTransferSet(t *testing.T) { - /* - {-# STDLIB_VERSION 3 #-} - {-# CONTENT_TYPE DAPP #-} - {-# SCRIPT_TYPE ACCOUNT #-} + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } + } - @Callable(i) - func tellme(question: String) = { - TransferSet([ScriptTransfer(i.caller, 100, unit)]) - } - */ - env, tx := testInvokeEnv(false) - addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, tx.SenderPK) - require.NoError(t, err) - code := "AAIDAAAAAAAAAAAAAAAAAAAAAQAAAAFpAQAAAAZ0ZWxsbWUAAAABAAAACHF1ZXN0aW9uCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgAAAAAAAAAAZAUAAAAEdW5pdAUAAAADbmlsAAAAAH5a2L0=" - src, err := base64.StdEncoding.DecodeString(code) - require.NoError(t, err) + var envActions []proto.ScriptAction + var invCount uint64 - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + SetInvocationFunc: func(inv rideObject) { + }, + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, - res, err := CallFunction(env, tree, "tellme", proto.Arguments{proto.NewIntegerArgument(100500)}) - require.NoError(t, err) - r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + envActions = append(envActions, actions...) - scriptTransfer := proto.TransferScriptAction{ - Recipient: proto.NewRecipientFromAddress(addr), - Amount: 100, - Asset: proto.OptionalAsset{Present: false}, - } - require.NoError(t, err) - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - require.EqualValues(t, - &proto.ScriptResult{ - DataEntries: make([]*proto.DataEntryScriptAction, 0), - Transfers: []*proto.TransferScriptAction{&scriptTransfer}, - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + return smartState().ApplyToState(envActions) }, - sr, - ) -} + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartState, -func TestScriptResult(t *testing.T) { - /* - {-# STDLIB_VERSION 3 #-} - {-# CONTENT_TYPE DAPP #-} - {-# SCRIPT_TYPE ACCOUNT #-} + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(address) + }, + setNewDAppAddressFunc: func(address proto.Address) { + }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return smartState().ApplyToState(actions) + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(4, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + } - @Callable(i) - func tellme(question: String) = { - ScriptResult( - WriteSet([DataEntry("key", 100)]), - TransferSet([ScriptTransfer(i.caller, 100500, unit)]) - ) - } - */ - env, tx := testInvokeEnv(false) - addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, tx.SenderPK) - require.NoError(t, err) - code := "AAIDAAAAAAAAAAAAAAAAAAAAAQAAAAFpAQAAAAZ0ZWxsbWUAAAABAAAACHF1ZXN0aW9uCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAABkBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyAAAAAAAAAYiUBQAAAAR1bml0BQAAAANuaWwAAAAARKRntw==" - src, err := base64.StdEncoding.DecodeString(code) + NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) tree, err := Parse(src) require.NoError(t, err) assert.NotNil(t, tree) - res, err := CallFunction(env, tree, "tellme", proto.Arguments{proto.NewIntegerArgument(100)}) + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + require.NoError(t, err) r, ok := res.(DAppResult) require.True(t, ok) @@ -774,24 +4629,23 @@ func TestScriptResult(t *testing.T) { sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) require.NoError(t, err) - scriptTransfer := proto.TransferScriptAction{ - Recipient: proto.NewRecipientFromAddress(addr), - Amount: 100500, - Asset: proto.OptionalAsset{Present: false}, + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } - require.Equal(t, - &proto.ScriptResult{ - DataEntries: []*proto.DataEntryScriptAction{{Entry: &proto.IntegerDataEntry{Key: "key", Value: 100}}}, - Transfers: []*proto.TransferScriptAction{&scriptTransfer}, - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - }, - sr, - ) + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + } func TestMatchOverwrite(t *testing.T) { @@ -833,6 +4687,9 @@ func TestMatchOverwrite(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + applyToStateFunc: func(actions []proto.ScriptAction) error { + return nil + }, heightFunc: func() rideInt { return 368430 }, @@ -1090,6 +4947,9 @@ func TestWhaleDApp(t *testing.T) { heightFunc: func() rideInt { return 368430 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -1224,6 +5084,9 @@ func TestExchangeDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -1392,6 +5255,9 @@ func TestBankDApp(t *testing.T) { schemeFunc: func() byte { return proto.MainNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -1516,6 +5382,9 @@ func TestLigaDApp1(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -1675,6 +5544,9 @@ func TestLigaDApp1(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -1854,6 +5726,9 @@ func TestTestingDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -1981,6 +5856,9 @@ func TestDropElementDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -2100,6 +5978,9 @@ func TestMathDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -2220,6 +6101,9 @@ func TestDAppWithInvalidAddress(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -2348,6 +6232,9 @@ func Test8Ball(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -2471,6 +6358,9 @@ func TestIntegerEntry(t *testing.T) { heightFunc: func() rideInt { return 844761 }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.StageNetScheme }, @@ -2531,6 +6421,9 @@ func TestAssetInfoV3V4(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, stateFunc: func() types.SmartState { return &MockSmartState{ NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { @@ -2619,6 +6512,9 @@ func TestDAppWithFullIssue(t *testing.T) { txIDFunc: func() rideType { return rideBytes(id) }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, } res, err := CallFunction(env, tree, "issue", proto.Arguments{&proto.StringArgument{Value: "xxx"}}) require.NoError(t, err) @@ -2645,6 +6541,9 @@ func TestDAppWithSimpleIssue(t *testing.T) { txIDFunc: func() rideType { return rideBytes(id) }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, } res, err := CallFunction(env, tree, "issue", proto.Arguments{&proto.StringArgument{Value: "xxx"}}) require.NoError(t, err) @@ -2710,6 +6609,9 @@ func TestBadType(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -2863,6 +6765,9 @@ func TestNoDeclaration(t *testing.T) { blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, + actionsFunc: func() []proto.ScriptAction { + return nil + }, stateFunc: func() types.SmartState { return &MockSmartState{ AddingBlockHeightFunc: func() (uint64, error) { @@ -3029,6 +6934,9 @@ func TestZeroReissue(t *testing.T) { "share_token_id": mustBytesFromBase64("Q3Uk9ZN5g5+xynU7VGPXUg1eVga04VYXnnZ0q+M1dxQ="), } env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return nil + }, heightFunc: func() rideInt { return 451323 }, @@ -3267,6 +7175,9 @@ func TestStageNet2(t *testing.T) { } dp := newJsonDataProvider(`[{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"aa","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"dappAddress","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"total_amount","intValue":"600900000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"masterAddress","stringValue":"3MkT3qvGwdLrSs2Cfx3E29ffaM5GYrEZegz"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"assetId_2020-10-3","stringValue":"Eo7N1sjexrfu6mx5LrG3suovSaXaBNnmYfvqJsMzSYE8"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"assetId_2020-10-5","stringValue":"J2j4PRKXuUKUZCP345EXAHYF2gRg15JsYQYtFT4GNPda"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_total_amount_2020-10-3","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_total_amount_2020-10-5","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","stringValue":"2020-11-23"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","stringValue":"2020-11-11"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","stringValue":"2020-09-30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_limit","stringValue":"2020-10-3"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_limit","stringValue":"2020-10-5"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_limit","stringValue":"2020-10-3"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_limit","stringValue":"2020-10-5"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_amount","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_amount","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_assetId","stringValue":"GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_assetId","stringValue":"9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_assetId","stringValue":"3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_assetId","stringValue":"fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_assetId","stringValue":"Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_assetId","stringValue":"AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_assetId","stringValue":"DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_assetId","stringValue":"5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_assetId","stringValue":"6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_assetId","stringValue":"BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_unitPrice","intValue":"300"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_unitPrice","intValue":"300"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_description","stringValue":"みんな電力公式"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"dappAddress","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"masterAddress","stringValue":"3MSvD3m1R8Z3v8SAztrt1afp28vRdsMwxAu"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"asset_total_amount","intValue":"100000"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MgvX2f2ExVwTMkAk6dua8yE2iRmuBV4heT","stringValue":"{\"name\":\"ママママママママっまm\",\"description\":\"retail user\"}"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MktJgV2eTmcCqtyQaeqiiHkQ1eY3EH5Tdb","stringValue":"{\"name\":\"ママママママママっまm\",\"description\":\"retail user\"}"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MRiqDCpFntSEud3Co8bdQygjSwB515zyS5_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MSvD3m1R8Z3v8SAztrt1afp28vRdsMwxAu_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MUJS7P4W3XyP2pnAJUGqkstSAiU4Ac2YdA_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MZyZAgAJmXmJs5gDihnMvZ7HCLxe6zVVpU_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MfF8z9y9nUUuHTeKiGFGoWXnUrRPbEcNiD_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MgvX2f2ExVwTMkAk6dua8yE2iRmuBV4heT_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3Mh5b5UttYteWjd5Mku43kajZFKX9z5WNxZ_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MjBN2kiRB6JmoEVEC42ZNMX9ibx5iZ9Mih_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MkT3qvGwdLrSs2Cfx3E29ffaM5GYrEZegz_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MktJgV2eTmcCqtyQaeqiiHkQ1eY3EH5Tdb_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3Mm9VfS5424Vn4oNKv1DSh7Htk6FhQReEuP_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MmNtj9n49UgGapeh1Sg8Nd8jfQGDbqRTkx_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3P35F9e1QdcHkBMbYtovuMUmsxxCqo9DF1d_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PLXmyBua1pAH4y3aHjMqJrcJEcyrWMP1EB_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PMoTnMU6U4hx8km23iZJ6Akis6JKhcxhUn_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PNVubsGCrnMHLXvg1gYidcP3G7HUC5fAuZ_active","boolValue":true}}]`) env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return nil + }, heightFunc: func() rideInt { return 451323 }, @@ -3397,7 +7308,11 @@ func TestRecipientAddressToString(t *testing.T) { Attachment: nil, }, } + env := &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return nil + }, schemeFunc: func() byte { return proto.TestNetScheme }, diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index 6f030c088..297afa4d8 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -218,6 +218,7 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { if err != nil { return nil, err } + switch res := r.(type) { case rideThrow: if e.dapp { @@ -227,31 +228,46 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { case rideBoolean: return ScriptResult{res: bool(res)}, nil case rideObject: - actions, err := objectToActions(e.env, res) + a, err := objectToActions(e.env, res) if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - return DAppResult{true, actions, ""}, nil + act := e.env.actions() + act = append(act, a...) + return DAppResult{res: true, actions: act, msg: ""}, nil case rideList: - actions := make([]proto.ScriptAction, len(res)) - for i, item := range res { + var newActions []proto.ScriptAction + for _, item := range res { a, err := convertToAction(e.env, item) if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - actions[i] = a + newActions = append(newActions, a) + } + + return DAppResult{res: true, actions: newActions}, nil + case tuple2: + var act []proto.ScriptAction + switch resAct := res.el1.(type) { + case rideList: + for _, item := range resAct { + a, err := convertToAction(e.env, item) + if err != nil { + return nil, errors.Wrap(err, "failed to convert evaluation result") + } + act = append(act, a) + } + + default: + return nil, errors.Errorf("unexpected result type '%T'", r) } - return DAppResult{res: true, actions: actions}, nil + + return DAppResult{res: true, actions: act, msg: "", param: res.el2}, nil default: return nil, errors.Errorf("unexpected result type '%T'", r) } } -// -//func (e *treeEvaluator) exceeded() bool { -// return e.limit > 0 && e.cost >= e.limit -//} - func isThrow(r rideType) bool { return r.instanceOf() == "Throw" } @@ -361,6 +377,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { if err != nil { return nil, errors.Wrapf(err, "failed to call system function '%s'", id) } + return r, nil } uf, cl, err := e.s.userFunction(id) @@ -370,6 +387,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { if len(n.Arguments) != len(uf.Arguments) { return nil, errors.Errorf("mismatched arguments number of user function '%s'", id) } + args := make([]esValue, len(n.Arguments)) for i, arg := range n.Arguments { an := uf.Arguments[i] @@ -388,6 +406,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { } var tmp int tmp, e.s.cl = e.s.cl, cl + r, err := e.walk(uf.Body) if err != nil { return nil, errors.Wrapf(err, "failed to evaluate function '%s' body", id) @@ -406,6 +425,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { return obj, nil } v, err := obj.get(name) + if err != nil { return nil, errors.Wrapf(err, "failed to get property '%s'", name) } @@ -451,6 +471,40 @@ func treeVerifierEvaluator(env RideEnvironment, tree *Tree) (*treeEvaluator, err }, nil } +func treeFunctionEvaluatorForInvokeDAppFromDApp(env RideEnvironment, tree *Tree, name string, args []rideType) (*treeEvaluator, error) { + s, err := newEvaluationScope(tree.LibVersion, env) + if err != nil { + return nil, errors.Wrap(err, "failed to create scope") + } + for _, declaration := range tree.Declarations { + err = s.declare(declaration) + if err != nil { + return nil, errors.Wrap(err, "invalid declaration") + } + } + if !tree.IsDApp() { + return nil, errors.Errorf("unable to call function '%s' on simple script", name) + } + for i := 0; i < len(tree.Functions); i++ { + function, ok := tree.Functions[i].(*FunctionDeclarationNode) + if !ok { + return nil, errors.New("invalid callable declaration") + } + if function.Name == name { + s.constants[function.invocationParameter] = esConstant{c: newInvocation} + if l := len(args); l != len(function.Arguments) { + return nil, errors.Errorf("invalid arguments count %d for function '%s'", l, name) + } + // without conversion + for i, arg := range args { + s.pushValue(function.Arguments[i], arg) + } + return &treeEvaluator{dapp: true, f: function.Body, s: s, env: env}, nil + } + } + return nil, errors.Errorf("function '%s' not found", name) +} + func treeFunctionEvaluator(env RideEnvironment, tree *Tree, name string, args proto.Arguments) (*treeEvaluator, error) { s, err := newEvaluationScope(tree.LibVersion, env) if err != nil { @@ -475,6 +529,7 @@ func treeFunctionEvaluator(env RideEnvironment, tree *Tree, name string, args pr if l := len(args); l != len(function.Arguments) { return nil, errors.Errorf("invalid arguments count %d for function '%s'", l, name) } + for i, arg := range args { a, err := convertArgument(arg) if err != nil { diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index e9fc571bc..086309e11 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -23,12 +23,18 @@ var _ types.SmartState = &MockSmartState{} // AddingBlockHeightFunc: func() (uint64, error) { // panic("mock out the AddingBlockHeight method") // }, +// ApplyToStateFunc: func(actions []proto.ScriptAction) error { +// panic("mock out the ApplyToState method") +// }, // BlockVRFFunc: func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { // panic("mock out the BlockVRF method") // }, // EstimatorVersionFunc: func() (int, error) { // panic("mock out the EstimatorVersion method") // }, +// GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { +// panic("mock out the GetByteTree method") +// }, // IsNotFoundFunc: func(err error) bool { // panic("mock out the IsNotFound method") // }, @@ -53,6 +59,12 @@ var _ types.SmartState = &MockSmartState{} // NewestHeaderByHeightFunc: func(height uint64) (*proto.BlockHeader, error) { // panic("mock out the NewestHeaderByHeight method") // }, +// NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { +// panic("mock out the NewestRecipientToAddress method") +// }, +// NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { +// panic("mock out the NewestScriptPKByAddr method") +// }, // NewestTransactionByIDFunc: func(in1 []byte) (proto.Transaction, error) { // panic("mock out the NewestTransactionByID method") // }, @@ -81,12 +93,18 @@ type MockSmartState struct { // AddingBlockHeightFunc mocks the AddingBlockHeight method. AddingBlockHeightFunc func() (uint64, error) + // ApplyToStateFunc mocks the ApplyToState method. + ApplyToStateFunc func(actions []proto.ScriptAction) error + // BlockVRFFunc mocks the BlockVRF method. BlockVRFFunc func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) // EstimatorVersionFunc mocks the EstimatorVersion method. EstimatorVersionFunc func() (int, error) + // GetByteTreeFunc mocks the GetByteTree method. + GetByteTreeFunc func(recipient proto.Recipient) (proto.Script, error) + // IsNotFoundFunc mocks the IsNotFound method. IsNotFoundFunc func(err error) bool @@ -111,6 +129,12 @@ type MockSmartState struct { // NewestHeaderByHeightFunc mocks the NewestHeaderByHeight method. NewestHeaderByHeightFunc func(height uint64) (*proto.BlockHeader, error) + // NewestRecipientToAddressFunc mocks the NewestRecipientToAddress method. + NewestRecipientToAddressFunc func(recipient proto.Recipient) (*proto.Address, error) + + // NewestScriptPKByAddrFunc mocks the NewestScriptPKByAddr method. + NewestScriptPKByAddrFunc func(addr proto.Address, filter bool) (crypto.PublicKey, error) + // NewestTransactionByIDFunc mocks the NewestTransactionByID method. NewestTransactionByIDFunc func(in1 []byte) (proto.Transaction, error) @@ -134,6 +158,11 @@ type MockSmartState struct { // AddingBlockHeight holds details about calls to the AddingBlockHeight method. AddingBlockHeight []struct { } + // ApplyToState holds details about calls to the ApplyToState method. + ApplyToState []struct { + // Actions is the actions argument value. + Actions []proto.ScriptAction + } // BlockVRF holds details about calls to the BlockVRF method. BlockVRF []struct { // BlockHeader is the blockHeader argument value. @@ -144,6 +173,11 @@ type MockSmartState struct { // EstimatorVersion holds details about calls to the EstimatorVersion method. EstimatorVersion []struct { } + // GetByteTree holds details about calls to the GetByteTree method. + GetByteTree []struct { + // Recipient is the recipient argument value. + Recipient proto.Recipient + } // IsNotFound holds details about calls to the IsNotFound method. IsNotFound []struct { // Err is the err argument value. @@ -186,6 +220,18 @@ type MockSmartState struct { // Height is the height argument value. Height uint64 } + // NewestRecipientToAddress holds details about calls to the NewestRecipientToAddress method. + NewestRecipientToAddress []struct { + // Recipient is the recipient argument value. + Recipient proto.Recipient + } + // NewestScriptPKByAddr holds details about calls to the NewestScriptPKByAddr method. + NewestScriptPKByAddr []struct { + // Addr is the addr argument value. + Addr proto.Address + // Filter is the filter argument value. + Filter bool + } // NewestTransactionByID holds details about calls to the NewestTransactionByID method. NewestTransactionByID []struct { // In1 is the in1 argument value. @@ -226,8 +272,10 @@ type MockSmartState struct { } } lockAddingBlockHeight sync.RWMutex + lockApplyToState sync.RWMutex lockBlockVRF sync.RWMutex lockEstimatorVersion sync.RWMutex + lockGetByteTree sync.RWMutex lockIsNotFound sync.RWMutex lockNewestAccountBalance sync.RWMutex lockNewestAddrByAlias sync.RWMutex @@ -236,6 +284,8 @@ type MockSmartState struct { lockNewestFullAssetInfo sync.RWMutex lockNewestFullWavesBalance sync.RWMutex lockNewestHeaderByHeight sync.RWMutex + lockNewestRecipientToAddress sync.RWMutex + lockNewestScriptPKByAddr sync.RWMutex lockNewestTransactionByID sync.RWMutex lockNewestTransactionHeightByID sync.RWMutex lockRetrieveNewestBinaryEntry sync.RWMutex @@ -270,6 +320,37 @@ func (mock *MockSmartState) AddingBlockHeightCalls() []struct { return calls } +// ApplyToState calls ApplyToStateFunc. +func (mock *MockSmartState) ApplyToState(actions []proto.ScriptAction) error { + if mock.ApplyToStateFunc == nil { + panic("MockSmartState.ApplyToStateFunc: method is nil but SmartState.ApplyToState was just called") + } + callInfo := struct { + Actions []proto.ScriptAction + }{ + Actions: actions, + } + mock.lockApplyToState.Lock() + mock.calls.ApplyToState = append(mock.calls.ApplyToState, callInfo) + mock.lockApplyToState.Unlock() + return mock.ApplyToStateFunc(actions) +} + +// ApplyToStateCalls gets all the calls that were made to ApplyToState. +// Check the length with: +// len(mockedSmartState.ApplyToStateCalls()) +func (mock *MockSmartState) ApplyToStateCalls() []struct { + Actions []proto.ScriptAction +} { + var calls []struct { + Actions []proto.ScriptAction + } + mock.lockApplyToState.RLock() + calls = mock.calls.ApplyToState + mock.lockApplyToState.RUnlock() + return calls +} + // BlockVRF calls BlockVRFFunc. func (mock *MockSmartState) BlockVRF(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { if mock.BlockVRFFunc == nil { @@ -331,6 +412,37 @@ func (mock *MockSmartState) EstimatorVersionCalls() []struct { return calls } +// GetByteTree calls GetByteTreeFunc. +func (mock *MockSmartState) GetByteTree(recipient proto.Recipient) (proto.Script, error) { + if mock.GetByteTreeFunc == nil { + panic("MockSmartState.GetByteTreeFunc: method is nil but SmartState.GetByteTree was just called") + } + callInfo := struct { + Recipient proto.Recipient + }{ + Recipient: recipient, + } + mock.lockGetByteTree.Lock() + mock.calls.GetByteTree = append(mock.calls.GetByteTree, callInfo) + mock.lockGetByteTree.Unlock() + return mock.GetByteTreeFunc(recipient) +} + +// GetByteTreeCalls gets all the calls that were made to GetByteTree. +// Check the length with: +// len(mockedSmartState.GetByteTreeCalls()) +func (mock *MockSmartState) GetByteTreeCalls() []struct { + Recipient proto.Recipient +} { + var calls []struct { + Recipient proto.Recipient + } + mock.lockGetByteTree.RLock() + calls = mock.calls.GetByteTree + mock.lockGetByteTree.RUnlock() + return calls +} + // IsNotFound calls IsNotFoundFunc. func (mock *MockSmartState) IsNotFound(err error) bool { if mock.IsNotFoundFunc == nil { @@ -583,6 +695,72 @@ func (mock *MockSmartState) NewestHeaderByHeightCalls() []struct { return calls } +// NewestRecipientToAddress calls NewestRecipientToAddressFunc. +func (mock *MockSmartState) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { + if mock.NewestRecipientToAddressFunc == nil { + panic("MockSmartState.NewestRecipientToAddressFunc: method is nil but SmartState.NewestRecipientToAddress was just called") + } + callInfo := struct { + Recipient proto.Recipient + }{ + Recipient: recipient, + } + mock.lockNewestRecipientToAddress.Lock() + mock.calls.NewestRecipientToAddress = append(mock.calls.NewestRecipientToAddress, callInfo) + mock.lockNewestRecipientToAddress.Unlock() + return mock.NewestRecipientToAddressFunc(recipient) +} + +// NewestRecipientToAddressCalls gets all the calls that were made to NewestRecipientToAddress. +// Check the length with: +// len(mockedSmartState.NewestRecipientToAddressCalls()) +func (mock *MockSmartState) NewestRecipientToAddressCalls() []struct { + Recipient proto.Recipient +} { + var calls []struct { + Recipient proto.Recipient + } + mock.lockNewestRecipientToAddress.RLock() + calls = mock.calls.NewestRecipientToAddress + mock.lockNewestRecipientToAddress.RUnlock() + return calls +} + +// NewestScriptPKByAddr calls NewestScriptPKByAddrFunc. +func (mock *MockSmartState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { + if mock.NewestScriptPKByAddrFunc == nil { + panic("MockSmartState.NewestScriptPKByAddrFunc: method is nil but SmartState.NewestScriptPKByAddr was just called") + } + callInfo := struct { + Addr proto.Address + Filter bool + }{ + Addr: addr, + Filter: filter, + } + mock.lockNewestScriptPKByAddr.Lock() + mock.calls.NewestScriptPKByAddr = append(mock.calls.NewestScriptPKByAddr, callInfo) + mock.lockNewestScriptPKByAddr.Unlock() + return mock.NewestScriptPKByAddrFunc(addr, filter) +} + +// NewestScriptPKByAddrCalls gets all the calls that were made to NewestScriptPKByAddr. +// Check the length with: +// len(mockedSmartState.NewestScriptPKByAddrCalls()) +func (mock *MockSmartState) NewestScriptPKByAddrCalls() []struct { + Addr proto.Address + Filter bool +} { + var calls []struct { + Addr proto.Address + Filter bool + } + mock.lockNewestScriptPKByAddr.RLock() + calls = mock.calls.NewestScriptPKByAddr + mock.lockNewestScriptPKByAddr.RUnlock() + return calls +} + // NewestTransactionByID calls NewestTransactionByIDFunc. func (mock *MockSmartState) NewestTransactionByID(in1 []byte) (proto.Transaction, error) { if mock.NewestTransactionByIDFunc == nil { diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 6c23d19df..84723b5b4 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -622,7 +622,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf if err != nil { return nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) } - scriptPK, err := ia.stor.scriptsStorage.newestScriptPKByAddr(*scriptAddr, !info.initialisation) + scriptPK, err := ia.stor.scriptsStorage.NewestScriptPKByAddr(*scriptAddr, !info.initialisation) if err != nil { return nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) } diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 25a05c251..ae7cccaca 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -735,7 +735,7 @@ func TestFailedApplyInvokeScript(t *testing.T) { @Callable(i) func simpleLeaseToAddress(rcp: String, amount: Int) = { let addr = addressFromStringValue(rcp) - [Lease(addr, amount)] + ([Lease(addr, amount)], unit) } @Callable(i) @@ -743,13 +743,13 @@ func detailedLeaseToAddress(rcp: String, amount: Int) = { let addr = addressFromStringValue(rcp) let lease = Lease(addr, amount, 0) let id = calculateLeaseId(lease) - [lease] + ([lease], id) } @Callable(i) func simpleLeaseToAlias(rcp: String, amount: Int) = { let alias = Alias(rcp) - [Lease(alias, amount)] + ([Lease(alias, amount)], unit) } @Callable(i) @@ -757,23 +757,23 @@ func detailedLeaseToAlias(rcp: String, amount: Int) = { let alias = Alias(rcp) let lease = Lease(alias, amount, 0) let id = calculateLeaseId(lease) - [lease] + ([lease], id) } @Callable(i) func simpleLeaseToSender(amount: Int) = { - [Lease(i.caller, amount)] + ([Lease(i.caller, amount)], unit) } @Callable(i) func detailedLeaseToSender(amount: Int) = { let lease = Lease(i.caller, amount, 0) let id = calculateLeaseId(lease) - [lease] + ([lease], id) } @Callable(i) -func cancel(id: ByteVector) = [LeaseCancel(id)] +func cancel(id: ByteVector) = ([LeaseCancel(id)], unit) */ diff --git a/pkg/state/scripts_storage.go b/pkg/state/scripts_storage.go index 49b382208..5300d6087 100644 --- a/pkg/state/scripts_storage.go +++ b/pkg/state/scripts_storage.go @@ -381,7 +381,7 @@ func (ss *scriptsStorage) newestScriptByAddr(addr proto.Address, filter bool) (* return tree, nil } -func (ss *scriptsStorage) newestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { +func (ss *scriptsStorage) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { key := accountScriptKey{addr} recordBytes, err := ss.hs.newestTopEntryData(key.bytes(), filter) if err != nil { diff --git a/pkg/state/state.go b/pkg/state/state.go index 45821d475..a4ce0e007 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -468,6 +468,32 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc return state, nil } +func (s *stateManager) ApplyToState(actions []proto.ScriptAction) error { + return nil +} + +func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, error) { + if recipient.Address != nil { + script, err := s.stor.scriptsStorage.scriptBytesByAddr(*recipient.Address, false) + if err != nil { + return nil, errors.Wrapf(err, "Failed to get script by address") + } + return script, nil + } + if recipient.Alias != nil { + address, err := s.NewestAddrByAlias(*recipient.Alias) + if err != nil { + return nil, errors.Wrapf(err, "Failed to get address by alias") + } + script, err := s.stor.scriptsStorage.scriptBytesByAddr(address, false) + if err != nil { + return nil, errors.Wrapf(err, "Failed to get script by address") + } + return script, nil + } + return nil, errors.Errorf("Address and alias from recipient are nil") +} + func (s *stateManager) Mutex() *lock.RwMutex { return lock.NewRwMutex(s.mu) } @@ -654,6 +680,10 @@ func (s *stateManager) BlockByHeight(height uint64) (*proto.Block, error) { return s.Block(blockID) } +func (s *stateManager) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return s.stor.scriptsStorage.NewestScriptPKByAddr(addr, filter) +} + func (s *stateManager) AddingBlockHeight() (uint64, error) { return s.rw.addingBlockHeight(), nil } @@ -785,7 +815,7 @@ func (s *stateManager) FullWavesBalance(account proto.Recipient) (*proto.FullWav } func (s *stateManager) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -814,7 +844,7 @@ func (s *stateManager) NewestFullWavesBalance(account proto.Recipient) (*proto.F } func (s *stateManager) NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return 0, wrapErr(RetrievalError, err) } @@ -1437,7 +1467,7 @@ func (s *stateManager) CurrentScore() (*big.Int, error) { return s.ScoreAtHeight(height) } -func (s *stateManager) newestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { +func (s *stateManager) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { if recipient.Address == nil { return s.stor.aliases.newestAddrByAlias(recipient.Alias.Alias, true) } @@ -1464,7 +1494,7 @@ func (s *stateManager) EffectiveBalance(account proto.Recipient, startHeight, en } func (s *stateManager) NewestEffectiveBalance(account proto.Recipient, startHeight, endHeight uint64) (uint64, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return 0, wrapErr(RetrievalError, err) } @@ -1612,7 +1642,7 @@ func (s *stateManager) EstimatorVersion() (int, error) { // Accounts data storage. func (s *stateManager) RetrieveNewestEntry(account proto.Recipient, key string) (proto.DataEntry, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -1648,7 +1678,7 @@ func (s *stateManager) RetrieveEntry(account proto.Recipient, key string) (proto } func (s *stateManager) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -1672,7 +1702,7 @@ func (s *stateManager) RetrieveIntegerEntry(account proto.Recipient, key string) } func (s *stateManager) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -1696,7 +1726,7 @@ func (s *stateManager) RetrieveBooleanEntry(account proto.Recipient, key string) } func (s *stateManager) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -1720,7 +1750,7 @@ func (s *stateManager) RetrieveStringEntry(account proto.Recipient, key string) } func (s *stateManager) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - addr, err := s.newestRecipientToAddress(account) + addr, err := s.NewestRecipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } diff --git a/pkg/state/testdata/scripts/ride5_leasing.base64 b/pkg/state/testdata/scripts/ride5_leasing.base64 index 55f40bae6..d3e6ff2a0 100644 --- a/pkg/state/testdata/scripts/ride5_leasing.base64 +++ b/pkg/state/testdata/scripts/ride5_leasing.base64 @@ -1 +1 @@ -AAIFAAAAAAAAACkIAhIECgIIARIECgIIARIECgIIARIECgIIARIDCgEBEgMKAQESAwoBAgAAAAAAAAAHAAAAAWkBAAAAFHNpbXBsZUxlYXNlVG9BZGRyZXNzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAARhZGRyCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAANyY3AJAARMAAAAAgkABEQAAAACBQAAAARhZGRyBQAAAAZhbW91bnQFAAAAA25pbAAAAAFpAQAAABZkZXRhaWxlZExlYXNlVG9BZGRyZXNzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAARhZGRyCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAANyY3AEAAAABWxlYXNlCQAERQAAAAMFAAAABGFkZHIFAAAABmFtb3VudAAAAAAAAAAAAAQAAAACaWQJAAQ5AAAAAQUAAAAFbGVhc2UJAARMAAAAAgUAAAAFbGVhc2UFAAAAA25pbAAAAAFpAQAAABJzaW1wbGVMZWFzZVRvQWxpYXMAAAACAAAAA3JjcAAAAAZhbW91bnQEAAAABWFsaWFzCQEAAAAFQWxpYXMAAAABBQAAAANyY3AJAARMAAAAAgkABEQAAAACBQAAAAVhbGlhcwUAAAAGYW1vdW50BQAAAANuaWwAAAABaQEAAAAUZGV0YWlsZWRMZWFzZVRvQWxpYXMAAAACAAAAA3JjcAAAAAZhbW91bnQEAAAABWFsaWFzCQEAAAAFQWxpYXMAAAABBQAAAANyY3AEAAAABWxlYXNlCQAERQAAAAMFAAAABWFsaWFzBQAAAAZhbW91bnQAAAAAAAAAAAAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwAAAABaQEAAAATc2ltcGxlTGVhc2VUb1NlbmRlcgAAAAEAAAAGYW1vdW50CQAETAAAAAIJAAREAAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQFAAAAA25pbAAAAAFpAQAAABVkZXRhaWxlZExlYXNlVG9TZW5kZXIAAAABAAAABmFtb3VudAQAAAAFbGVhc2UJAARFAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQAAAAAAAAAAAAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwAAAABaQEAAAAGY2FuY2VsAAAAAQAAAAJpZAkABEwAAAACCQEAAAALTGVhc2VDYW5jZWwAAAABBQAAAAJpZAUAAAADbmlsAAAAABW3T5I= \ No newline at end of file +AAIFAAAAAAAAACkIAhIECgIIARIECgIIARIECgIIARIECgIIARIDCgEBEgMKAQESAwoBAgAAAAAAAAAHAAAAAWkBAAAAFHNpbXBsZUxlYXNlVG9BZGRyZXNzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAARhZGRyCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAANyY3AJAAUUAAAAAgkABEwAAAACCQAERAAAAAIFAAAABGFkZHIFAAAABmFtb3VudAUAAAADbmlsBQAAAAR1bml0AAAAAWkBAAAAFmRldGFpbGVkTGVhc2VUb0FkZHJlc3MAAAACAAAAA3JjcAAAAAZhbW91bnQEAAAABGFkZHIJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAA3JjcAQAAAAFbGVhc2UJAARFAAAAAwUAAAAEYWRkcgUAAAAGYW1vdW50AAAAAAAAAAAABAAAAAJpZAkABDkAAAABBQAAAAVsZWFzZQkABRQAAAACCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwFAAAAAmlkAAAAAWkBAAAAEnNpbXBsZUxlYXNlVG9BbGlhcwAAAAIAAAADcmNwAAAABmFtb3VudAQAAAAFYWxpYXMJAQAAAAVBbGlhcwAAAAEFAAAAA3JjcAkABRQAAAACCQAETAAAAAIJAAREAAAAAgUAAAAFYWxpYXMFAAAABmFtb3VudAUAAAADbmlsBQAAAAR1bml0AAAAAWkBAAAAFGRldGFpbGVkTGVhc2VUb0FsaWFzAAAAAgAAAANyY3AAAAAGYW1vdW50BAAAAAVhbGlhcwkBAAAABUFsaWFzAAAAAQUAAAADcmNwBAAAAAVsZWFzZQkABEUAAAADBQAAAAVhbGlhcwUAAAAGYW1vdW50AAAAAAAAAAAABAAAAAJpZAkABDkAAAABBQAAAAVsZWFzZQkABRQAAAACCQAETAAAAAIFAAAABWxlYXNlBQAAAANuaWwFAAAAAmlkAAAAAWkBAAAAE3NpbXBsZUxlYXNlVG9TZW5kZXIAAAABAAAABmFtb3VudAkABRQAAAACCQAETAAAAAIJAAREAAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQFAAAAA25pbAUAAAAEdW5pdAAAAAFpAQAAABVkZXRhaWxlZExlYXNlVG9TZW5kZXIAAAABAAAABmFtb3VudAQAAAAFbGVhc2UJAARFAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQAAAAAAAAAAAAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAFFAAAAAIJAARMAAAAAgUAAAAFbGVhc2UFAAAAA25pbAUAAAACaWQAAAABaQEAAAAGY2FuY2VsAAAAAQAAAAJpZAkABRQAAAACCQAETAAAAAIJAQAAAAtMZWFzZUNhbmNlbAAAAAEFAAAAAmlkBQAAAANuaWwFAAAAAmlkAAAAAOkd5dA= \ No newline at end of file diff --git a/pkg/types/types.go b/pkg/types/types.go index 6f9d43104..1bbb3ffb4 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -35,15 +35,18 @@ type TransactionWithBytes struct { // state for smart contracts type SmartState interface { + NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) AddingBlockHeight() (uint64, error) NewestTransactionByID([]byte) (proto.Transaction, error) NewestTransactionHeightByID([]byte) (uint64, error) + GetByteTree(recipient proto.Recipient) (proto.Script, error) + NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) + NewestAddrByAlias(alias proto.Alias) (proto.Address, error) // NewestAccountBalance retrieves balance of address in specific currency, asset is asset's ID. // nil asset = Waves. NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) - NewestAddrByAlias(alias proto.Alias) (proto.Address, error) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) @@ -51,9 +54,11 @@ type SmartState interface { NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) + // NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) + ApplyToState(actions []proto.ScriptAction) error EstimatorVersion() (int, error) IsNotFound(err error) bool } From f161a8db91182bc1977ea6f2344c5838ef29a79f Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 12 Jan 2021 16:27:57 +0300 Subject: [PATCH 04/52] Ride fix actions dapp from dapp (#408) * Added sender to actions, fixed first test * Fixed tests * Added teardown * Changed name of function * Fixed naming. Comments removed. * Protobuf schemas submodule switched to tag v1.3.0 * Address was changed to PK in Sender Co-authored-by: Alexey Kiselev --- pkg/grpc/protobuf-schemas | 2 +- pkg/proto/scripting.go | 10 +- pkg/proto/scripting_test.go | 21 +- pkg/ride/environment.go | 118 +- pkg/ride/functions_proto.go | 37 +- pkg/ride/runtime.go | 2 +- pkg/ride/runtime_moq_test.go | 6 +- pkg/ride/tree_evaluation_test.go | 4176 +++++++----------------------- pkg/ride/tree_evaluator.go | 4 +- pkg/ride/types_moq_test.go | 6 +- pkg/state/state.go | 4 +- pkg/types/types.go | 2 +- 12 files changed, 1156 insertions(+), 3232 deletions(-) diff --git a/pkg/grpc/protobuf-schemas b/pkg/grpc/protobuf-schemas index 41bcd5544..359f1d9c8 160000 --- a/pkg/grpc/protobuf-schemas +++ b/pkg/grpc/protobuf-schemas @@ -1 +1 @@ -Subproject commit 41bcd554482810f40bdc387b4cd29a96b213dedf +Subproject commit 359f1d9c802e7fd4898d1732f67ce950c466940e diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index 3b1fe416d..96e7c19f2 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -17,7 +17,8 @@ type ScriptAction interface { // DataEntryScriptAction is an action to manipulate account data state. type DataEntryScriptAction struct { - Entry DataEntry + Sender crypto.PublicKey + Entry DataEntry } func (a DataEntryScriptAction) scriptAction() {} @@ -28,6 +29,7 @@ func (a *DataEntryScriptAction) ToProtobuf() *g.DataTransactionData_DataEntry { // TransferScriptAction is an action to emit transfer of asset. type TransferScriptAction struct { + Sender crypto.PublicKey Recipient Recipient Amount int64 Asset OptionalAsset @@ -50,6 +52,7 @@ func (a *TransferScriptAction) ToProtobuf() (*g.InvokeScriptResult_Payment, erro // IssueScriptAction is an action to issue a new asset as a result of script invocation. type IssueScriptAction struct { + Sender crypto.PublicKey ID crypto.Digest // calculated field Name string // name Description string // description @@ -103,6 +106,7 @@ func GenerateIssueScriptActionID(name, description string, decimals, quantity in // ReissueScriptAction is an action to emit Reissue transaction as a result of script invocation. type ReissueScriptAction struct { + Sender crypto.PublicKey AssetID crypto.Digest // assetId Quantity int64 // quantity Reissuable bool // isReissuable @@ -120,6 +124,7 @@ func (a *ReissueScriptAction) ToProtobuf() *g.InvokeScriptResult_Reissue { // BurnScriptAction is an action to burn some assets in response to script invocation. type BurnScriptAction struct { + Sender crypto.PublicKey AssetID crypto.Digest // assetId Quantity int64 // quantity } @@ -135,6 +140,7 @@ func (a *BurnScriptAction) ToProtobuf() *g.InvokeScriptResult_Burn { // SponsorshipScriptAction is an action to set sponsorship for given asset in response to script invocation. type SponsorshipScriptAction struct { + Sender crypto.PublicKey AssetID crypto.Digest // assetId MinFee int64 // minSponsoredAssetFee } @@ -152,6 +158,7 @@ func (a *SponsorshipScriptAction) ToProtobuf() *g.InvokeScriptResult_SponsorFee // LeaseScriptAction is an action to lease Waves to given account. type LeaseScriptAction struct { + Sender crypto.PublicKey ID crypto.Digest Recipient Recipient Amount int64 @@ -197,6 +204,7 @@ func GenerateLeaseScriptActionID(recipient Recipient, amount int64, nonce int64, // LeaseCancelScriptAction is an action that cancels previously created lease. type LeaseCancelScriptAction struct { + Sender crypto.PublicKey LeaseID crypto.Digest } diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index 19be83459..97b55bac2 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -2,6 +2,7 @@ package proto import ( "fmt" + "github.com/wavesplatform/gowaves/pkg/crypto" "math" "strings" "testing" @@ -33,15 +34,15 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { for i, test := range []ScriptResult{ { DataEntries: []*DataEntryScriptAction{ - {&IntegerDataEntry{"some key", 12345}}, - {&BooleanDataEntry{"negative value", false}}, - {&StringDataEntry{"some key", "some value string"}}, - {&BinaryDataEntry{Key: "k3", Value: []byte{0x24, 0x7f, 0x71, 0x14, 0x1d}}}, - {&IntegerDataEntry{"some key2", -12345}}, - {&BooleanDataEntry{"negative value2", true}}, - {&StringDataEntry{"some key143", "some value2 string"}}, - {&BinaryDataEntry{Key: "k5", Value: []byte{0x24, 0x7f, 0x71, 0x10, 0x1d}}}, - {&DeleteDataEntry{Key: "xxx"}}, + {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key", 12345}}, + {Sender: crypto.PublicKey{}, Entry: &BooleanDataEntry{"negative value", false}}, + {Sender: crypto.PublicKey{}, Entry: &StringDataEntry{"some key", "some value string"}}, + {Sender: crypto.PublicKey{}, Entry: &BinaryDataEntry{Key: "k3", Value: []byte{0x24, 0x7f, 0x71, 0x14, 0x1d}}}, + {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key2", -12345}}, + {Sender: crypto.PublicKey{}, Entry: &BooleanDataEntry{"negative value2", true}}, + {Sender: crypto.PublicKey{}, Entry: &StringDataEntry{"some key143", "some value2 string"}}, + {Sender: crypto.PublicKey{}, Entry: &BinaryDataEntry{Key: "k5", Value: []byte{0x24, 0x7f, 0x71, 0x10, 0x1d}}}, + {Sender: crypto.PublicKey{}, Entry: &DeleteDataEntry{Key: "xxx"}}, }, Transfers: []*TransferScriptAction{ {Amount: math.MaxInt64, Asset: *waves, Recipient: rcp}, @@ -58,7 +59,7 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { }, { DataEntries: []*DataEntryScriptAction{ - {&IntegerDataEntry{"some key", 12345}}, + {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key", 12345}}, }, Transfers: emptyTransfers, Issues: emptyIssues, diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 21b53be22..6a042507f 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -272,7 +272,7 @@ func (wrappedSt *wrappedState) IsNotFound(err error) bool { return wrappedSt.diff.state.IsNotFound(err) } -func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error { +func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { for _, action := range actions { switch res := action.(type) { @@ -286,61 +286,122 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error addr := proto.Address(wrappedSt.envThis) wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.StringDataEntry: stringEntry := *dataEntry addr := proto.Address(wrappedSt.envThis) wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.BooleanDataEntry: boolEntry := *dataEntry addr := proto.Address(wrappedSt.envThis) wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.BinaryDataEntry: binaryEntry := *dataEntry addr := proto.Address(wrappedSt.envThis) wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.DeleteDataEntry: deleteEntry := *dataEntry addr := proto.Address(wrappedSt.envThis) wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK default: } case *proto.TransferScriptAction: + var senderAddress proto.Address + + emptyPK := crypto.PublicKey{} + + var senderPK crypto.PublicKey + + if res.Sender != emptyPK { + senderPK = res.Sender + var err error + senderAddress, err = proto.NewAddressFromPublicKey(wrappedSt.envScheme, senderPK) + if err != nil { + return nil, errors.Wrap(err, "failed to get address by public key") + } + } else { + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + senderPK = pk + + senderAddress = proto.Address(wrappedSt.envThis) + } + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) if err != nil { - return err + return nil, err } err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) if err != nil { - return err + return nil, err } - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) + senderRecipient := proto.NewRecipientFromAddress(senderAddress) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset.ID.Bytes()) if err != nil { - return err + return nil, err } - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecipient) if err != nil { - return err + return nil, err } + res.Sender = senderPK + case *proto.SponsorshipScriptAction: var sponsorship diffSponsorship sponsorship.MinFee = res.MinFee wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.IssueScriptAction: var assetInfo diffNewAssetInfo assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) @@ -354,6 +415,12 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.ReissueScriptAction: searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) if searchNewAsset == nil { @@ -366,6 +433,12 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error } wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.BurnScriptAction: searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) if searchAsset == nil { @@ -379,16 +452,23 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) error } wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + default: } } - return nil + return actions, nil } type wrappedState struct { - diff diffState - envThis rideAddress + diff diffState + envThis rideAddress + envScheme proto.Scheme } type Environment struct { @@ -405,7 +485,7 @@ type Environment struct { invokeCount uint64 } -func newWrappedState(state types.SmartState, envThis rideType) types.SmartState { +func newWrappedState(state types.SmartState, envThis rideType, envScheme proto.Scheme) types.SmartState { var dataEntries diffDataEntries dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} @@ -561,7 +641,7 @@ func (e *Environment) setNewDAppAddress(address proto.Address) { e.SetThisFromAddress(address) } -func (e *Environment) applyToState(actions []proto.ScriptAction) error { +func (e *Environment) applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { return e.st.ApplyToState(actions) } @@ -572,12 +652,16 @@ func (e *Environment) appendActions(actions []proto.ScriptAction) { func (e *Environment) smartAppendActions(actions []proto.ScriptAction) error { _, ok := e.st.(*wrappedState) if !ok { - wrappedSt := newWrappedState(e.state(), e.this()) + wrappedSt := newWrappedState(e.state(), e.this(), e.sch) e.st = wrappedSt } - e.appendActions(actions) - return e.applyToState(actions) + modifiedActions, err := e.applyToState(actions) + if err != nil { + return err + } + e.appendActions(modifiedActions) + return nil } func (e *Environment) checkMessageLength(l int) bool { return e.check(l) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index d0494703e..6d924de05 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -18,17 +18,30 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { if env.invCount() > 9 { return rideUnit{}, nil } - oldAddress := env.this() + callerAddress, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, errors.Errorf("invoke: this has an unexpected type '%s'", env.this().instanceOf()) + } recipient, err := extractRecipient(args[0]) if err != nil { return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[0].instanceOf()) } - fnName, ok := args[1].(rideString) - if !ok { + var fnName rideString + switch fnN := args[1].(type) { + case rideUnit: + fnName = "default" + case rideString: + if fnN == "" { + fnName = "default" + break + } + fnName = fnN + default: return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[1].instanceOf()) } + listArg, ok := args[2].(rideList) if !ok { return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[2].instanceOf()) @@ -39,8 +52,8 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { payments := args[3].(rideList) invocationParam := env.invocation() - invocationParam["caller"] = oldAddress.(rideAddress) - callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(oldAddress.(rideAddress)), false) + invocationParam["caller"] = callerAddress + callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(callerAddress), false) if err != nil { return nil, errors.Wrapf(err, "failed to get caller public key by address") } @@ -78,28 +91,28 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { var paymentActions []proto.ScriptAction for _, payment := range attachedPayments { - action := &proto.TransferScriptAction{Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} + action := &proto.TransferScriptAction{Sender: callerPublicKey, Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} paymentActions = append(paymentActions, action) } - err = env.applyToState(paymentActions) - if err != nil { - return nil, errors.Wrapf(err, "Failed to apply attachedPayments") - } - res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) if err != nil { return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") } + err = env.smartAppendActions(paymentActions) + if err != nil { + return nil, errors.Wrapf(err, "Failed to apply attachedPayments") + } + if res.Result() { if res.UserError() != "" { return nil, errors.Errorf(res.UserError()) } err = env.smartAppendActions(res.ScriptActions()) - env.setNewDAppAddress(proto.Address(oldAddress.(rideAddress))) + env.setNewDAppAddress(proto.Address(callerAddress)) if err != nil { return nil, err } diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index c800324d4..4ddbbd4bd 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -341,7 +341,7 @@ type RideEnvironment interface { block() rideObject txID() rideType // Invoke transaction ID state() types.SmartState - applyToState(actions []proto.ScriptAction) error + applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) appendActions(actions []proto.ScriptAction) smartAppendActions(actions []proto.ScriptAction) error actions() []proto.ScriptAction diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index 543ee6c9f..68bb9fa79 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -28,7 +28,7 @@ var _ RideEnvironment = &MockRideEnvironment{} // appendActionsFunc: func(actions []proto.ScriptAction) { // panic("mock out the appendActions method") // }, -// applyToStateFunc: func(actions []proto.ScriptAction) error { +// applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { // panic("mock out the applyToState method") // }, // blockFunc: func() rideObject { @@ -87,7 +87,7 @@ type MockRideEnvironment struct { appendActionsFunc func(actions []proto.ScriptAction) // applyToStateFunc mocks the applyToState method. - applyToStateFunc func(actions []proto.ScriptAction) error + applyToStateFunc func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) // blockFunc mocks the block method. blockFunc func() rideObject @@ -302,7 +302,7 @@ func (mock *MockRideEnvironment) appendActionsCalls() []struct { } // applyToState calls applyToStateFunc. -func (mock *MockRideEnvironment) applyToState(actions []proto.ScriptAction) error { +func (mock *MockRideEnvironment) applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { if mock.applyToStateFunc == nil { panic("MockRideEnvironment.applyToStateFunc: method is nil but RideEnvironment.applyToState was just called") } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 404c6552e..591d8f39e 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -825,6 +825,527 @@ func initWrappedState(state types.SmartState, envThis rideAddress) *wrappedState return &wrappedSt } +var wrappedSt wrappedState +var firstScript string +var secondScript string +var assetIDIssue crypto.Digest +var addr proto.Address +var addrPK crypto.PublicKey +var addressCallable proto.Address +var addressCallablePK crypto.PublicKey + +func smartStateDappFromDapp() types.SmartState { + return &MockSmartState{ + ApplyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { + + for _, action := range actions { + switch res := action.(type) { + + case *proto.DataEntryScriptAction: + + switch dataEntry := res.Entry.(type) { + + case *proto.IntegerDataEntry: + intEntry := *dataEntry + address := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+address.String()] = intEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + case *proto.StringDataEntry: + stringEntry := *dataEntry + address := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffString[dataEntry.Key+address.String()] = stringEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.BooleanDataEntry: + boolEntry := *dataEntry + address := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+address.String()] = boolEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.BinaryDataEntry: + binaryEntry := *dataEntry + address := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+address.String()] = binaryEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.DeleteDataEntry: + deleteEntry := *dataEntry + address := proto.Address(wrappedSt.envThis) + + wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+address.String()] = deleteEntry + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + default: + + } + + case *proto.TransferScriptAction: + var senderAddress proto.Address + + emptyPK := crypto.PublicKey{} + + var senderPK crypto.PublicKey + + if res.Sender != emptyPK { + senderPK = res.Sender + if senderPK.String() == addrPK.String() { + senderAddress = addr + } else { + senderAddress = addressCallable + } + + } else { + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + senderPK = pk + + senderAddress = proto.Address(wrappedSt.envThis) + } + + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + if err != nil { + return nil, err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + if err != nil { + return nil, err + } + senderRecipient := proto.NewRecipientFromAddress(senderAddress) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset.ID.Bytes()) + if err != nil { + return nil, err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecipient) + if err != nil { + return nil, err + } + + res.Sender = senderPK + + case *proto.SponsorshipScriptAction: + var sponsorship diffSponsorship + sponsorship.MinFee = res.MinFee + + wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.IssueScriptAction: + var assetInfo diffNewAssetInfo + assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.name = res.Name + assetInfo.description = res.Description + assetInfo.quantity = res.Quantity + assetInfo.decimals = res.Decimals + assetInfo.reissuable = res.Reissuable + assetInfo.script = res.Script + assetInfo.nonce = res.Nonce + + assetIDIssue = res.ID + + wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.ReissueScriptAction: + searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchNewAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + break + } + wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + case *proto.BurnScriptAction: + searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + var assetInfo diffOldAssetInfo + + assetInfo.diffQuantity += -res.Quantity + + wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + + break + } + wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + + senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = senderPK + + default: + } + + } + return actions, nil + }, + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var script proto.Script + var err error + if recipient.Address.String() == addr.String() { + script, err = base64.StdEncoding.DecodeString(firstScript) + } + if recipient.Address.String() == addressCallable.String() { + script, err = base64.StdEncoding.DecodeString(secondScript) + } + if err != nil { + return proto.Script{}, err + } + return script, nil + }, + NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + return recipient.Address, nil + }, + AddingBlockHeightFunc: func() (uint64, error) { + return 10, nil + }, + NewestScriptPKByAddrFunc: func(address proto.Address, filter bool) (crypto.PublicKey, error) { + if address == addr { + return crypto.MustPublicKeyFromBase58("JBjPD1xkTTcYUVhbLp1bLJLcjDKLT3c32RVk9Rue87ZD"), nil + } + if address == addressCallable { + return crypto.MustPublicKeyFromBase58("8TLsCqkkroVot9dVR1WcWUN9Qx96HDfzG3hnx7NpSJA9"), nil + } + return crypto.PublicKey{}, nil + }, + NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { + return nil, nil + }, + NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + balance := 0 + balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + if err != nil { + return 0, err + } + if balanceDiff != nil { + resBalance := int64(balance) + balanceDiff.amount + return uint64(resBalance), nil + + } + return uint64(balance), nil + }, + NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance := 0 + + wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + if err != nil { + return nil, err + } + if wavesBalanceDiff != nil { + resRegular := wavesBalanceDiff.amount + int64(balance) + resGenerating := wavesBalanceDiff.amount + int64(balance) + resAvailable := wavesBalanceDiff.amount + int64(balance) + resEffective := wavesBalanceDiff.amount + int64(balance) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), + Generating: uint64(resGenerating), + Available: uint64(resAvailable), + Effective: uint64(resEffective), + LeaseIn: 0, + LeaseOut: 0}, nil + + } + return &proto.FullWavesBalance{ + Regular: 0, + Generating: 0, + Available: 0, + Effective: 0, + LeaseIn: 0, + LeaseOut: 0}, nil + }, + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + return intDataEntry, nil + } + + return nil, nil + }, + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + return boolDataEntry, nil + } + return nil, nil + }, + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + return stringDataEntry, nil + } + return nil, nil + }, + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) + if err != nil { + return nil, err + } + + if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + return nil, nil + } + + if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + return binaryDataEntry, nil + } + return nil, nil + }, + NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { + if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { + if *cost == 0 { + return false, nil + } + return true, nil + } + return false, nil + }, + NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + assetFromStore := proto.AssetInfo{} + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + return &proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + }, nil + + }, + NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + + if searchNewAsset == nil { + + assetFromStore := proto.FullAssetInfo{} + + if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + + if quantity >= 0 { + assetFromStore.Quantity = uint64(quantity) + return &assetFromStore, nil + } + + return nil, errors.Errorf("quantity of the asset is negative") + } + + return &assetFromStore, nil + } + + issuerPK := crypto.PublicKey{} + + scripted := false + if searchNewAsset.script != nil { + scripted = true + } + + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: uint64(searchNewAsset.quantity), + Decimals: uint8(searchNewAsset.decimals), + Issuer: searchNewAsset.dAppIssuer, + IssuerPublicKey: issuerPK, + Reissuable: searchNewAsset.reissuable, + Scripted: scripted, + Sponsored: false, + } + scriptInfo := proto.ScriptInfo{ + Bytes: searchNewAsset.script, + } + + sponsorshipCost := int64(0) + if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + sponsorshipCost = *sponsorship + } + + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: searchNewAsset.name, + Description: searchNewAsset.description, + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(sponsorshipCost), + }, nil + }, + } +} + +var envActions []proto.ScriptAction +var invCount uint64 +var thisAddress proto.Address +var tx *proto.InvokeScriptWithProofs +var id []byte + +var envDappFromDapp = &MockRideEnvironment{ + actionsFunc: func() []proto.ScriptAction { + return envActions + }, + appendActionsFunc: func(actions []proto.ScriptAction) { + envActions = append(envActions, actions...) + }, + SetInvocationFunc: func(inv rideObject) { + }, + smartAppendActionsFunc: func(actions []proto.ScriptAction) error { + modifiedActions, err := smartStateDappFromDapp().ApplyToState(actions) + if err != nil { + return nil + } + envActions = append(envActions, modifiedActions...) + return nil + }, + schemeFunc: func() byte { + return proto.MainNetScheme + }, + stateFunc: smartStateDappFromDapp, + + txIDFunc: func() rideType { + return rideBytes(id) + }, + thisFunc: func() rideType { + return rideAddress(thisAddress) + }, + setNewDAppAddressFunc: func(address proto.Address) { + wrappedSt.envThis = rideAddress(address) + thisAddress = address + }, + applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { + modifiedActions, err := smartStateDappFromDapp().ApplyToState(envActions) + if err != nil { + return nil, err + } + return modifiedActions, nil + }, + transactionFunc: func() rideObject { + obj, _ := transactionToObject(proto.MainNetScheme, tx) + return obj + }, + invocationFunc: func() rideObject { + obj, _ := invocationToObject(4, proto.MainNetScheme, tx) + return obj + }, + invCountFunc: func() uint64 { + return invCount + }, + incrementInvCountFunc: func() { + invCount++ + }, +} + +func tearDownDappFromDapp() { + + wrappedSt = wrappedState{} + firstScript = "" + secondScript = "" + assetIDIssue = crypto.Digest{} + addr = proto.Address{} + addressCallable = proto.Address{} + addrPK = crypto.PublicKey{} + addressCallablePK = crypto.PublicKey{} + + envActions = nil + invCount = 0 + thisAddress = proto.Address{} + tx = nil + id = nil +} + func TestInvokeDAppFromDAppAllActions(t *testing.T) { /* script 1 @@ -856,7 +1377,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { let assetId = asset.calculateAssetId() ([ - ScriptTransfer(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), 1, unit), + ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 1, unit), BinaryEntry("bin", base58''), BooleanEntry("bool", true), IntegerEntry("int", 1), @@ -868,7 +1389,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { ], 17) } */ - var assetIDIssue crypto.Digest + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") @@ -877,9 +1398,19 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) + + addressCallable, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) @@ -888,7 +1419,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ + tx = &proto.InvokeScriptWithProofs{ Type: proto.InvokeScriptTransaction, Version: 1, ID: &txID, @@ -903,495 +1434,125 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { Timestamp: 1564703444249, } - firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" - secondScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVyOzrRJck6TK7Dn+T0bWzVZNLfsQ+2OYegAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAANzdHICAAAAAAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABAgAAAANzdHIJAARMAAAAAgUAAAAFYXNzZXQJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAdhc3NldElkAAAAAAAAAAAKBwkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAAB2Fzc2V0SWQAAAAAAAAAAAUFAAAAA25pbAAAAAAAAAAAEQAAAACaHEHX" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" + secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAANzdHICAAAAAAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABAgAAAANzdHIJAARMAAAAAgUAAAAFYXNzZXQJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAdhc3NldElkAAAAAAAAAAAKBwkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAAB2Fzc2V0SWQAAAAAAAAAAAUFAAAAA25pbAAAAAAAAAAAEQAAAAD8KQzH" - id := bytes.Repeat([]byte{0}, 32) + id = bytes.Repeat([]byte{0}, 32) - assetExp := proto.OptionalAsset{ID: crypto.Digest{}, Present: false} + expectedIssueWrites := []*proto.IssueScriptAction{ + {Sender: addressCallablePK, Name: "CatCoin", Description: "", Quantity: 1, Decimals: 0, Reissuable: true, Script: nil, Nonce: 0}, + } + expectedReissueWrites := []*proto.ReissueScriptAction{ + {Sender: addressCallablePK, Quantity: 10, Reissuable: false}, + } + expectedBurnWrites := []*proto.BurnScriptAction{ + {Sender: addressCallablePK, Quantity: 5}, + } expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.BinaryDataEntry{Key: "bin", Value: []byte("")}, Sender: addressCallablePK}, + {Entry: &proto.BooleanDataEntry{Key: "bool", Value: true}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.StringDataEntry{Key: "str", Value: ""}, Sender: addressCallablePK}, + {Entry: &proto.DeleteDataEntry{Key: "str"}, Sender: addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + } - case *proto.DataEntryScriptAction: + smartState := smartStateDappFromDapp - switch dataEntry := res.Entry.(type) { + invCount = 0 + thisAddress = addr + env := envDappFromDapp - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + wrappedSt = *NewWrappedSt - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) + pid, ok := env.txID().(rideBytes) + require.True(t, ok) + d, err := crypto.NewDigestFromBytes(pid) + require.NoError(t, err) + expectedIssueWrites[0].ID = proto.GenerateIssueScriptActionID(expectedIssueWrites[0].Name, expectedIssueWrites[0].Description, int64(expectedIssueWrites[0].Decimals), expectedIssueWrites[0].Quantity, expectedIssueWrites[0].Reissuable, expectedIssueWrites[0].Nonce, d) + expectedReissueWrites[0].AssetID = expectedIssueWrites[0].ID + expectedBurnWrites[0].AssetID = expectedIssueWrites[0].ID - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + res, err := CallFunction(env, tree, "test", proto.Arguments{}) - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) + assetExp := proto.OptionalAsset{} - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: expectedIssueWrites, + Reissues: expectedReissueWrites, + Burns: expectedBurnWrites, + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } - } + assert.Equal(t, expectedActionsResult, sr) - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + balance := diffBalance{amount: -2467, assetID: assetExp.ID} + expectedDiffResult.balances[addr.String()+assetExp.ID.String()] = balance - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } + balanceCallable := diffBalance{amount: 2467, assetID: assetExp.ID} + expectedDiffResult.balances[addressCallable.String()+assetExp.ID.String()] = balanceCallable - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } + intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry1 - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee + boolEntry := proto.BooleanDataEntry{Key: "bool", Value: true} + expectedDiffResult.dataEntries.diffBool["bool"+addressCallable.String()] = boolEntry - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + stringEntry := proto.StringDataEntry{Key: "str", Value: ""} + expectedDiffResult.dataEntries.diffString["str"+addressCallable.String()] = stringEntry - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce + binaryEntry := proto.BinaryDataEntry{Key: "bin", Value: []byte("")} + expectedDiffResult.dataEntries.diffBinary["bin"+addressCallable.String()] = binaryEntry - assetIDIssue = res.ID + deleteEntry := proto.DeleteDataEntry{Key: "str"} + expectedDiffResult.dataEntries.diffDDelete["str"+addressCallable.String()] = deleteEntry - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + newAsset := diffNewAssetInfo{dAppIssuer: addressCallable, name: "CatCoin", description: "", quantity: 6, decimals: 0, reissuable: false, script: nil, nonce: 0} + expectedDiffResult.newAssetsInfo[assetIDIssue.String()] = newAsset - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo + assert.Equal(t, expectedDiffResult.newAssetsInfo, wrappedSt.diff.newAssetsInfo) + assert.Equal(t, expectedDiffResult.oldAssetsInfo, wrappedSt.diff.oldAssetsInfo) + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + assert.Equal(t, expectedDiffResult.sponsorships, wrappedSt.diff.sponsorships) - assetInfo.diffQuantity += res.Quantity + tearDownDappFromDapp() +} - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) +func TestInvokeDAppFromDAppScript1(t *testing.T) { - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - if recipient.Address.String() == address.String() { - script, err = base64.StdEncoding.DecodeString(secondScript) - require.NoError(t, err) - return script, nil - } - - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return &address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } - } - - var envActions []proto.ScriptAction - var invCount uint64 - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - SetInvocationFunc: func(inv rideObject) { - }, - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) - - return smartState().ApplyToState(envActions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, - - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(address) - }, - setNewDAppAddressFunc: func(address proto.Address) { - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - } - - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) - wrappedSt = *NewWrappedSt - - src, err := base64.StdEncoding.DecodeString(firstScript) - require.NoError(t, err) - - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) - - res, err := CallFunction(env, tree, "test", proto.Arguments{}) - - require.NoError(t, err) - r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: make([]*proto.TransferScriptAction, 0), - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - } - assert.Equal(t, expectedActionsResult, sr) - - // new test - - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff - balance := diffBalance{amount: 0, assetID: assetExp.ID} - expectedDiffResult.balances[address.String()+assetExp.ID.String()] = balance - - intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} - expectedDiffResult.dataEntries.diffInteger["int"+address.String()] = intEntry1 - - boolEntry := proto.BooleanDataEntry{Key: "bool", Value: true} - expectedDiffResult.dataEntries.diffBool["bool"+address.String()] = boolEntry - - stringEntry := proto.StringDataEntry{Key: "str", Value: ""} - expectedDiffResult.dataEntries.diffString["str"+address.String()] = stringEntry - - binaryEntry := proto.BinaryDataEntry{Key: "bin", Value: []byte("")} - expectedDiffResult.dataEntries.diffBinary["bin"+address.String()] = binaryEntry - - deleteEntry := proto.DeleteDataEntry{Key: "str"} - expectedDiffResult.dataEntries.diffDDelete["str"+address.String()] = deleteEntry - - newAsset := diffNewAssetInfo{dAppIssuer: address, name: "CatCoin", description: "", quantity: 6, decimals: 0, reissuable: false, script: nil, nonce: 0} - expectedDiffResult.newAssetsInfo[assetIDIssue.String()] = newAsset - - assert.Equal(t, expectedDiffResult.newAssetsInfo, wrappedSt.diff.newAssetsInfo) - assert.Equal(t, expectedDiffResult.oldAssetsInfo, wrappedSt.diff.oldAssetsInfo) - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) - assert.Equal(t, expectedDiffResult.sponsorships, wrappedSt.diff.sponsorships) - -} - -func TestInvokeDAppFromDAppScript1(t *testing.T) { - - /* script 1 - {-# STDLIB_VERSION 5#-} - {-# CONTENT_TYPE DAPP #-} - {-#SCRIPT_TYPE ACCOUNT#-} + /* script 1 + {-# STDLIB_VERSION 5#-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} @Callable(i) func bar() = { @@ -1423,9 +1584,13 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) call := proto.FunctionCall{ @@ -1433,985 +1598,39 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ - Type: proto.InvokeScriptTransaction, - Version: 1, - ID: &txID, - Proofs: proofs, - ChainID: proto.MainNetScheme, - SenderPK: sender, - ScriptRecipient: recipient, - FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, - } - - firstScript := "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAANiYXIAAAAACQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQUAAAADbmlsAgAAAAZyZXR1cm4AAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANiYXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyAgAAAAZyZXR1cm4EAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIFAAAABHRoaXMCAAAAA2JhcgMJAAAAAAAAAgUAAAAEZGF0YQAAAAAAAAAAAQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAADz23Fz" - - id := bytes.Repeat([]byte{0}, 32) - - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, - } - - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - if recipient.Address.String() == address.String() { - script, err = base64.StdEncoding.DecodeString(firstScript) - require.NoError(t, err) - return script, nil - } - - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return &address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } - } - - var envActions []proto.ScriptAction - - var invCount uint64 - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - SetInvocationFunc: func(inv rideObject) { - }, - - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) - - return smartState().ApplyToState(envActions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, - - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(address) - }, - setNewDAppAddressFunc: func(address proto.Address) { - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - } - - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) - wrappedSt = *NewWrappedSt - - src, err := base64.StdEncoding.DecodeString(firstScript) - require.NoError(t, err) - - tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) - - res, err := CallFunction(env, tree, "foo", proto.Arguments{}) - - require.NoError(t, err) - r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: make([]*proto.TransferScriptAction, 0), - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - } - assert.Equal(t, expectedActionsResult, sr) - - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff - - intEntry1 := proto.IntegerDataEntry{Key: "bar", Value: 1} - expectedDiffResult.dataEntries.diffInteger["bar"+address.String()] = intEntry1 - - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - -} - -func TestInvokeDAppFromDAppScript2(t *testing.T) { - - /* script 1 - {-# STDLIB_VERSION 5 #-} - {-# CONTENT_TYPE DAPP #-} - {-#SCRIPT_TYPE ACCOUNT#-} - - @Callable(i) - func foo() = { - let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) - if b1 == b1 && ob1 == ob1 - then - let r = Invoke(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) - if r == 17 - then - let data = getIntegerValue(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar") - let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) - if data == 1 - then - if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 - then - [ - IntegerEntry("key", 1) - ] - else - throw("Balance check failed") - else - throw("Bad state") - else - throw("Bad returned value") - else - throw("Imposible") - } - */ - - /* - script2 - - {-# STDLIB_VERSION 5 #-} - {-# CONTENT_TYPE DAPP #-} - {-#SCRIPT_TYPE ACCOUNT#-} - - @Callable(i) - func bar(a: ByteVector) = { - ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) - } - */ - txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") - require.NoError(t, err) - proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") - require.NoError(t, err) - proofs := proto.NewProofs() - proofs.Proofs = []proto.B58Bytes{proof[:]} - sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") - require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") - require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) - arguments := proto.Arguments{} - arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - - addressCallable, err := proto.NewAddressFromString("3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW") - require.NoError(t, err) - - call := proto.FunctionCall{ - Default: false, - Name: "cancel", - Arguments: arguments, - } - tx := &proto.InvokeScriptWithProofs{ - Type: proto.InvokeScriptTransaction, - Version: 1, - ID: &txID, - Proofs: proofs, - ChainID: proto.MainNetScheme, - SenderPK: sender, - ScriptRecipient: recipient, - FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, - } - - firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAALVWK3g==" - secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" - - id := bytes.Repeat([]byte{0}, 32) - - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, - } - - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - script, err = base64.StdEncoding.DecodeString(secondScript) - require.NoError(t, err) - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return recipient.Address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } - } - - var envActions []proto.ScriptAction - isNewDapp := false - - var invCount uint64 - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - SetInvocationFunc: func(inv rideObject) { - }, - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) - - return smartState().ApplyToState(actions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, - - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - if isNewDapp { - return rideAddress(addressCallable) - } - return rideAddress(address) - }, - setNewDAppAddressFunc: func(address proto.Address) { - wrappedSt.envThis = rideAddress(address) - isNewDapp = true - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAANiYXIAAAAACQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQUAAAADbmlsAgAAAAZyZXR1cm4AAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANiYXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyAgAAAAZyZXR1cm4EAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIFAAAABHRoaXMCAAAAA2JhcgMJAAAAAAAAAgUAAAAEZGF0YQAAAAAAAAAAAQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAADz23Fz" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addrPK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + smartState := smartStateDappFromDapp + + envActions = nil + + invCount = 0 + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -2443,20 +1662,17 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -14} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 14} - intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} - expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain - expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + intEntry1 := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addr.String()] = intEntry1 assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } -func TestInvokeDAppFromDAppScript3(t *testing.T) { +func TestInvokeDAppFromDAppScript2(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} @@ -2466,43 +1682,31 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob1 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") + let data = getIntegerValue(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob2 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) if data == 1 then if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 then - let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) - if r1 == r1 - then - let b3 = wavesBalance(this) - let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) - if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 - then - [ - IntegerEntry("key", 1) - ] - else - throw("Bad balance after second invoke") + [ + IntegerEntry("key", 1) + ] else - throw("Imposible") - else - throw("Balance check failed") + throw("Balance check failed") else throw("Bad state") - else - throw("Bad returned value") else - throw("Imposible") + throw("Bad returned value") + else + throw("Imposible") } - */ /* @@ -2514,7 +1718,7 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { @Callable(i) func bar(a: ByteVector) = { - ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) } */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") @@ -2525,21 +1729,29 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err := proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + addressCallable, err = proto.NewAddressFromString("3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW") require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + call := proto.FunctionCall{ Default: false, Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ + tx = &proto.InvokeScriptWithProofs{ Type: proto.InvokeScriptTransaction, Version: 1, ID: &txID, @@ -2554,423 +1766,31 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { Timestamp: 1564703444249, } - firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" - secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAALVWK3g==" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" - id := bytes.Repeat([]byte{0}, 32) + id = bytes.Repeat([]byte{0}, 32) - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - script, err = base64.StdEncoding.DecodeString(secondScript) - require.NoError(t, err) - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return recipient.Address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - var envActions []proto.ScriptAction - thisAddr := address - - var invCount uint64 - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - SetInvocationFunc: func(inv rideObject) { - }, - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) + smartState := smartStateDappFromDapp - return smartState().ApplyToState(actions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, + envActions = nil + invCount = 0 + thisAddress = addr - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(thisAddr) - }, - setNewDAppAddressFunc: func(address proto.Address) { - wrappedSt.envThis = rideAddress(address) - thisAddr = address - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - } + env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -2992,7 +1812,7 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { expectedActionsResult := &proto.ScriptResult{ DataEntries: expectedDataEntryWrites, - Transfers: make([]*proto.TransferScriptAction, 0), + Transfers: expectedTransferWrites, Issues: make([]*proto.IssueScriptAction, 0), Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), @@ -3002,78 +1822,80 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -14} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 14} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } -func TestInvokeDAppFromDAppScript4(t *testing.T) { +func TestInvokeDAppFromDAppScript3(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} {-# CONTENT_TYPE DAPP #-} {-#SCRIPT_TYPE ACCOUNT#-} - @Callable(i) - func back() = { - [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 2, unit)] - } - @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar") - let tdata = getIntegerValue(this, "key") + let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) - if data == 1 && tdata == 0 + let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if data == 1 then - if ob1.regular+16 == ob2.regular && b1.regular == b2.regular+16 + if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 then - [ - IntegerEntry("key", 1) - ] + let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) + if r1 == r1 + then + let b3 = wavesBalance(this) + let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Bad balance after second invoke") else - throw("Balance check failed") + throw("Imposible") + else + throw("Balance check failed") else throw("Bad state") - else - throw("Bad returned value") else - throw("Imposible") + throw("Bad returned value") + else + throw("Imposible") } + */ /* - script2 + script2 + {-# STDLIB_VERSION 5 #-} {-# CONTENT_TYPE DAPP #-} {-#SCRIPT_TYPE ACCOUNT#-} - @Callable(i) - func bar(a: ByteVector) = { - let r = Invoke(Address(a), "back", [], []) - if r == r - then + @Callable(i) + func bar(a: ByteVector) = { ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) - else - throw("Imposible") - } - + } */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) @@ -3083,13 +1905,19 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err := proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + addressCallable, err = proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) call := proto.FunctionCall{ @@ -3097,7 +1925,7 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ + tx = &proto.InvokeScriptWithProofs{ Type: proto.InvokeScriptTransaction, Version: 1, ID: &txID, @@ -3112,428 +1940,33 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { Timestamp: 1564703444249, } - firstScript := "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAACP+w2w=" - secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" - id := bytes.Repeat([]byte{0}, 32) + id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - if recipient.Address.String() == address.String() { - script, err = base64.StdEncoding.DecodeString(firstScript) - } - if recipient.Address.String() == addressCallable.String() { - script, err = base64.StdEncoding.DecodeString(secondScript) - } - - require.NoError(t, err) - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return recipient.Address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addrPK, Recipient: recipientCallable, Amount: 18, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } - var envActions []proto.ScriptAction - thisAddress := address - var invCount uint64 - - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, + smartState := smartStateDappFromDapp - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - SetInvocationFunc: func(inv rideObject) { - }, - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) + envActions = nil + thisAddress = addr + invCount = 0 - return smartState().ApplyToState(actions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(thisAddress) - }, - setNewDAppAddressFunc: func(address proto.Address) { - wrappedSt.envThis = rideAddress(address) - thisAddress = address - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - } + env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -3555,7 +1988,7 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { expectedActionsResult := &proto.ScriptResult{ DataEntries: expectedDataEntryWrites, - Transfers: make([]*proto.TransferScriptAction, 0), + Transfers: expectedTransferWrites, Issues: make([]*proto.IssueScriptAction, 0), Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), @@ -3565,81 +1998,79 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -16} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 16} - intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} - intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} - expectedDiffResult.dataEntries.diffInteger["key"+address.String()] = intEntry1 - expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 - expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry + expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } -func TestInvokeDAppFromDAppScript5(t *testing.T) { +func TestInvokeDAppFromDAppScript4(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} {-# CONTENT_TYPE DAPP #-} {-#SCRIPT_TYPE ACCOUNT#-} + @Callable(i) + func back() = { + [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 2, unit)] + } + @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob1 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") + let data = getIntegerValue(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar") + let tdata = getIntegerValue(this, "key") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) - if data == 1 + let ob2 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + if data == 1 && tdata == 0 then - if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 + if ob1.regular+16 == ob2.regular && b1.regular == b2.regular+16 then - let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) - if r1 == r1 - then - let b3 = wavesBalance(this) - let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) - if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 - then - [ - IntegerEntry("key", 1) - ] - else - throw("Bad balance after second invoke") + [ + IntegerEntry("key", 1) + ] else - throw("Imposible") - else - throw("Balance check failed") + throw("Balance check failed") else throw("Bad state") - else - throw("Bad returned value") else - throw("Imposible") + throw("Bad returned value") + else + throw("Imposible") } - */ /* - script2 - + script2 {-# STDLIB_VERSION 5 #-} {-# CONTENT_TYPE DAPP #-} {-#SCRIPT_TYPE ACCOUNT#-} @Callable(i) func bar(a: ByteVector) = { - ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + let r = Invoke(Address(a), "back", [], []) + if r == r + then + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + else + throw("Imposible") } + */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) @@ -3649,22 +2080,27 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err := proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + addressCallable, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) - //recipientCallable := proto.NewRecipientFromAddress(address) call := proto.FunctionCall{ Default: false, Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ + tx = &proto.InvokeScriptWithProofs{ Type: proto.InvokeScriptTransaction, Version: 1, ID: &txID, @@ -3679,429 +2115,206 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { Timestamp: 1564703444249, } - firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" - secondScript := "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAACP+w2w=" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" - id := bytes.Repeat([]byte{0}, 32) + id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: addrPK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - if recipient.Address.String() == address.String() { - script, err = base64.StdEncoding.DecodeString(firstScript) - } - if recipient.Address.String() == addressCallable.String() { - script, err = base64.StdEncoding.DecodeString(secondScript) - } - - require.NoError(t, err) - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return recipient.Address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } + smartState := smartStateDappFromDapp - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } + envActions = nil + thisAddress = addr + invCount = 0 - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } + env := envDappFromDapp - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + wrappedSt = *NewWrappedSt - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) - return &assetFromStore, nil - } + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) - issuerPK := crypto.PublicKey{} + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - scripted := false - if searchNewAsset.script != nil { - scripted = true - } + balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -16} + balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 16} + intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} + intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 + expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil + tearDownDappFromDapp() +} - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) +func TestInvokeDAppFromDAppScript5(t *testing.T) { - if searchNewAsset == nil { + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } + @Callable(i) + func back() = { + [ScriptTransfer(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), 2, unit)] + } - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc')) + if b1 == b1 && ob1 == ob1 + then + let r = Invoke(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), "bar") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc')) + if data == 1 + then + if ob1.regular+13 == ob2.regular && b1.regular == b2.regular+13 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + } + */ - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } + /* + script2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} - return nil, errors.Errorf("quantity of the asset is negative") - } + @Callable(i) + func bar(a: ByteVector) = { + let r = Invoke(Address(a), "back", [], [AttachedPayment(unit, 3)]) + if r == r + then + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + else + throw("Imposible") + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - return &assetFromStore, nil - } + addressCallable, err = proto.NewAddressFromString("3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) - issuerPK := crypto.PublicKey{} + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) - scripted := false - if searchNewAsset.script != nil { - scripted = true - } + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFU+nlLLlJlc8+xTjSzsqlWzv76DyZcRlcJAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAADKkWnw==" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAADBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACzZnMp" - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } + id = bytes.Repeat([]byte{0}, 32) - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } - var envActions []proto.ScriptAction - thisAddress := address - - var invCount uint64 - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + } - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, - SetInvocationFunc: func(inv rideObject) { - }, - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) + smartState := smartStateDappFromDapp - return smartState().ApplyToState(actions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, + envActions = nil + thisAddress = addr - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(thisAddress) - }, - setNewDAppAddressFunc: func(address proto.Address) { - wrappedSt.envThis = rideAddress(address) - thisAddress = address - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - } + invCount = 0 + env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -4123,7 +2336,7 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { expectedActionsResult := &proto.ScriptResult{ DataEntries: expectedDataEntryWrites, - Transfers: make([]*proto.TransferScriptAction, 0), + Transfers: expectedTransferWrites, Issues: make([]*proto.IssueScriptAction, 0), Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), @@ -4133,17 +2346,18 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[address.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } func TestInvokeDAppFromDAppScript6(t *testing.T) { @@ -4173,9 +2387,10 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - address, err := proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(address) + recipient := proto.NewRecipientFromAddress(addr) + arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) call := proto.FunctionCall{ @@ -4183,7 +2398,7 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { Name: "cancel", Arguments: arguments, } - tx := &proto.InvokeScriptWithProofs{ + tx = &proto.InvokeScriptWithProofs{ Type: proto.InvokeScriptTransaction, Version: 1, ID: &txID, @@ -4198,419 +2413,19 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { Timestamp: 1564703444249, } - firstScript := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" - - id := bytes.Repeat([]byte{0}, 32) - - var wrappedSt wrappedState - - smartState := func() types.SmartState { - return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) error { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - case *proto.StringDataEntry: - stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - default: - - } - - case *proto.TransferScriptAction: - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) - if err != nil { - return err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return err - } - - senderAddr := proto.Address(wrappedSt.envThis) - senderRecip := proto.Recipient{Address: &senderAddr} - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecip, res.Asset.ID.Bytes()) - if err != nil { - return err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecip) - if err != nil { - return err - } - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - default: - } - - } - return nil - }, - GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { - var script proto.Script - var err error - if recipient.Address.String() == address.String() { - script, err = base64.StdEncoding.DecodeString(firstScript) - require.NoError(t, err) - return script, nil - } - - return script, nil - }, - NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { - return &address, nil - }, - AddingBlockHeightFunc: func() (uint64, error) { - return 10, nil - }, - NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return crypto.PublicKey{}, nil - }, - NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { - return nil, nil - }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { - balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount - return uint64(resBalance), nil - - } - return uint64(balance), nil - }, - NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil - - } - return &proto.FullWavesBalance{ - Regular: 0, - Generating: 0, - Available: 0, - Effective: 0, - LeaseIn: 0, - LeaseOut: 0}, nil - }, - RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - - return nil, nil - }, - RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } - return nil, nil - }, - RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } - return nil, nil - }, - RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } - return nil, nil - }, - NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } - return false, nil - }, - NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - if err != nil { - return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") - } - - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - - }, - NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - if err != nil { - return nil, errors.Wrap(err, "failed to get asset's info from store") - } - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true - } - - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } - - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship - } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil - }, - } - } - - var envActions []proto.ScriptAction - var invCount uint64 + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" - env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - SetInvocationFunc: func(inv rideObject) { - }, - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, + id = bytes.Repeat([]byte{0}, 32) - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - envActions = append(envActions, actions...) + smartState := smartStateDappFromDapp - return smartState().ApplyToState(envActions) - }, - schemeFunc: func() byte { - return proto.MainNetScheme - }, - stateFunc: smartState, + envActions = nil + thisAddress = addr + invCount = 0 - txIDFunc: func() rideType { - return rideBytes(id) - }, - thisFunc: func() rideType { - return rideAddress(address) - }, - setNewDAppAddressFunc: func(address proto.Address) { - }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return smartState().ApplyToState(actions) - }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ - }, - transactionFunc: func() rideObject { - obj, err := transactionToObject(proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - invocationFunc: func() rideObject { - obj, err := invocationToObject(4, proto.MainNetScheme, tx) - require.NoError(t, err) - return obj - }, - } + env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(address)) + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -4642,10 +2457,11 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(address)).diff + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } func TestMatchOverwrite(t *testing.T) { @@ -4687,8 +2503,8 @@ func TestMatchOverwrite(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - applyToStateFunc: func(actions []proto.ScriptAction) error { - return nil + applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { + return nil, nil }, heightFunc: func() rideInt { return 368430 diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index 297afa4d8..7a17c902d 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -244,8 +244,10 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { } newActions = append(newActions, a) } + act := e.env.actions() + act = append(act, newActions...) - return DAppResult{res: true, actions: newActions}, nil + return DAppResult{res: true, actions: act}, nil case tuple2: var act []proto.ScriptAction switch resAct := res.el1.(type) { diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index 086309e11..4e5279c24 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -23,7 +23,7 @@ var _ types.SmartState = &MockSmartState{} // AddingBlockHeightFunc: func() (uint64, error) { // panic("mock out the AddingBlockHeight method") // }, -// ApplyToStateFunc: func(actions []proto.ScriptAction) error { +// ApplyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { // panic("mock out the ApplyToState method") // }, // BlockVRFFunc: func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { @@ -94,7 +94,7 @@ type MockSmartState struct { AddingBlockHeightFunc func() (uint64, error) // ApplyToStateFunc mocks the ApplyToState method. - ApplyToStateFunc func(actions []proto.ScriptAction) error + ApplyToStateFunc func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) // BlockVRFFunc mocks the BlockVRF method. BlockVRFFunc func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) @@ -321,7 +321,7 @@ func (mock *MockSmartState) AddingBlockHeightCalls() []struct { } // ApplyToState calls ApplyToStateFunc. -func (mock *MockSmartState) ApplyToState(actions []proto.ScriptAction) error { +func (mock *MockSmartState) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { if mock.ApplyToStateFunc == nil { panic("MockSmartState.ApplyToStateFunc: method is nil but SmartState.ApplyToState was just called") } diff --git a/pkg/state/state.go b/pkg/state/state.go index a4ce0e007..2e537b6a6 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -468,8 +468,8 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc return state, nil } -func (s *stateManager) ApplyToState(actions []proto.ScriptAction) error { - return nil +func (s *stateManager) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { + return nil, nil } func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, error) { diff --git a/pkg/types/types.go b/pkg/types/types.go index 1bbb3ffb4..678cb8c05 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -58,7 +58,7 @@ type SmartState interface { NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) - ApplyToState(actions []proto.ScriptAction) error + ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) EstimatorVersion() (int, error) IsNotFound(err error) bool } From 49c31d446a81af94bfddd2bc76dd93bae9f9f6b1 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 19 Jan 2021 11:02:03 +0300 Subject: [PATCH 05/52] Support for RIDE V5 added to transaction_checker (#410) --- pkg/ride/tree_estimation_test.go | 1 + pkg/state/script_caller.go | 2 +- pkg/state/transaction_checker.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/ride/tree_estimation_test.go b/pkg/ride/tree_estimation_test.go index 017703969..2a92a2f13 100644 --- a/pkg/ride/tree_estimation_test.go +++ b/pkg/ride/tree_estimation_test.go @@ -159,6 +159,7 @@ func TestEstimatorCommon(t *testing.T) { {`V4: 922-833`, "AAIEAAAAAAAAAAgIAhIAEgASAAAAABoAAAAADXNjcmlwdFZlcnNpb24CAAAADnYzLjA3XzIwMjAwOTEzAAAAAAdwZXJjZW50AAAAAAAAAABkAAAAAAtyaXNrUGVyY2VudAAAAAAAAAAAFAAAAAALdGVhbVBlcmNlbnQAAAAAAAAAAAoAAAAADmFkbWluUHVibGljS2V5AQAAACD/zQv9xtp+IwicmSq/7YB3qzF8dYREKcB8rX1b2hNXAwAAAAAOZnRlYW1QdWJsaWNLZXkBAAAAIIN6TMTYLvwQfnpKcKqqAAZ8882v9yZAFQ900E5yClNCAAAAAA5tbWJvdFB1YmxpY0tleQEAAAAgSqCTD7MZSfeiXlZ7r112NWe+YGAAI7co5SLZqPgB7C8AAAAACWVtcHR5TGlzdAkABEwAAAACAQAAAAAJAARMAAAAAgEAAAAACQAETAAAAAIBAAAAAAkABEwAAAACAQAAAAAJAARMAAAAAgEAAAAACQAETAAAAAIBAAAAAAkABEwAAAACAQAAAAAFAAAAA25pbAAAAAATZ3VhcmFudG9yUHVibGljS2V5cwkABE4AAAACCQAETAAAAAIBAAAAIP/NC/3G2n4jCJyZKr/tgHerMXx1hEQpwHytfVvaE1cDBQAAAANuaWwFAAAACWVtcHR5TGlzdAAAAAANZ3VhcmFudG9yU2l6ZQkAAGUAAAACCQABkAAAAAEFAAAAE2d1YXJhbnRvclB1YmxpY0tleXMJAAGQAAAAAQUAAAAJZW1wdHlMaXN0AAAAAA1taW5TaWduYXR1cmVzCQAAZAAAAAIJAABpAAAAAgUAAAANZ3VhcmFudG9yU2l6ZQAAAAAAAAAAAgkAAGoAAAACBQAAAA1ndWFyYW50b3JTaXplAAAAAAAAAAACAAAAAAlmbW10QXNzZXQBAAAAIGYr8dw8TDanuTqo+vs1Q9xNuAeFp1N2ZT91Xozrfzj0AAAAAAl4ZmVlQXNzZXQBAAAAID7aqaNufgAR8AeMAT3F3i6NRzE7nRhBON4sOuYerrY3AAAAAAlwb3J0Zm9saW8JAARNAAAAAgkABE0AAAACCQAETAAAAAIBAAAAIB6UBxNSdqEllf3IYaiCXxB/3zpPKbv8mkY/Wv02T5+RCQAETAAAAAIBAAAAIGz6av/F7aqMC3+1KpPSogwvgoLbdHoEjFP7/RMfc6D/CQAETAAAAAIFAAAABHVuaXQJAARMAAAAAgEAAAAgLiDD9uqKn4lRu7/oiBETNux+2MJCA3JlDVjNcyZCZYIJAARMAAAAAgEAAAAgDrECagw+n0f35EaU5062t7xDfH5ladDpGJsi5gny6M4JAARMAAAAAgEAAAAg9h42QtOX3fJaWBUg7iwP2i1GBoqANpKuVYlZnrDFLKEJAARMAAAAAgEAAAAglVMgFzLH9/gxbVKojbVZ08/r8nPtlHFX5Z0m586HauAJAARMAAAAAgEAAAAgQxj0G3VSMI+7+iJkvwQoTrekocmcbhiCndEGv8vAJAIJAARMAAAAAgEAAAAgoVJa1UnWcbrDrx+GyZJ/6g+KWhwfmKQrcwaOzJr+1WcFAAAAA25pbAUAAAAJeGZlZUFzc2V0BQAAAAlmbW10QXNzZXQAAAAABWFkbWluCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXyvBTGJ3PniBi4dPVWqjby+gPf9AH2sQ1AAAAAAVmdGVhbQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVxC7GUc6JOl3erhvhB+nL92RfEkunZJulwAAAAAFZmRhcHAJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVeUGM4qgYZsQxeQti8+oFzAKUNnZKGyBg0AAAAACmhlZGdlRnVuZHMJAABlAAAAAggJAQAAAAV2YWx1ZQAAAAEJAAPsAAAAAQUAAAAJZm1tdEFzc2V0AAAACHF1YW50aXR5CQAAZAAAAAIJAABkAAAAAgkAA/AAAAACBQAAAAR0aGlzBQAAAAlmbW10QXNzZXQJAAPwAAAAAgUAAAAFZnRlYW0FAAAACWZtbXRBc3NldAkAA/AAAAACBQAAAAVmZGFwcAUAAAAJZm1tdEFzc2V0AAAAABJ0ZWFtUGF5b3V0c0RhdGFLZXkCAAAAC3RlYW1QYXlvdXRzAAAAABRzY3JpcHRWZXJzaW9uRGF0YUtleQIAAAANc2NyaXB0VmVyc2lvbgAAAAAQdGltZXN0YW1wRGF0YUtleQIAAAAJdGltZXN0YW1wAAAAABFsYXN0QWN0aW9uRGF0YUtleQIAAAAKbGFzdEFjdGlvbgAAAAALZGFwcERhdGFLZXkJAAJYAAAAAQgFAAAABHRoaXMAAAAFYnl0ZXMAAAAAE2lzQ29udHJhY3RTdXNwZW5kZWQJAQAAAAEhAAAAAQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAAVhZG1pbgUAAAALZGFwcERhdGFLZXkHAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEAAAAFYXNzZXQKAQAAAA9pc0Fzc2V0RGlzYWJsZWQAAAABAAAADGFzc2V0RGF0YUtleQkBAAAAASEAAAABCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAABWFkbWluBQAAAAxhc3NldERhdGFLZXkHCgEAAAAKZGlmZmVyZW5jZQAAAAIAAAAMZmNvbGRCYWxhbmNlAAAADGZkYXBwQmFsYW5jZQkAAGUAAAACCQAAawAAAAMJAABkAAAAAgUAAAAMZmNvbGRCYWxhbmNlBQAAAAxmZGFwcEJhbGFuY2UFAAAAC3Jpc2tQZXJjZW50BQAAAAdwZXJjZW50BQAAAAxmZGFwcEJhbGFuY2UEAAAABmFtb3VudAQAAAAHJG1hdGNoMAUAAAAFYXNzZXQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAACkJ5dGVWZWN0b3IEAAAAAmlkBQAAAAckbWF0Y2gwAwkBAAAAD2lzQXNzZXREaXNhYmxlZAAAAAEJAAJYAAAAAQUAAAACaWQAAAAAAAAAAAAJAQAAAApkaWZmZXJlbmNlAAAAAgkAA/AAAAACBQAAAAR0aGlzBQAAAAJpZAkAA/AAAAACBQAAAAVmZGFwcAUAAAACaWQDCQEAAAAPaXNBc3NldERpc2FibGVkAAAAAQIAAAAFV0FWRVMAAAAAAAAAAAAJAQAAAApkaWZmZXJlbmNlAAAAAggJAAPvAAAAAQUAAAAEdGhpcwAAAAdyZWd1bGFyCAkAA+8AAAABBQAAAAVmZGFwcAAAAAdyZWd1bGFyAwkAAGYAAAACBQAAAAZhbW91bnQAAAAAAAAAAAAJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAFZmRhcHAFAAAABmFtb3VudAUAAAAFYXNzZXQFAAAAA25pbAUAAAADbmlsAQAAABBnZXRTY3JpcHRWZXJzaW9uAAAAAAQAAAAQb2xkU2NyaXB0VmVyc2lvbgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAABRzY3JpcHRWZXJzaW9uRGF0YUtleQIAAAAAAwkAAAAAAAACBQAAABBvbGRTY3JpcHRWZXJzaW9uBQAAAA1zY3JpcHRWZXJzaW9uBQAAAANuaWwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAUc2NyaXB0VmVyc2lvbkRhdGFLZXkFAAAADXNjcmlwdFZlcnNpb24FAAAAA25pbAAAAAMAAAABaQEAAAANYXV0b1JlYmFsYW5jZQAAAAAEAAAAE2xhc3RBY3Rpb25EYXRhVmFsdWUCAAAADWF1dG9SZWJhbGFuY2UDBQAAABNpc0NvbnRyYWN0U3VzcGVuZGVkCQAAAgAAAAECAAAALVRoZSBhZG1pbmlzdHJhdG9yIGhhcyBzdXNwZW5kZWQgdGhlIGNvbnRyYWN0IQMDCQEAAAACIT0AAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQEAAAACIT0AAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADm1tYm90UHVibGljS2V5BwkAAAIAAAABAgAAADFPbmx5IHRoZSBhZG1pbmlzdHJhdG9yIGNhbiBwZXJmb3JtIHRoaXMgZnVuY3Rpb24hAwkAAGYAAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAACQAAAgAAAAECAAAAMkRvbid0IGF0dGFjaCBwYXltZW50IHdoZW4gY2FsbGluZyB0aGlzIGZ1bmN0aW9uLi4uBAAAAA9zY3JpcHRUcmFuc2ZlcnMJAAROAAAAAgkABE4AAAACCQAETgAAAAIJAAROAAAAAgkABE4AAAACCQAETgAAAAIJAAROAAAAAgkABE4AAAACCQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAAAAkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAEJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAACCQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAAAwkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAQJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAAFCQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAABgkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAcJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAAIAwkAAGYAAAACCQABkAAAAAEFAAAAD3NjcmlwdFRyYW5zZmVycwAAAAAAAAAAAAkABE0AAAACCQAETQAAAAIJAAROAAAAAgUAAAAPc2NyaXB0VHJhbnNmZXJzCQEAAAAQZ2V0U2NyaXB0VmVyc2lvbgAAAAAJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEWxhc3RBY3Rpb25EYXRhS2V5BQAAABNsYXN0QWN0aW9uRGF0YVZhbHVlCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAQdGltZXN0YW1wRGF0YUtleQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAAACAAAAAQIAAAA1Tm8gdHJhbnNmZXJzIGF2YWlsYWJsZS4gV2FpdCB1bnRpbCBpbWJhbGFuY2UgYXBwZWFycy4AAAABaQEAAAAPc2VuZFRlYW1QYXlvdXRzAAAAAAQAAAATbGFzdEFjdGlvbkRhdGFWYWx1ZQIAAAAPc2VuZFRlYW1QYXlvdXRzAwUAAAATaXNDb250cmFjdFN1c3BlbmRlZAkAAAIAAAABAgAAAC1UaGUgYWRtaW5pc3RyYXRvciBoYXMgc3VzcGVuZGVkIHRoZSBjb250cmFjdCEDAwkBAAAAAiE9AAAAAggFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BQAAAA5hZG1pblB1YmxpY0tleQkBAAAAAiE9AAAAAggFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BQAAAA5mdGVhbVB1YmxpY0tleQcJAAACAAAAAQIAAAAxT25seSB0aGUgYWRtaW5pc3RyYXRvciBjYW4gcGVyZm9ybSB0aGlzIGZ1bmN0aW9uIQMJAABmAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAkAAAIAAAABAgAAADJEb24ndCBhdHRhY2ggcGF5bWVudCB3aGVuIGNhbGxpbmcgdGhpcyBmdW5jdGlvbi4uLgQAAAAOb2xkVGVhbVBheW91dHMJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwUAAAASdGVhbVBheW91dHNEYXRhS2V5AAAAAAAAAAAABAAAAAt0ZWFtUGF5b3V0cwkAAGUAAAACCQAAawAAAAMFAAAACmhlZGdlRnVuZHMFAAAAC3RlYW1QZXJjZW50BQAAAAdwZXJjZW50BQAAAA5vbGRUZWFtUGF5b3V0cwMJAABmAAAAAgUAAAALdGVhbVBheW91dHMAAAAAAAAAAAAJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAFZnRlYW0FAAAAC3RlYW1QYXlvdXRzBQAAAAlmbW10QXNzZXQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEnRlYW1QYXlvdXRzRGF0YUtleQkAAGQAAAACBQAAAA5vbGRUZWFtUGF5b3V0cwUAAAALdGVhbVBheW91dHMJAARNAAAAAgkABE0AAAACCQEAAAAQZ2V0U2NyaXB0VmVyc2lvbgAAAAAJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEWxhc3RBY3Rpb25EYXRhS2V5BQAAABNsYXN0QWN0aW9uRGF0YVZhbHVlCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAQdGltZXN0YW1wRGF0YUtleQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAAACAAAAAQIAAAA4Tm8gcGF5bWVudHMgYXZhaWxhYmxlLiBXYWl0IGZvciBuZXcgaW52ZXN0bWVudHMgdG8gY29tZS4AAAABaQEAAAAQc2V0U2NyaXB0VmVyc2lvbgAAAAAEAAAAE2xhc3RBY3Rpb25EYXRhVmFsdWUCAAAAEHNldFNjcmlwdFZlcnNpb24DBQAAABNpc0NvbnRyYWN0U3VzcGVuZGVkCQAAAgAAAAECAAAALVRoZSBhZG1pbmlzdHJhdG9yIGhhcyBzdXNwZW5kZWQgdGhlIGNvbnRyYWN0IQMJAQAAAAIhPQAAAAIIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAAACAAAAAQIAAAAxT25seSB0aGUgYWRtaW5pc3RyYXRvciBjYW4gcGVyZm9ybSB0aGlzIGZ1bmN0aW9uIQMJAABmAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAkAAAIAAAABAgAAADJEb24ndCBhdHRhY2ggcGF5bWVudCB3aGVuIGNhbGxpbmcgdGhpcyBmdW5jdGlvbi4uLgQAAAAQb2xkU2NyaXB0VmVyc2lvbgkBAAAAEGdldFNjcmlwdFZlcnNpb24AAAAAAwkAAGYAAAACCQABkAAAAAEFAAAAEG9sZFNjcmlwdFZlcnNpb24AAAAAAAAAAAAJAARNAAAAAgkABE0AAAACBQAAABBvbGRTY3JpcHRWZXJzaW9uCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABFsYXN0QWN0aW9uRGF0YUtleQUAAAATbGFzdEFjdGlvbkRhdGFWYWx1ZQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEHRpbWVzdGFtcERhdGFLZXkIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wCQAAAgAAAAEJAAEsAAAAAgIAAAAtVGhlIHNjcmlwdCB2ZXJzaW9uIGhhcyBhbHJlYWR5IGJlZW4gdXBkYXRlZDogBQAAAA1zY3JpcHRWZXJzaW9uAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAQAAAAMaXNWYWxpZE93bmVyCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAgFAAAAAnR4AAAAD3NlbmRlclB1YmxpY0tleQQAAAAMaXNWYWxpZEFkbWluAwUAAAAMaXNWYWxpZE93bmVyBgkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAEFAAAADmFkbWluUHVibGljS2V5BAAAAAxpc1ZhbGlkTU1Cb3QDBQAAAAxpc1ZhbGlkT3duZXIGCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAQUAAAAObW1ib3RQdWJsaWNLZXkEAAAAEWlzVmFsaWRHdWFyYW50b3JzCQAAZwAAAAIJAABkAAAAAgkAAGQAAAACCQAAZAAAAAIJAABkAAAAAgMJAAnFAAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAABCQABkQAAAAIFAAAAE2d1YXJhbnRvclB1YmxpY0tleXMAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAADCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAgkAAZEAAAACBQAAABNndWFyYW50b3JQdWJsaWNLZXlzAAAAAAAAAAABAAAAAAAAAAABAAAAAAAAAAAAAwkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAMJAAGRAAAAAgUAAAATZ3VhcmFudG9yUHVibGljS2V5cwAAAAAAAAAAAgAAAAAAAAAAAQAAAAAAAAAAAAMJAAnFAAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAECQABkQAAAAIFAAAAE2d1YXJhbnRvclB1YmxpY0tleXMAAAAAAAAAAAMAAAAAAAAAAAEAAAAAAAAAAAADCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAABQkAAZEAAAACBQAAABNndWFyYW50b3JQdWJsaWNLZXlzAAAAAAAAAAAEAAAAAAAAAAABAAAAAAAAAAAABQAAAA1taW5TaWduYXR1cmVzBAAAAAckbWF0Y2gwBQAAAAJ0eAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQnVyblRyYW5zYWN0aW9uBAAAAAFiBQAAAAckbWF0Y2gwAwUAAAAMaXNWYWxpZE93bmVyCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAAlwb3J0Zm9saW8IBQAAAAFiAAAAB2Fzc2V0SWQHAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAVPcmRlcgQAAAABbwUAAAAHJG1hdGNoMAMFAAAADGlzVmFsaWRPd25lcgMDCQAAAAAAAAIIBQAAAAFvAAAACW9yZGVyVHlwZQUAAAADQnV5CQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAAlwb3J0Zm9saW8ICAUAAAABbwAAAAlhc3NldFBhaXIAAAAKcHJpY2VBc3NldAcGAwkAAAAAAAACCAUAAAABbwAAAAlvcmRlclR5cGUFAAAABFNlbGwJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAACXBvcnRmb2xpbwgIBQAAAAFvAAAACWFzc2V0UGFpcgAAAAthbW91bnRBc3NldAcHAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABNUcmFuc2ZlclRyYW5zYWN0aW9uBAAAAAF0BQAAAAckbWF0Y2gwAwkBAAAAASEAAAABBQAAABNpc0NvbnRyYWN0U3VzcGVuZGVkAwMDAwUAAAAMaXNWYWxpZE93bmVyCQAAAAAAAAIIBQAAAAF0AAAACmZlZUFzc2V0SWQFAAAACXhmZWVBc3NldAcJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAACXBvcnRmb2xpbwgFAAAAAXQAAAAHYXNzZXRJZAcGAwMDBQAAAAxpc1ZhbGlkQWRtaW4JAAAAAAAAAggFAAAAAXQAAAAHYXNzZXRJZAUAAAAJZm1tdEFzc2V0BwkAAAAAAAACCAUAAAABdAAAAApmZWVBc3NldElkBQAAAAl4ZmVlQXNzZXQHCQAAAAAAAAIJAAQkAAAAAQgFAAAAAXQAAAAJcmVjaXBpZW50BQAAAAVmZGFwcAcGAwMDAwUAAAARaXNWYWxpZEd1YXJhbnRvcnMJAQAAAAIhPQAAAAIIBQAAAAF0AAAAB2Fzc2V0SWQFAAAACWZtbXRBc3NldAcJAQAAAAIhPQAAAAIIBQAAAAF0AAAAB2Fzc2V0SWQFAAAACXhmZWVBc3NldAcJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAAlwb3J0Zm9saW8IBQAAAAF0AAAAB2Fzc2V0SWQHCQAAAAAAAAIJAAQkAAAAAQgFAAAAAXQAAAAJcmVjaXBpZW50BQAAAAVmZGFwcAcHAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABBMZWFzZVRyYW5zYWN0aW9uBAAAAAFsBQAAAAckbWF0Y2gwBQAAAAxpc1ZhbGlkTU1Cb3QDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAFkxlYXNlQ2FuY2VsVHJhbnNhY3Rpb24DBQAAAAxpc1ZhbGlkTU1Cb3QGBQAAABFpc1ZhbGlkR3VhcmFudG9ycwMDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAUU2V0U2NyaXB0VHJhbnNhY3Rpb24GCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAD0RhdGFUcmFuc2FjdGlvbgMFAAAADGlzVmFsaWRBZG1pbgUAAAARaXNWYWxpZEd1YXJhbnRvcnMHB9AmlPU=", 1699, 1708, 833}, {`V4: 922-802`, "AAIEAAAAAAAAAAgIAhIAEgASAAAAABkAAAAADXNjcmlwdFZlcnNpb24CAAAADnYzLjA1XzIwMjAwOTEzAAAAAAdwZXJjZW50AAAAAAAAAABkAAAAAAtyaXNrUGVyY2VudAAAAAAAAAAAFAAAAAALdGVhbVBlcmNlbnQAAAAAAAAAAAoAAAAADmFkbWluUHVibGljS2V5AQAAACD/zQv9xtp+IwicmSq/7YB3qzF8dYREKcB8rX1b2hNXAwAAAAAOZnRlYW1QdWJsaWNLZXkBAAAAIIN6TMTYLvwQfnpKcKqqAAZ8882v9yZAFQ900E5yClNCAAAAAA5tbWJvdFB1YmxpY0tleQEAAAAgSqCTD7MZSfeiXlZ7r112NWe+YGAAI7co5SLZqPgB7C8AAAAACWVtcHR5TGlzdAkABEwAAAACAQAAAAAJAARMAAAAAgEAAAAACQAETAAAAAIBAAAAAAkABEwAAAACAQAAAAAJAARMAAAAAgEAAAAACQAETAAAAAIBAAAAAAkABEwAAAACAQAAAAAFAAAAA25pbAAAAAATZ3VhcmFudG9yUHVibGljS2V5cwkABE4AAAACCQAETAAAAAIBAAAAIP/NC/3G2n4jCJyZKr/tgHerMXx1hEQpwHytfVvaE1cDBQAAAANuaWwFAAAACWVtcHR5TGlzdAAAAAANZ3VhcmFudG9yU2l6ZQkAAGUAAAACCQABkAAAAAEFAAAAE2d1YXJhbnRvclB1YmxpY0tleXMJAAGQAAAAAQUAAAAJZW1wdHlMaXN0AAAAAA1taW5TaWduYXR1cmVzCQAAZAAAAAIJAABpAAAAAgUAAAANZ3VhcmFudG9yU2l6ZQAAAAAAAAAAAgkAAGoAAAACBQAAAA1ndWFyYW50b3JTaXplAAAAAAAAAAACAAAAAAlmbW10QXNzZXQBAAAAIGYr8dw8TDanuTqo+vs1Q9xNuAeFp1N2ZT91Xozrfzj0AAAAAAl4ZmVlQXNzZXQBAAAAID7aqaNufgAR8AeMAT3F3i6NRzE7nRhBON4sOuYerrY3AAAAAAlwb3J0Zm9saW8JAARNAAAAAgkABE0AAAACCQAETAAAAAIBAAAAIB6UBxNSdqEllf3IYaiCXxB/3zpPKbv8mkY/Wv02T5+RCQAETAAAAAIBAAAAIGz6av/F7aqMC3+1KpPSogwvgoLbdHoEjFP7/RMfc6D/CQAETAAAAAIFAAAABHVuaXQJAARMAAAAAgEAAAAgLiDD9uqKn4lRu7/oiBETNux+2MJCA3JlDVjNcyZCZYIJAARMAAAAAgEAAAAgDrECagw+n0f35EaU5062t7xDfH5ladDpGJsi5gny6M4JAARMAAAAAgEAAAAg9h42QtOX3fJaWBUg7iwP2i1GBoqANpKuVYlZnrDFLKEJAARMAAAAAgEAAAAglVMgFzLH9/gxbVKojbVZ08/r8nPtlHFX5Z0m586HauAJAARMAAAAAgEAAAAgQxj0G3VSMI+7+iJkvwQoTrekocmcbhiCndEGv8vAJAIJAARMAAAAAgEAAAAgoVJa1UnWcbrDrx+GyZJ/6g+KWhwfmKQrcwaOzJr+1WcFAAAAA25pbAUAAAAJeGZlZUFzc2V0BQAAAAlmbW10QXNzZXQAAAAABWFkbWluCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXyvBTGJ3PniBi4dPVWqjby+gPf9AH2sQ1AAAAAAVmdGVhbQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVxC7GUc6JOl3erhvhB+nL92RfEkunZJulwAAAAAFZmRhcHAJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVeUGM4qgYZsQxeQti8+oFzAKUNnZKGyBg0AAAAACmhlZGdlRnVuZHMJAABlAAAAAggJAQAAAAV2YWx1ZQAAAAEJAAPsAAAAAQUAAAAJZm1tdEFzc2V0AAAACHF1YW50aXR5CQAAZAAAAAIJAABkAAAAAgkAA/AAAAACBQAAAAR0aGlzBQAAAAlmbW10QXNzZXQJAAPwAAAAAgUAAAAFZnRlYW0FAAAACWZtbXRBc3NldAkAA/AAAAACBQAAAAVmZGFwcAUAAAAJZm1tdEFzc2V0AAAAABJ0ZWFtUGF5b3V0c0RhdGFLZXkCAAAAC3RlYW1QYXlvdXRzAAAAABRzY3JpcHRWZXJzaW9uRGF0YUtleQIAAAANc2NyaXB0VmVyc2lvbgAAAAAQdGltZXN0YW1wRGF0YUtleQIAAAAJdGltZXN0YW1wAAAAABFsYXN0QWN0aW9uRGF0YUtleQIAAAAKbGFzdEFjdGlvbgAAAAALZGFwcERhdGFLZXkJAAJYAAAAAQgFAAAABHRoaXMAAAAFYnl0ZXMAAAAAE2lzQ29udHJhY3RTdXNwZW5kZWQJAQAAAAEhAAAAAQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAAVhZG1pbgUAAAALZGFwcERhdGFLZXkHAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEAAAAFYXNzZXQKAQAAAA9pc0Fzc2V0RGlzYWJsZWQAAAABAAAADGFzc2V0RGF0YUtleQkBAAAAASEAAAABCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAABWFkbWluBQAAAAxhc3NldERhdGFLZXkHCgEAAAAKZGlmZmVyZW5jZQAAAAIAAAAMZmNvbGRCYWxhbmNlAAAADGZkYXBwQmFsYW5jZQkAAGUAAAACCQAAawAAAAMJAABkAAAAAgUAAAAMZmNvbGRCYWxhbmNlBQAAAAxmZGFwcEJhbGFuY2UFAAAAC3Jpc2tQZXJjZW50BQAAAAdwZXJjZW50BQAAAAxmZGFwcEJhbGFuY2UEAAAABmFtb3VudAQAAAAHJG1hdGNoMAUAAAAFYXNzZXQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAACkJ5dGVWZWN0b3IEAAAAAmlkBQAAAAckbWF0Y2gwAwkBAAAAD2lzQXNzZXREaXNhYmxlZAAAAAEJAAJYAAAAAQUAAAACaWQAAAAAAAAAAAAJAQAAAApkaWZmZXJlbmNlAAAAAgkAA/AAAAACBQAAAAR0aGlzBQAAAAJpZAkAA/AAAAACBQAAAAVmZGFwcAUAAAACaWQDCQEAAAAPaXNBc3NldERpc2FibGVkAAAAAQIAAAAFV0FWRVMAAAAAAAAAAAAJAQAAAApkaWZmZXJlbmNlAAAAAggJAAPvAAAAAQUAAAAEdGhpcwAAAAdyZWd1bGFyCAkAA+8AAAABBQAAAAVmZGFwcAAAAAdyZWd1bGFyAwkAAGYAAAACBQAAAAZhbW91bnQAAAAAAAAAAAAJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAFZmRhcHAFAAAABmFtb3VudAUAAAAFYXNzZXQFAAAAA25pbAUAAAADbmlsAAAAAwAAAAFpAQAAAA1hdXRvUmViYWxhbmNlAAAAAAQAAAATbGFzdEFjdGlvbkRhdGFWYWx1ZQIAAAANYXV0b1JlYmFsYW5jZQMFAAAAE2lzQ29udHJhY3RTdXNwZW5kZWQJAAACAAAAAQIAAAAtVGhlIGFkbWluaXN0cmF0b3IgaGFzIHN1c3BlbmRlZCB0aGUgY29udHJhY3QhAwMJAQAAAAIhPQAAAAIIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAQAAAAIhPQAAAAIIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAObW1ib3RQdWJsaWNLZXkHCQAAAgAAAAECAAAAMU9ubHkgdGhlIGFkbWluaXN0cmF0b3IgY2FuIHBlcmZvcm0gdGhpcyBmdW5jdGlvbiEDCQAAZgAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAJAAACAAAAAQIAAAAyRG9uJ3QgYXR0YWNoIHBheW1lbnQgd2hlbiBjYWxsaW5nIHRoaXMgZnVuY3Rpb24uLi4EAAAAD3NjcmlwdFRyYW5zZmVycwkABE4AAAACCQAETgAAAAIJAAROAAAAAgkABE4AAAACCQAETgAAAAIJAAROAAAAAgkABE4AAAACCQAETgAAAAIJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAAACQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAAAQkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAIJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAADCQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAABAkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAUJAQAAABFnZXRTY3JpcHRUcmFuc2ZlcgAAAAEJAAGRAAAAAgUAAAAJcG9ydGZvbGlvAAAAAAAAAAAGCQEAAAARZ2V0U2NyaXB0VHJhbnNmZXIAAAABCQABkQAAAAIFAAAACXBvcnRmb2xpbwAAAAAAAAAABwkBAAAAEWdldFNjcmlwdFRyYW5zZmVyAAAAAQkAAZEAAAACBQAAAAlwb3J0Zm9saW8AAAAAAAAAAAgDCQAAZgAAAAIJAAGQAAAAAQUAAAAPc2NyaXB0VHJhbnNmZXJzAAAAAAAAAAAACQAETQAAAAIJAARNAAAAAgUAAAAPc2NyaXB0VHJhbnNmZXJzCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAQdGltZXN0YW1wRGF0YUtleQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEWxhc3RBY3Rpb25EYXRhS2V5BQAAABNsYXN0QWN0aW9uRGF0YVZhbHVlCQAAAgAAAAECAAAANU5vIHRyYW5zZmVycyBhdmFpbGFibGUuIFdhaXQgdW50aWwgaW1iYWxhbmNlIGFwcGVhcnMuAAAAAWkBAAAADmdldFRlYW1QYXlvdXRzAAAAAAQAAAATbGFzdEFjdGlvbkRhdGFWYWx1ZQIAAAAOZ2V0VGVhbVBheW91dHMDBQAAABNpc0NvbnRyYWN0U3VzcGVuZGVkCQAAAgAAAAECAAAALVRoZSBhZG1pbmlzdHJhdG9yIGhhcyBzdXNwZW5kZWQgdGhlIGNvbnRyYWN0IQMDCQEAAAACIT0AAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQEAAAACIT0AAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmZ0ZWFtUHVibGljS2V5BwkAAAIAAAABAgAAADFPbmx5IHRoZSBhZG1pbmlzdHJhdG9yIGNhbiBwZXJmb3JtIHRoaXMgZnVuY3Rpb24hAwkAAGYAAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAACQAAAgAAAAECAAAAMkRvbid0IGF0dGFjaCBwYXltZW50IHdoZW4gY2FsbGluZyB0aGlzIGZ1bmN0aW9uLi4uBAAAAApvbGRQYXlvdXRzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAEnRlYW1QYXlvdXRzRGF0YUtleQAAAAAAAAAAAAQAAAAGYW1vdW50CQAAZQAAAAIJAABrAAAAAwUAAAAKaGVkZ2VGdW5kcwUAAAALdGVhbVBlcmNlbnQFAAAAB3BlcmNlbnQFAAAACm9sZFBheW91dHMDCQAAZgAAAAIFAAAABmFtb3VudAAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAASdGVhbVBheW91dHNEYXRhS2V5CQAAZAAAAAIFAAAACm9sZFBheW91dHMFAAAABmFtb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAAVmdGVhbQUAAAAGYW1vdW50BQAAAAlmbW10QXNzZXQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEHRpbWVzdGFtcERhdGFLZXkIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEWxhc3RBY3Rpb25EYXRhS2V5BQAAABNsYXN0QWN0aW9uRGF0YVZhbHVlBQAAAANuaWwJAAACAAAAAQIAAAA4Tm8gcGF5bWVudHMgYXZhaWxhYmxlLiBXYWl0IGZvciBuZXcgaW52ZXN0bWVudHMgdG8gY29tZS4AAAABaQEAAAAQc2V0U2NyaXB0VmVyc2lvbgAAAAAEAAAAE2xhc3RBY3Rpb25EYXRhVmFsdWUCAAAAEHNldFNjcmlwdFZlcnNpb24DBQAAABNpc0NvbnRyYWN0U3VzcGVuZGVkCQAAAgAAAAECAAAALVRoZSBhZG1pbmlzdHJhdG9yIGhhcyBzdXNwZW5kZWQgdGhlIGNvbnRyYWN0IQMJAQAAAAIhPQAAAAIIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAAACAAAAAQIAAAAxT25seSB0aGUgYWRtaW5pc3RyYXRvciBjYW4gcGVyZm9ybSB0aGlzIGZ1bmN0aW9uIQMJAABmAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAkAAAIAAAABAgAAADJEb24ndCBhdHRhY2ggcGF5bWVudCB3aGVuIGNhbGxpbmcgdGhpcyBmdW5jdGlvbi4uLgQAAAAKb2xkVmVyc2lvbgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAABRzY3JpcHRWZXJzaW9uRGF0YUtleQIAAAAAAwkBAAAAAiE9AAAAAgUAAAAKb2xkVmVyc2lvbgUAAAANc2NyaXB0VmVyc2lvbgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABRzY3JpcHRWZXJzaW9uRGF0YUtleQUAAAANc2NyaXB0VmVyc2lvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAQdGltZXN0YW1wRGF0YUtleQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAARbGFzdEFjdGlvbkRhdGFLZXkFAAAAE2xhc3RBY3Rpb25EYXRhVmFsdWUFAAAAA25pbAkAAAIAAAABCQABLAAAAAICAAAALVRoZSBzY3JpcHQgdmVyc2lvbiBoYXMgYWxyZWFkeSBiZWVuIHVwZGF0ZWQ6IAUAAAAKb2xkVmVyc2lvbgAAAAEAAAACdHgBAAAABnZlcmlmeQAAAAAEAAAADGlzVmFsaWRPd25lcgkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAIBQAAAAJ0eAAAAA9zZW5kZXJQdWJsaWNLZXkEAAAADGlzVmFsaWRBZG1pbgMFAAAADGlzVmFsaWRPd25lcgYJAAnFAAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAABBQAAAA5hZG1pblB1YmxpY0tleQQAAAAMaXNWYWxpZE1NQm90AwUAAAAMaXNWYWxpZE93bmVyBgkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAEFAAAADm1tYm90UHVibGljS2V5BAAAABFpc1ZhbGlkR3VhcmFudG9ycwkAAGcAAAACCQAAZAAAAAIJAABkAAAAAgkAAGQAAAACCQAAZAAAAAIDCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAQkAAZEAAAACBQAAABNndWFyYW50b3JQdWJsaWNLZXlzAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAwkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAIJAAGRAAAAAgUAAAATZ3VhcmFudG9yUHVibGljS2V5cwAAAAAAAAAAAQAAAAAAAAAAAQAAAAAAAAAAAAMJAAnFAAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAADCQABkQAAAAIFAAAAE2d1YXJhbnRvclB1YmxpY0tleXMAAAAAAAAAAAIAAAAAAAAAAAEAAAAAAAAAAAADCQAJxQAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAABAkAAZEAAAACBQAAABNndWFyYW50b3JQdWJsaWNLZXlzAAAAAAAAAAADAAAAAAAAAAABAAAAAAAAAAAAAwkACcUAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAUJAAGRAAAAAgUAAAATZ3VhcmFudG9yUHVibGljS2V5cwAAAAAAAAAABAAAAAAAAAAAAQAAAAAAAAAAAAUAAAANbWluU2lnbmF0dXJlcwQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAD0J1cm5UcmFuc2FjdGlvbgQAAAABYgUAAAAHJG1hdGNoMAMFAAAADGlzVmFsaWRPd25lcgkBAAAAASEAAAABCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAAJcG9ydGZvbGlvCAUAAAABYgAAAAdhc3NldElkBwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAFT3JkZXIEAAAAAW8FAAAAByRtYXRjaDADBQAAAAxpc1ZhbGlkT3duZXIDAwkAAAAAAAACCAUAAAABbwAAAAlvcmRlclR5cGUFAAAAA0J1eQkBAAAAASEAAAABCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAAJcG9ydGZvbGlvCAgFAAAAAW8AAAAJYXNzZXRQYWlyAAAACnByaWNlQXNzZXQHBgMJAAAAAAAAAggFAAAAAW8AAAAJb3JkZXJUeXBlBQAAAARTZWxsCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAAlwb3J0Zm9saW8ICAUAAAABbwAAAAlhc3NldFBhaXIAAAALYW1vdW50QXNzZXQHBwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAATVHJhbnNmZXJUcmFuc2FjdGlvbgQAAAABdAUAAAAHJG1hdGNoMAMJAQAAAAEhAAAAAQUAAAATaXNDb250cmFjdFN1c3BlbmRlZAMDAwMFAAAADGlzVmFsaWRPd25lcgkAAAAAAAACCAUAAAABdAAAAApmZWVBc3NldElkBQAAAAl4ZmVlQXNzZXQHCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAAlwb3J0Zm9saW8IBQAAAAF0AAAAB2Fzc2V0SWQHBgMDAwUAAAAMaXNWYWxpZEFkbWluCQAAAAAAAAIIBQAAAAF0AAAAB2Fzc2V0SWQFAAAACWZtbXRBc3NldAcJAAAAAAAAAggFAAAAAXQAAAAKZmVlQXNzZXRJZAUAAAAJeGZlZUFzc2V0BwkAAAAAAAACCQAEJAAAAAEIBQAAAAF0AAAACXJlY2lwaWVudAUAAAAFZmRhcHAHBgMDAwMFAAAAEWlzVmFsaWRHdWFyYW50b3JzCQEAAAACIT0AAAACCAUAAAABdAAAAAdhc3NldElkBQAAAAlmbW10QXNzZXQHCQEAAAACIT0AAAACCAUAAAABdAAAAAdhc3NldElkBQAAAAl4ZmVlQXNzZXQHCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAAJcG9ydGZvbGlvCAUAAAABdAAAAAdhc3NldElkBwkAAAAAAAACCQAEJAAAAAEIBQAAAAF0AAAACXJlY2lwaWVudAUAAAAFZmRhcHAHBwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAQTGVhc2VUcmFuc2FjdGlvbgQAAAABbAUAAAAHJG1hdGNoMAUAAAAMaXNWYWxpZE1NQm90AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABZMZWFzZUNhbmNlbFRyYW5zYWN0aW9uAwUAAAAMaXNWYWxpZE1NQm90BgUAAAARaXNWYWxpZEd1YXJhbnRvcnMDAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABdJbnZva2VTY3JpcHRUcmFuc2FjdGlvbgYDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAFFNldFNjcmlwdFRyYW5zYWN0aW9uBgkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAA9EYXRhVHJhbnNhY3Rpb24DBQAAAAxpc1ZhbGlkQWRtaW4FAAAAEWlzVmFsaWRHdWFyYW50b3JzBwdbf5So", 1651, 1660, 802}, {`V4: ARHXYD7j7chYAze2gwH4J3h7HLpHpiBxufnJo6YeqTvQ`, "AAIEAAAAAAAAABYIAhIAEgMKAQESBAoCAQgSAwoBCBIAAAAAQgEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAABAAAADmdldFN0cmluZ0J5S2V5AAAAAQAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5AgAAAAABAAAAFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkAAAACAAAAB2FkZHJlc3MAAAADa2V5CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAAB2FkZHJlc3MFAAAAA2tleQcBAAAAGGdldFN0cmluZ0J5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAHYWRkcmVzcwUAAAADa2V5AgAAAAABAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAHYWRkcmVzcwUAAAADa2V5AAAAAAAAAAAAAAAAAAdXQVZFTEVUAAAAAAAF9eEAAAAAAAVQQVVMSQAAAAAAAA9CQAAAAAAIUFJJQ0VMRVQAAAAAAAAPQkAAAAAABE1VTFQAAAAAAAX14QAAAAAACVNDQUxFTVVMVAAAAAAAAAAACAAAAAANTUlOT1JERVJUT1RBTAkAAGgAAAACAAAAAAAAAAAKBQAAAAdXQVZFTEVUAAAAAAZNQVhST0kAAAAAAAAAAF8AAAAACENBTkNFTEVEAgAAAAhjYW5jZWxlZAAAAAADTkVXAgAAAANuZXcAAAAABkZJTExFRAIAAAAGZmlsbGVkAAAAAAhQcmljZUtleQIAAAAFcHJpY2UAAAAADkJvbmRBc3NldElkS2V5AgAAAA1ib25kX2Fzc2V0X2lkAAAAABJOZXV0cmlub0Fzc2V0SWRLZXkCAAAAEW5ldXRyaW5vX2Fzc2V0X2lkAAAAABFCYWxhbmNlTG9ja2Vka0tleQIAAAANYmFsYW5jZV9sb2NrXwAAAAAVV2F2ZXNMb2NrZWRCYWxhbmNlS2V5CQABLAAAAAIFAAAAEUJhbGFuY2VMb2NrZWRrS2V5AgAAAAV3YXZlcwAAAAAYTmV1dHJpbm9Mb2NrZWRCYWxhbmNlS2V5CQABLAAAAAIFAAAAEUJhbGFuY2VMb2NrZWRrS2V5AgAAAAhuZXV0cmlubwAAAAANRmlyc3RPcmRlcktleQIAAAALb3JkZXJfZmlyc3QBAAAAEmdldFJvaUJ5T3JkZXJJZEtleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACAgAAABBkZWJ1Z19vcmRlcl9yb2lfBQAAAAdvcmRlcklkAQAAABBnZXRPcmRlclByaWNlS2V5AAAAAQAAAAdvcmRlcklkCQABLAAAAAICAAAADG9yZGVyX3ByaWNlXwUAAAAHb3JkZXJJZAEAAAAQZ2V0T3JkZXJUb3RhbEtleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACAgAAAAxvcmRlcl90b3RhbF8FAAAAB29yZGVySWQBAAAAEGdldE9yZGVyT3duZXJLZXkAAAABAAAAB29yZGVySWQJAAEsAAAAAgIAAAAMb3JkZXJfb3duZXJfBQAAAAdvcmRlcklkAQAAABFnZXRPcmRlckhlaWdodEtleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACAgAAAA1vcmRlcl9oZWlnaHRfBQAAAAdvcmRlcklkAQAAABFnZXRPcmRlclN0YXR1c0tleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACAgAAAA1vcmRlcl9zdGF0dXNfBQAAAAdvcmRlcklkAQAAABZnZXRPcmRlckZpbGxlZFRvdGFsS2V5AAAAAQAAAAdvcmRlcklkCQABLAAAAAICAAAAE29yZGVyX2ZpbGxlZF90b3RhbF8FAAAAB29yZGVySWQBAAAAD2dldFByZXZPcmRlcktleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACAgAAAAtvcmRlcl9wcmV2XwUAAAAHb3JkZXJJZAEAAAAPZ2V0TmV4dE9yZGVyS2V5AAAAAQAAAAdvcmRlcklkCQABLAAAAAICAAAAC29yZGVyX25leHRfBQAAAAdvcmRlcklkAQAAABZjb252ZXJ0TmV1dHJpbm9Ub1dhdmVzAAAAAgAAAAZhbW91bnQAAAAFcHJpY2UJAABrAAAAAwkAAGsAAAADBQAAAAZhbW91bnQFAAAACFBSSUNFTEVUBQAAAAVwcmljZQUAAAAHV0FWRUxFVAUAAAAFUEFVTEkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACAAAABmFtb3VudAAAAAVwcmljZQkAAGsAAAADCQAAawAAAAMFAAAABmFtb3VudAUAAAAFcHJpY2UFAAAACFBSSUNFTEVUBQAAAAVQQVVMSQUAAAAHV0FWRUxFVAEAAAASY29udmVydFdhdmVzVG9Cb25kAAAAAgAAAAZhbW91bnQAAAAFcHJpY2UJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgUAAAAGYW1vdW50BQAAAAVwcmljZQEAAAASY29udmVydEJvbmRUb1dhdmVzAAAAAgAAAAZhbW91bnQAAAAFcHJpY2UJAQAAABZjb252ZXJ0TmV1dHJpbm9Ub1dhdmVzAAAAAgUAAAAGYW1vdW50BQAAAAVwcmljZQAAAAAQbmV1dHJpbm9Db250cmFjdAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV3AEYqZHm+mtVmiUy++FjDCCICiaCBSWsgAAAAAPY29udHJvbENvbnRyYWN0CQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AAAAABNsaXF1aWRhdGlvbkNvbnRyYWN0CQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXGupJy/oKfsoIfyjVn5WODHtptak4kR9IAAAAAA9uZXV0cmlub0Fzc2V0SWQBAAAAILYmKcME9c5TkaQOS3UkL2SMUbH6369UKb1I0h0qsqrRAAAAAAtib25kQXNzZXRJZAEAAAAgVe7DvqoL8FDoccgbqm5wnqSxyP5KLrnB8czFaw94l0sAAAAACWlzQmxvY2tlZAkBAAAAFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QCAAAACmlzX2Jsb2NrZWQAAAAADGN1cnJlbnRQcmljZQkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2NvbnRyb2xDb250cmFjdAUAAAAIUHJpY2VLZXkAAAAAFW5ldXRyaW5vTG9ja2VkQmFsYW5jZQkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAAGE5ldXRyaW5vTG9ja2VkQmFsYW5jZUtleQAAAAAHcmVzZXJ2ZQkAAGUAAAACCAkAA+8AAAABBQAAABBuZXV0cmlub0NvbnRyYWN0AAAAB3JlZ3VsYXIJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAABBuZXV0cmlub0NvbnRyYWN0BQAAABVXYXZlc0xvY2tlZEJhbGFuY2VLZXkAAAAADnJlc2VydmVzSW5Vc2RuCQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIFAAAAB3Jlc2VydmUFAAAADGN1cnJlbnRQcmljZQAAAAAObmV1dHJpbm9TdXBwbHkJAABlAAAAAgkAAGUAAAACCQAAZAAAAAIFAAAAFW5ldXRyaW5vTG9ja2VkQmFsYW5jZQgJAQAAAAV2YWx1ZQAAAAEJAAPsAAAAAQUAAAAPbmV1dHJpbm9Bc3NldElkAAAACHF1YW50aXR5CQAD8AAAAAIFAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAAD25ldXRyaW5vQXNzZXRJZAkAA/AAAAACBQAAABNsaXF1aWRhdGlvbkNvbnRyYWN0BQAAAA9uZXV0cmlub0Fzc2V0SWQAAAAAB2RlZmljaXQJAABlAAAAAgUAAAAObmV1dHJpbm9TdXBwbHkFAAAADnJlc2VydmVzSW5Vc2RuAAAAAA1jdXJyZW50TWF4Um9pCQAAawAAAAMFAAAAB2RlZmljaXQAAAAAAAAAAGQFAAAADm5ldXRyaW5vU3VwcGx5AAAAAA1jdXJyZW50QnJNdWx0CQAAawAAAAMFAAAADnJlc2VydmVzSW5Vc2RuBQAAAARNVUxUBQAAAA5uZXV0cmlub1N1cHBseQAAAAAKZmlyc3RPcmRlcgkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAANRmlyc3RPcmRlcktleQEAAAANZ2V0T3JkZXJQcmljZQAAAAEAAAACaWQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABBnZXRPcmRlclByaWNlS2V5AAAAAQUAAAACaWQBAAAADWdldE9yZGVyVG90YWwAAAABAAAAAmlkCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAQZ2V0T3JkZXJUb3RhbEtleQAAAAEFAAAAAmlkAQAAAA1nZXRPcmRlck93bmVyAAAAAQAAAAJpZAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAEGdldE9yZGVyT3duZXJLZXkAAAABBQAAAAJpZAEAAAAOZ2V0T3JkZXJTdGF0dXMAAAABAAAAAmlkCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAARZ2V0T3JkZXJTdGF0dXNLZXkAAAABBQAAAAJpZAEAAAATZ2V0T3JkZXJGaWxsZWRUb3RhbAAAAAEAAAACaWQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABZnZXRPcmRlckZpbGxlZFRvdGFsS2V5AAAAAQUAAAACaWQBAAAADGdldFByZXZPcmRlcgAAAAEAAAACaWQJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAA9nZXRQcmV2T3JkZXJLZXkAAAABBQAAAAJpZAEAAAAMZ2V0TmV4dE9yZGVyAAAAAQAAAAJpZAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAD2dldE5leHRPcmRlcktleQAAAAEFAAAAAmlkAQAAAA5nZXRQcmljZUZvclJvaQAAAAEAAAALcm9pUGVyY2VudHMJAABrAAAAAwkAAGQAAAACAAAAAAAAAABkBQAAAAtyb2lQZXJjZW50cwUAAAAMY3VycmVudFByaWNlAAAAAAAAAABkAQAAAA9nZXRSZXZlcnNlUHJpY2UAAAABAAAABXByaWNlCQAAaQAAAAIJAABoAAAAAgUAAAAIUFJJQ0VMRVQFAAAACFBSSUNFTEVUBQAAAAVwcmljZQEAAAAWY2FsY05zYnQyV2F2ZXNQcmljZVJhdwAAAAIAAAANc3BlbnRXYXZlc1JhdwAAAA9yZWNlaXZlZE5zYnRSYXcJAABrAAAAAwUAAAANc3BlbnRXYXZlc1JhdwkAAGgAAAACBQAAAAVQQVVMSQUAAAAIUFJJQ0VMRVQFAAAAD3JlY2VpdmVkTnNidFJhdwEAAAAJb3JkZXJEYXRhAAAABwAAAAdvcmRlcklkAAAADXRvdGFsV2F2ZWxldHMAAAAOZmlsbGVkV2F2ZWxldHMAAAAFb3duZXIAAAAGc3RhdHVzAAAAA3JvaQAAAAVwcmljZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAEGdldE9yZGVyUHJpY2VLZXkAAAABBQAAAAdvcmRlcklkBQAAAAVwcmljZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAEGdldE9yZGVyVG90YWxLZXkAAAABBQAAAAdvcmRlcklkBQAAAA10b3RhbFdhdmVsZXRzCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAWZ2V0T3JkZXJGaWxsZWRUb3RhbEtleQAAAAEFAAAAB29yZGVySWQFAAAADmZpbGxlZFdhdmVsZXRzCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABBnZXRPcmRlck93bmVyS2V5AAAAAQUAAAAHb3JkZXJJZAUAAAAFb3duZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABFnZXRPcmRlckhlaWdodEtleQAAAAEFAAAAB29yZGVySWQFAAAABmhlaWdodAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAARZ2V0T3JkZXJTdGF0dXNLZXkAAAABBQAAAAdvcmRlcklkBQAAAAZzdGF0dXMJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgIAAAAZZGVidWdfb3JkZXJfY3VycmVudFByaWNlXwUAAAAHb3JkZXJJZAUAAAAMY3VycmVudFByaWNlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAASZ2V0Um9pQnlPcmRlcklkS2V5AAAAAQUAAAAHb3JkZXJJZAUAAAADcm9pBQAAAANuaWwBAAAAEGludGVybmFsU2VsbEJvbmQAAAAIAAAAC3BGaXJzdE9yZGVyAAAACnBOZXh0T3JkZXIAAAAMcEZpbGxlZFRvdGFsAAAABHBSb2kAAAAGcFByaWNlAAAAEHBQYXltZW50V2F2ZWxldHMAAAARb3JkZXJPd25lckFkZHJlc3MAAAAMaW5zdGFudE9yZGVyBAAAABVwcmljZVdhdmVzQnlCb25kQ2VudHMJAQAAAA5nZXRQcmljZUZvclJvaQAAAAEFAAAABHBSb2kEAAAADXJlbWFpbmVkVG90YWwJAABlAAAAAgUAAAAQcFBheW1lbnRXYXZlbGV0cwUAAAAMcEZpbGxlZFRvdGFsBAAAABNmaWxsYWJsZU9yZGVyQW1vdW50CQEAAAASY29udmVydFdhdmVzVG9Cb25kAAAAAgUAAAANcmVtYWluZWRUb3RhbAUAAAAVcHJpY2VXYXZlc0J5Qm9uZENlbnRzBAAAABt0b3RhbE9yZGVyV2F2ZWxldGVzUmVxdWlyZWQJAQAAABJjb252ZXJ0Qm9uZFRvV2F2ZXMAAAACBQAAABNmaWxsYWJsZU9yZGVyQW1vdW50BQAAABVwcmljZVdhdmVzQnlCb25kQ2VudHMEAAAAFW5iVG9rZW5zU2VsbENvbmRpdGlvbgkAAGcAAAACBQAAAA1jdXJyZW50TWF4Um9pBQAAAARwUm9pAwkBAAAAASEAAAABBQAAABVuYlRva2Vuc1NlbGxDb25kaXRpb24JAAACAAAAAQkAASwAAAACAgAAABNpbm5hcHJvcHJpYXRlIHJvaTogCQABpAAAAAEFAAAABHBSb2kDCQAAAAAAAAIFAAAAG3RvdGFsT3JkZXJXYXZlbGV0ZXNSZXF1aXJlZAAAAAAAAAAAAAkAAAIAAAABAgAAAB9jYW5ub3QgZmlsbCBvcmRlciBhdCB0aGUgbW9tZW50BAAAAA5jaGFuZ2VXYXZlbGV0cwkAAGUAAAACBQAAAA1yZW1haW5lZFRvdGFsBQAAABt0b3RhbE9yZGVyV2F2ZWxldGVzUmVxdWlyZWQEAAAADHdyaXRlU2V0RGF0YQMFAAAADGluc3RhbnRPcmRlcgkBAAAACW9yZGVyRGF0YQAAAAcFAAAAC3BGaXJzdE9yZGVyBQAAABBwUGF5bWVudFdhdmVsZXRzCQAAZAAAAAIFAAAADHBGaWxsZWRUb3RhbAUAAAAbdG90YWxPcmRlcldhdmVsZXRlc1JlcXVpcmVkCQACWAAAAAEIBQAAABFvcmRlck93bmVyQWRkcmVzcwAAAAVieXRlcwUAAAAGRklMTEVEBQAAAARwUm9pBQAAAAxjdXJyZW50UHJpY2UJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABZnZXRPcmRlckZpbGxlZFRvdGFsS2V5AAAAAQUAAAALcEZpcnN0T3JkZXIJAABkAAAAAgUAAAAMcEZpbGxlZFRvdGFsBQAAABt0b3RhbE9yZGVyV2F2ZWxldGVzUmVxdWlyZWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEWdldE9yZGVyU3RhdHVzS2V5AAAAAQUAAAALcEZpcnN0T3JkZXIFAAAABkZJTExFRAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2V0UHJldk9yZGVyS2V5AAAAAQUAAAAKcE5leHRPcmRlcgIAAAAACQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAADUZpcnN0T3JkZXJLZXkFAAAACnBOZXh0T3JkZXIFAAAAA25pbAkABE4AAAACBQAAAAx3cml0ZVNldERhdGEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAARb3JkZXJPd25lckFkZHJlc3MFAAAAE2ZpbGxhYmxlT3JkZXJBbW91bnQFAAAAC2JvbmRBc3NldElkCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAAG3RvdGFsT3JkZXJXYXZlbGV0ZXNSZXF1aXJlZAUAAAAEdW5pdAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAABFvcmRlck93bmVyQWRkcmVzcwUAAAAOY2hhbmdlV2F2ZWxldHMFAAAABHVuaXQFAAAAA25pbAEAAAAXaW50ZXJuYWxBZGRCdXlCb25kT3JkZXIAAAAFAAAAA3JvaQAAAAVwcmljZQAAAAlwcmV2T3JkZXIAAAADaW52AAAADGluc3RhbnRPcmRlcgQAAAADcG10CQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAANpbnYAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAACm5ld09yZGVySWQJAAJYAAAAAQgFAAAAA2ludgAAAA10cmFuc2FjdGlvbklkAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWWNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWwgcmVhY3RpdmF0aW9uIGJ5IGVtZXJnZW5jeSBvcmFjbGVzAwkAAGYAAAACBQAAAA1NSU5PUkRFUlRPVEFMCAUAAAADcG10AAAABmFtb3VudAkAAAIAAAABCQABLAAAAAICAAAAF21pbiBvcmRlciB0b3RhbCBlcXVhbHMgCQABpAAAAAEFAAAADU1JTk9SREVSVE9UQUwDCQAAZgAAAAIFAAAAA3JvaQUAAAAGTUFYUk9JCQAAAgAAAAECAAAAF21heCBzZXRPcmRlciBST0kgaXMgOTUlAwkAAGYAAAACAAAAAAAAAAAABQAAAANyb2kJAAACAAAAAQIAAAAjY2FuJ3QgcGxhY2Ugb3JkZXIgd2l0aCBuZWdhdGl2ZSByb2kDCQAAAAAAAAIFAAAAA3JvaQAAAAAAAAAAAAkAAAIAAAABAgAAABxyb2kgc2hvdWxkIG5vdCBiZSBlcXVhbCB0byAwAwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkAAAIAAAABAgAAABJjYW4gdXNlIHdhdmVzIG9ubHkDCQEAAAACIT0AAAACCQEAAAANZ2V0T3JkZXJPd25lcgAAAAEFAAAACm5ld09yZGVySWQCAAAAAAkAAAIAAAABAgAAAAxvcmRlciBleGlzdHMDAwkBAAAAAiE9AAAAAgUAAAAJcHJldk9yZGVyAgAAAAAJAQAAAAIhPQAAAAIJAQAAAA5nZXRPcmRlclN0YXR1cwAAAAEFAAAACXByZXZPcmRlcgUAAAADTkVXBwkAAAIAAAABAgAAABxwcmV2IG9yZGVyIHN0YXR1cyBpcyBub3QgbmV3BAAAABlpc05ld09yZGVyQXRGaXJzdFBvc2l0aW9uCQAAAAAAAAIFAAAACXByZXZPcmRlcgIAAAAABAAAAAVvd25lcgkABCUAAAABCAUAAAADaW52AAAABmNhbGxlcgQAAAAJbmV4dE9yZGVyAwUAAAAZaXNOZXdPcmRlckF0Rmlyc3RQb3NpdGlvbgUAAAAKZmlyc3RPcmRlcgkBAAAADGdldE5leHRPcmRlcgAAAAEFAAAACXByZXZPcmRlcgQAAAAMbmV4dE9yZGVyUm9pCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAASZ2V0Um9pQnlPcmRlcklkS2V5AAAAAQUAAAAJbmV4dE9yZGVyBAAAABBpc05leHRPcmRlckVycm9yAwMJAQAAAAIhPQAAAAIFAAAACW5leHRPcmRlcgIAAAAACQAAZwAAAAIFAAAAA3JvaQUAAAAMbmV4dE9yZGVyUm9pBwYHBAAAAAxwcmV2T3JkZXJSb2kJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABJnZXRSb2lCeU9yZGVySWRLZXkAAAABBQAAAAlwcmV2T3JkZXIEAAAAEGlzUHJldk9yZGVyRXJyb3IDAwkBAAAAAiE9AAAAAgUAAAAJcHJldk9yZGVyAgAAAAAJAABmAAAAAgUAAAAMcHJldk9yZGVyUm9pBQAAAANyb2kHBgcDAwUAAAAQaXNOZXh0T3JkZXJFcnJvcgYFAAAAEGlzUHJldk9yZGVyRXJyb3IJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAfaW52YWxpZCBvcmRlciBpc1ByZXZPcmRlckVycm9yOgkAAaUAAAABBQAAABBpc1ByZXZPcmRlckVycm9yAgAAABIgaXNOZXh0T3JkZXJFcnJvcjoJAAGlAAAAAQUAAAAQaXNOZXh0T3JkZXJFcnJvcgMDBQAAABlpc05ld09yZGVyQXRGaXJzdFBvc2l0aW9uCQAAZwAAAAIFAAAADWN1cnJlbnRNYXhSb2kFAAAAA3JvaQcJAQAAABBpbnRlcm5hbFNlbGxCb25kAAAACAUAAAAKbmV3T3JkZXJJZAUAAAAJbmV4dE9yZGVyAAAAAAAAAAAABQAAAANyb2kFAAAABXByaWNlCAUAAAADcG10AAAABmFtb3VudAgFAAAAA2ludgAAAAZjYWxsZXIGAwUAAAAMaW5zdGFudE9yZGVyCQAAAgAAAAECAAAAMkluc3RhbnQgb3JkZXIgY291bGRuJ3QgYmUgYWRkZWQgaW50byB3YWl0aW5nIHF1ZXVlCQAETgAAAAIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAD2dldFByZXZPcmRlcktleQAAAAEFAAAACm5ld09yZGVySWQFAAAACXByZXZPcmRlcgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2V0TmV4dE9yZGVyS2V5AAAAAQUAAAAKbmV3T3JkZXJJZAUAAAAJbmV4dE9yZGVyCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAA9nZXROZXh0T3JkZXJLZXkAAAABBQAAAAlwcmV2T3JkZXIDCQAAAAAAAAIFAAAACXByZXZPcmRlcgIAAAAAAgAAAAAFAAAACm5ld09yZGVySWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAD2dldFByZXZPcmRlcktleQAAAAEFAAAACW5leHRPcmRlcgMJAAAAAAAAAgUAAAAJbmV4dE9yZGVyAgAAAAACAAAAAAUAAAAKbmV3T3JkZXJJZAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA1GaXJzdE9yZGVyS2V5AwMJAAAAAAAAAgUAAAAKZmlyc3RPcmRlcgIAAAAABgkAAAAAAAACBQAAAApmaXJzdE9yZGVyBQAAAAluZXh0T3JkZXIFAAAACm5ld09yZGVySWQFAAAACmZpcnN0T3JkZXIFAAAAA25pbAkBAAAACW9yZGVyRGF0YQAAAAcFAAAACm5ld09yZGVySWQIBQAAAANwbXQAAAAGYW1vdW50AAAAAAAAAAAABQAAAAVvd25lcgUAAAADTkVXBQAAAANyb2kFAAAABXByaWNlAQAAAA1jdXJ2ZUZ1bmN0aW9uAAAAAwAAAAR3UmF3AAAABHVSYXcAAAAFcHJpY2UEAAAAA0VYUAAAAAAAEDPEhAQAAAAPbnNidEN1cnZlUGFyYW1BCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMCAAAAEG5zYnRDdXJ2ZVBhcmFtX2EAAAAAAAAAAAMEAAAAD3dSZXNlcnZlc0luVXNkbgkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAAR3UmF3BQAAAAVwcmljZQQAAAAGYnJNdWx0CQAAawAAAAMFAAAAD3dSZXNlcnZlc0luVXNkbgUAAAAETVVMVAUAAAAEdVJhdwQAAAAJcG93ZXJNdWx0CQAAaAAAAAIFAAAAD25zYnRDdXJ2ZVBhcmFtQQkAAGUAAAACBQAAAAZick11bHQJAABoAAAAAgAAAAAAAAAAAQUAAAAETVVMVAQAAAAOZXhwSW5Qb3dlck11bHQJAABsAAAABgUAAAADRVhQBQAAAAlTQ0FMRU1VTFQFAAAACXBvd2VyTXVsdAUAAAAJU0NBTEVNVUxUBQAAAAlTQ0FMRU1VTFQFAAAABERPV04EAAAACmNvbnN0Q29lZmYJAABrAAAAAwUAAAAEdVJhdwUAAAAIUFJJQ0VMRVQJAABoAAAAAgUAAAAPbnNidEN1cnZlUGFyYW1BBQAAAAVwcmljZQQAAAAYZmluYWxSZXN1bHRJZlByaWNlSW5Vc2RuCQAAawAAAAMFAAAACmNvbnN0Q29lZmYFAAAABE1VTFQFAAAADmV4cEluUG93ZXJNdWx0BAAAAAtmaW5hbFJlc3VsdAkAAGsAAAADBQAAABhmaW5hbFJlc3VsdElmUHJpY2VJblVzZG4FAAAABXByaWNlBQAAAAhQUklDRUxFVAkABRgAAAAGBQAAAAtmaW5hbFJlc3VsdAUAAAAPd1Jlc2VydmVzSW5Vc2RuBQAAAAZick11bHQFAAAACXBvd2VyTXVsdAUAAAAOZXhwSW5Qb3dlck11bHQFAAAACmNvbnN0Q29lZmYBAAAABXRvU3RyAAAAAgAAAARuYW1lAAAAAWwJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAEbmFtZQIAAAANW2ZpbmFsUmVzdWx0PQkAAaQAAAABCAUAAAABbAAAAAJfMQIAAAAQd1Jlc2VydmVzSW5Vc2RuPQkAAaQAAAABCAUAAAABbAAAAAJfMgIAAAAIIGJyTXVsdD0JAAGkAAAAAQgFAAAAAWwAAAACXzMCAAAACyBwb3dlck11bHQ9CQABpAAAAAEIBQAAAAFsAAAAAl80AgAAABAgZXhwSW5Qb3dlck11bHQ9CQABpAAAAAEIBQAAAAFsAAAAAl81AgAAAAwgY29uc3RDb2VmZj0JAAGkAAAAAQgFAAAAAWwAAAACXzYCAAAAAV0BAAAADWJpZ0NvbXBsZXhpdHkAAAABAAAAAWkDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCQEAAAABIQAAAAEJAQAAAAlpc0RlZmluZWQAAAABCQAD7gAAAAEJAAJZAAAAAQIAAAAsUGRMdzVKSzVwcGZTRXF2bUZKdmNoZWpvckFremQ0QnJXTHZvRnd2TUd1NWsJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxhZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxzZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxkZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxmZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxnZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxoZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxqZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxrZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACxyZEx3NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACx0ZExxNUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACx0ZEx5NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACx0ZEx1NUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACx0ZExoNUpLZHBxZlNFcXZtRkp2Y2hlam9yQWt6ZDRCcldMdm9Gd3ZNR3U1awcJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAPuAAAAAQkAAlkAAAABAgAAACsxZEw0SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDJkTDI1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDNkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDRkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDVkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDZkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDdkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDhkTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDkxTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDkyTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDkzTDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+4AAAABCQACWQAAAAECAAAALDk0TDk1SktkcHFmU0Vxdm1GSnZjaGVqb3JBa3pkNEJyV0x2b0Z3dk1HdTVrBwAAAAUAAAABaQEAAAAQYnV5TnNidEluU3VycGx1cwAAAAAEAAAAA3BtdAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAAJcG10QW1vdW50CAUAAAADcG10AAAABmFtb3VudAQAAAAMb3duZXJBZGRyZXNzCAUAAAABaQAAAAZjYWxsZXIDBQAAAAlpc0Jsb2NrZWQJAAACAAAAAQIAAABZY29udHJhY3QgaXMgYmxvY2tlZCBieSBFTUVSR0VOQ1kgU0hVVERPV04gYWN0aW9ucyB1bnRpbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMDCQAAZgAAAAIJAABoAAAAAgAAAAAAAAAAAQUAAAAETVVMVAUAAAANY3VycmVudEJyTXVsdAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAFd1c2UgaW5zdGFudEJ1eU5zYnRPckZhaWwgb3IgYWRkQnV5Qm9uZE9yZGVyIG1ldGhvZHMgdG8gYnV5IG5zYnQgd2hlbiBCUiA8IDE6IGN1cnJlbnRCUj0JAAGkAAAAAQUAAAANY3VycmVudEJyTXVsdAIAAAABLwkAAaQAAAABBQAAAARNVUxUAwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkAAAIAAAABAgAAABJjYW4gdXNlIHdhdmVzIG9ubHkEAAAADW1pbkFtb3VudEZhaWwDCQAAZgAAAAIJAABoAAAAAgAAAAAAAAAAAQUAAAAHV0FWRUxFVAUAAAAJcG10QW1vdW50AwkAAAAAAAACCQEAAAANYmlnQ29tcGxleGl0eQAAAAEFAAAAAWkGBgcHAwUAAAANbWluQW1vdW50RmFpbAkAAAIAAAABAgAAACViaWcgY29tcGxleGl0eSArIG1pbiAxIHdhdmVzIGV4cGVjdGVkAwkAAGYAAAACCQAAaAAAAAIAAAAAAAAAAAEFAAAAB1dBVkVMRVQFAAAACXBtdEFtb3VudAkAAAIAAAABAgAAABRtaW4gMSB3YXZlcyBleHBlY3RlZAQAAAACZjAJAQAAAA1jdXJ2ZUZ1bmN0aW9uAAAAAwUAAAAHcmVzZXJ2ZQUAAAAObmV1dHJpbm9TdXBwbHkFAAAADGN1cnJlbnRQcmljZQQAAAACZjEJAQAAAA1jdXJ2ZUZ1bmN0aW9uAAAAAwkAAGQAAAACBQAAAAdyZXNlcnZlBQAAAAlwbXRBbW91bnQFAAAADm5ldXRyaW5vU3VwcGx5BQAAAAxjdXJyZW50UHJpY2UEAAAACm5zYnRBbW91bnQJAABlAAAAAggFAAAAAmYwAAAAAl8xCAUAAAACZjEAAAACXzEEAAAAEm5zYnQyV2F2ZXNQcmljZVJhdwkBAAAAFmNhbGNOc2J0MldhdmVzUHJpY2VSYXcAAAACBQAAAAlwbXRBbW91bnQFAAAACm5zYnRBbW91bnQEAAAAA3JvaQkAAGUAAAACCQAAawAAAAMJAQAAAA9nZXRSZXZlcnNlUHJpY2UAAAABBQAAABJuc2J0MldhdmVzUHJpY2VSYXcAAAAAAAAAAGQFAAAADGN1cnJlbnRQcmljZQAAAAAAAAAAZAkABE4AAAACCQEAAAAJb3JkZXJEYXRhAAAABwkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAAlwbXRBbW91bnQFAAAACXBtdEFtb3VudAkABCUAAAABBQAAAAxvd25lckFkZHJlc3MFAAAABkZJTExFRAUAAAADcm9pBQAAABJuc2J0MldhdmVzUHJpY2VSYXcJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAMb3duZXJBZGRyZXNzBQAAAApuc2J0QW1vdW50BQAAAAtib25kQXNzZXRJZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAABBuZXV0cmlub0NvbnRyYWN0BQAAAAlwbXRBbW91bnQFAAAABHVuaXQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAAIZGVidWdfZjAJAQAAAAV0b1N0cgAAAAICAAAAAmYwBQAAAAJmMAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAAhkZWJ1Z19mMQkBAAAABXRvU3RyAAAAAgIAAAACZjEFAAAAAmYxBQAAAANuaWwAAAABaQEAAAAUaW5zdGFudEJ1eU5zYnRPckZhaWwAAAABAAAADW5vTGVzc1RoZW5Sb2kEAAAAA3BtdAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAADcm9pBQAAAA1jdXJyZW50TWF4Um9pAwkAAGYAAAACBQAAAA1ub0xlc3NUaGVuUm9pBQAAAANyb2kJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAPQ3VycmVudCBtYXhSb2k9CQABpAAAAAEFAAAAA3JvaQIAAAAtIGlzIGxlc3MgdGhlbiBwYXNzZWQgcGFyYW1ldGVyIG5vTGVzc1RoZW5Sb2k9CQABpAAAAAEFAAAADW5vTGVzc1RoZW5Sb2kEAAAAFXByaWNlV2F2ZXNCeUJvbmRDZW50cwkBAAAADmdldFByaWNlRm9yUm9pAAAAAQUAAAADcm9pCQEAAAAXaW50ZXJuYWxBZGRCdXlCb25kT3JkZXIAAAAFBQAAAANyb2kJAQAAAA9nZXRSZXZlcnNlUHJpY2UAAAABBQAAABVwcmljZVdhdmVzQnlCb25kQ2VudHMCAAAAAAUAAAABaQYAAAABaQEAAAAPYWRkQnV5Qm9uZE9yZGVyAAAAAgAAAAVwcmljZQAAAAlwcmV2T3JkZXIEAAAAA3BtdAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAAVcHJpY2VXYXZlc0J5Qm9uZENlbnRzCQEAAAAPZ2V0UmV2ZXJzZVByaWNlAAAAAQUAAAAFcHJpY2UDCQAAZwAAAAIAAAAAAAAAAAAFAAAABXByaWNlCQAAAgAAAAECAAAAD3ByaWNlIGxlc3MgemVybwkBAAAAF2ludGVybmFsQWRkQnV5Qm9uZE9yZGVyAAAABQkAAGsAAAADCQAAZQAAAAIFAAAAFXByaWNlV2F2ZXNCeUJvbmRDZW50cwUAAAAMY3VycmVudFByaWNlAAAAAAAAAABkBQAAAAxjdXJyZW50UHJpY2UFAAAABXByaWNlBQAAAAlwcmV2T3JkZXIFAAAAAWkHAAAAAWkBAAAAC2NhbmNlbE9yZGVyAAAAAQAAAAdvcmRlcklkBAAAAAVvd25lcgkBAAAADWdldE9yZGVyT3duZXIAAAABBQAAAAdvcmRlcklkBAAAAAZhbW91bnQJAABlAAAAAgkBAAAADWdldE9yZGVyVG90YWwAAAABBQAAAAdvcmRlcklkCQEAAAATZ2V0T3JkZXJGaWxsZWRUb3RhbAAAAAEFAAAAB29yZGVySWQEAAAABmNhbGxlcgkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAACW5leHRPcmRlcgkBAAAADGdldE5leHRPcmRlcgAAAAEFAAAAB29yZGVySWQEAAAACXByZXZPcmRlcgkBAAAADGdldFByZXZPcmRlcgAAAAEFAAAAB29yZGVySWQDBQAAAAlpc0Jsb2NrZWQJAAACAAAAAQIAAABZY29udHJhY3QgaXMgYmxvY2tlZCBieSBFTUVSR0VOQ1kgU0hVVERPV04gYWN0aW9ucyB1bnRpbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMDCQEAAAACIT0AAAACBQAAAAVvd25lcgUAAAAGY2FsbGVyCQAAAgAAAAECAAAAEXBlcm1pc3Npb24gZGVuaWVkAwkBAAAAAiE9AAAAAgkBAAAADmdldE9yZGVyU3RhdHVzAAAAAQUAAAAHb3JkZXJJZAUAAAADTkVXCQAAAgAAAAECAAAAFGludmFsaWQgb3JkZXIgc3RhdHVzCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAADUZpcnN0T3JkZXJLZXkDCQAAAAAAAAIFAAAACmZpcnN0T3JkZXIFAAAAB29yZGVySWQFAAAACW5leHRPcmRlcgUAAAAKZmlyc3RPcmRlcgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2V0TmV4dE9yZGVyS2V5AAAAAQUAAAAJcHJldk9yZGVyBQAAAAluZXh0T3JkZXIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAD2dldFByZXZPcmRlcktleQAAAAEFAAAACW5leHRPcmRlcgUAAAAJcHJldk9yZGVyCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABFnZXRPcmRlclN0YXR1c0tleQAAAAEFAAAAB29yZGVySWQFAAAACENBTkNFTEVECQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAGYW1vdW50BQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAAIc2VsbEJvbmQAAAAAAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWWNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWwgcmVhY3RpdmF0aW9uIGJ5IGVtZXJnZW5jeSBvcmFjbGVzAwkAAAAAAAACBQAAAApmaXJzdE9yZGVyAgAAAAAJAAACAAAAAQIAAAAPZW1wdHkgb3JkZXJib29rBAAAAAluZXh0T3JkZXIJAQAAAAxnZXROZXh0T3JkZXIAAAABBQAAAApmaXJzdE9yZGVyBAAAAAtmaWxsZWRUb3RhbAkBAAAAE2dldE9yZGVyRmlsbGVkVG90YWwAAAABBQAAAApmaXJzdE9yZGVyBAAAAApvcmRlclByaWNlCQEAAAANZ2V0T3JkZXJQcmljZQAAAAEFAAAACmZpcnN0T3JkZXIEAAAAA3JvaQkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAEmdldFJvaUJ5T3JkZXJJZEtleQAAAAEFAAAACmZpcnN0T3JkZXIEAAAAD3BheW1lbnRXYXZlbGV0cwkBAAAADWdldE9yZGVyVG90YWwAAAABBQAAAApmaXJzdE9yZGVyBAAAABFvcmRlck93bmVyQWRkcmVzcwkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAAA1nZXRPcmRlck93bmVyAAAAAQUAAAAKZmlyc3RPcmRlcgkBAAAAEGludGVybmFsU2VsbEJvbmQAAAAIBQAAAApmaXJzdE9yZGVyBQAAAAluZXh0T3JkZXIFAAAAC2ZpbGxlZFRvdGFsBQAAAANyb2kFAAAACm9yZGVyUHJpY2UFAAAAD3BheW1lbnRXYXZlbGV0cwUAAAARb3JkZXJPd25lckFkZHJlc3MHAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAQAAAAQcHViS2V5QWRtaW5zTGlzdAkABEwAAAACAgAAACxHSmRMU2FMaXY1Szd4dWVqYWM4bWNSY0hveW8zZFByRVNydmt0RzNhNk1BUgkABEwAAAACAgAAACxGV1ZmZllyMkFMbUhNZWpabTNXcWVMejZTZHltM2dMRkd0Sm40S1R3eVU1eAkABEwAAAACAgAAACwzV2gyTGFXY2I1Z2c3SzJwUGNXM0VwNkVBdVJCellrQWdyZHB0NDNqVERGYQkABEwAAAACAgAAACw1V1JYRlNqd2NUYk5mS2NKczhacVhtU1NXWXNTVkpVdE12TXFaajVoSDROYwUAAAADbmlsBAAAAAVjb3VudAkAAGQAAAACCQAAZAAAAAIJAABkAAAAAgMJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAACQACWQAAAAEJAAGRAAAAAgUAAAAQcHViS2V5QWRtaW5zTGlzdAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAMJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAABCQACWQAAAAEJAAGRAAAAAgUAAAAQcHViS2V5QWRtaW5zTGlzdAAAAAAAAAAAAQAAAAAAAAAAAQAAAAAAAAAAAAMJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAACCQACWQAAAAEJAAGRAAAAAgUAAAAQcHViS2V5QWRtaW5zTGlzdAAAAAAAAAAAAgAAAAAAAAAAAQAAAAAAAAAAAAMJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAADCQACWQAAAAEJAAGRAAAAAgUAAAAQcHViS2V5QWRtaW5zTGlzdAAAAAAAAAAAAwAAAAAAAAAAAgAAAAAAAAAAAAkAAGcAAAACBQAAAAVjb3VudAAAAAAAAAAAAzcijko=", 4122, 4071, 3131}, + {`V5: 4tb8uA1TUQBzQ62WjzA75ryDK8Uh2mEXhKAp48qWw3X4`, "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARjYWxsAAAAAAQAAAAFbGVhc2UJAAREAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQIAAAAjM01lOEpGOGZodWdTU2EyS3g0dzd2MnRYMzc3c1RWdEtTVTUAAAAAAAX14QAEAAAAAmlkCQAEOQAAAAEFAAAABWxlYXNlCQAFFAAAAAIJAARMAAAAAgUAAAAFbGVhc2UJAARMAAAAAgkBAAAAC0JpbmFyeUVudHJ5AAAAAgIAAAAFbGVhc2UFAAAAAmlkBQAAAANuaWwFAAAAA25pbAAAAAFpAQAAABRDcmVhdGVBbmRDYW5jZWxMZWFzZQAAAAAEAAAABWxlYXNlCQAERAAAAAIJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAECAAAAIzNNZThKRjhmaHVnU1NhMkt4NHc3djJ0WDM3N3NUVnRLU1U1AAAAAAAF9eEABAAAAAJpZAkABDkAAAABBQAAAAVsZWFzZQQAAAAMY2FuY2VsUGFydGx5CQEAAAALTGVhc2VDYW5jZWwAAAABBQAAAAJpZAQAAAAGbGVhc2UyCQAERAAAAAIJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAECAAAAIzNNZThKRjhmaHVnU1NhMkt4NHc3djJ0WDM3N3NUVnRLU1U1AAAAAAAC+vCABAAAAANpZDIJAAQ5AAAAAQUAAAAGbGVhc2UyCQAFFAAAAAIJAARMAAAAAgUAAAAFbGVhc2UJAARMAAAAAgUAAAAMY2FuY2VsUGFydGx5CQAETAAAAAIFAAAABmxlYXNlMgkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAAVsZWFzZQUAAAADaWQyBQAAAANuaWwFAAAAA25pbAAAAAEAAAACdHgBAAAABnZlcmlmeQAAAAAJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAACAUAAAACdHgAAAAPc2VuZGVyUHVibGljS2V55bVbiA==", 226, 226, 210}, } { src, err := base64.StdEncoding.DecodeString(test.source) require.NoError(t, err, test.comment) diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index 96f44e7df..bba0be4ff 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -133,7 +133,7 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.Environment, assetID cryp } env.ChooseSizeCheck(tree.LibVersion) switch tree.LibVersion { - case 4: + case 4, 5: assetInfo, err := a.state.NewestFullAssetInfo(assetID) if err != nil { return nil, err diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 59febd218..0d81f63fa 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -92,7 +92,7 @@ func (tc *transactionChecker) checkScriptComplexity(tree *ride.Tree, estimation switch tree.LibVersion { case 1, 2: maxComplexity = 2000 - case 3, 4: + case 3, 4, 5: maxComplexity = 4000 } complexity := estimation.Verifier From 694605bff4c639a45d767ee195d9358cc7dbb9e7 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 19 Jan 2021 11:02:48 +0300 Subject: [PATCH 06/52] Fix lease id generation (#411) * Support for RIDE V5 added to transaction_checker * Fixed error in leasing ID generation --- pkg/proto/scripting.go | 4 ++-- pkg/proto/scripting_test.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index 96e7c19f2..35d28a547 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -196,9 +196,9 @@ func GenerateLeaseScriptActionID(recipient Recipient, amount int64, nonce int64, pos += rl copy(buf[pos:], txID[:]) pos += crypto.DigestSize - binary.BigEndian.PutUint64(buf[pos:], uint64(amount)) - pos += 8 binary.BigEndian.PutUint64(buf[pos:], uint64(nonce)) + pos += 8 + binary.BigEndian.PutUint64(buf[pos:], uint64(amount)) return crypto.MustFastHash(buf) } diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index 97b55bac2..5c637d53b 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -2,11 +2,12 @@ package proto import ( "fmt" - "github.com/wavesplatform/gowaves/pkg/crypto" "math" "strings" "testing" + "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" @@ -238,3 +239,31 @@ func TestActionsValidation(t *testing.T) { } } } + +func TestGenerateLeaseScriptActionID(t *testing.T) { + for _, test := range []struct { + recipient Recipient + amount int64 + nonce int64 + tx crypto.Digest + id string + }{ + {mustRecipientFromString("3Me8JF8fhugSSa2Kx4w7v2tX377sTVtKSU5"), 100000000, 0, crypto.MustDigestFromBase58("3JGcEMaASHc7zcJwpkuFTU3WScKtMU6KDQ5KFr53GQhV"), "HrvHDiegqPhcoKamTeTsNUcQiFot8D1KqyBirsEuCMG9"}, + {mustRecipientFromString("3Me8JF8fhugSSa2Kx4w7v2tX377sTVtKSU5"), 100000000, 0, crypto.MustDigestFromBase58("45R9UJrmCmZu1HtofbHyEmaFr2r1u5xXThGmESszVuFV"), "28yGDS82NrYBC1B4XTVYbwWpJyW7JPYTX7UtVQd1Prkw"}, + {mustRecipientFromString("3Me8JF8fhugSSa2Kx4w7v2tX377sTVtKSU5"), 50000000, 0, crypto.MustDigestFromBase58("45R9UJrmCmZu1HtofbHyEmaFr2r1u5xXThGmESszVuFV"), "GmqQBZPPAHb1u7mQJ8vVp89mcaii23jAyrbDfqYiGo6U"}, + {mustRecipientFromString("3Me8JF8fhugSSa2Kx4w7v2tX377sTVtKSU5"), 100000000, 0, crypto.MustDigestFromBase58("FBmMUrQ5GXun9LrGtHPcJYWSkkfToMReux14iSb2zf4c"), "5PmSmWMmCGh7zjf8SgvzmrUZrEKVeNL2wK12p7Y3Rezi"}, + {mustRecipientFromString("3Me8JF8fhugSSa2Kx4w7v2tX377sTVtKSU5"), 50000000, 0, crypto.MustDigestFromBase58("FBmMUrQ5GXun9LrGtHPcJYWSkkfToMReux14iSb2zf4c"), "2EgitLRfQmYckjmi16b2h3YFLBz7yKS877tb1TQRXR6Y"}, + } { + id := GenerateLeaseScriptActionID(test.recipient, test.amount, test.nonce, test.tx) + assert.Equal(t, test.id, id.String()) + } +} + +// This function is for tests only! Could produce invalid recipient. +func mustRecipientFromString(s string) Recipient { + r, err := recipientFromString(s) + if err != nil { + panic(err) + } + return r +} From 95bfd447435ce2922e1cc8d28a718ef8d34b0804 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Fri, 22 Jan 2021 13:42:19 +0300 Subject: [PATCH 07/52] Added the processing of Lease Action to Diff (#412) * Added processing of LeaseScriptAction * Added the processing of LeaseCancelScriptAction * Added initialization of lease map in diff * Added calculation of balance * Added getting lease information from store * Fixed search of balance in processing of lease actions * Added test for lease * Fixed effective balances in history * Deleted fmt * Fix finding balance * Fixed wrong assignment --- pkg/proto/lease.go | 8 ++ pkg/ride/diff_state.go | 143 +++++++++++++++++++-- pkg/ride/environment.go | 105 +++++++++++++-- pkg/ride/tree_evaluation_test.go | 211 +++++++++++++++++++++++++------ pkg/ride/types_moq_test.go | 49 +++++++ pkg/state/state.go | 14 ++ pkg/types/types.go | 2 +- 7 files changed, 467 insertions(+), 65 deletions(-) create mode 100644 pkg/proto/lease.go diff --git a/pkg/proto/lease.go b/pkg/proto/lease.go new file mode 100644 index 000000000..33bebe711 --- /dev/null +++ b/pkg/proto/lease.go @@ -0,0 +1,8 @@ +package proto + +type LeaseInfo struct { + IsActive bool + LeaseAmount uint64 + Recipient Address + Sender Address +} diff --git a/pkg/ride/diff_state.go b/pkg/ride/diff_state.go index 24b923047..6f0b01e9b 100644 --- a/pkg/ride/diff_state.go +++ b/pkg/ride/diff_state.go @@ -15,9 +15,18 @@ type diffDataEntries struct { diffDDelete map[string]proto.DeleteDataEntry } +type lease struct { + Recipient proto.Recipient + leasedAmount int64 + Sender proto.Recipient +} + type diffBalance struct { - assetID crypto.Digest - amount int64 + assetID crypto.Digest + regular int64 + leaseIn int64 + leaseOut int64 + effectiveHistory []int64 } type diffSponsorship struct { @@ -42,15 +51,16 @@ type diffOldAssetInfo struct { type diffState struct { state types.SmartState dataEntries diffDataEntries - balances map[string]diffBalance // map[address.String() + Digest.String()] or map[address.String()] only + balances map[string]diffBalance // map[address.String() + Digest.String()] or map[address.String()] sponsorships map[string]diffSponsorship // map[Digest.String()] newAssetsInfo map[string]diffNewAssetInfo // map[assetID.String()] oldAssetsInfo map[string]diffOldAssetInfo // map[assetID.String()] + leases map[string]lease // map[leaseID.String()] } func (diffSt *diffState) addBalanceTo(searchAddress string, amount int64) { oldDiffBalance := diffSt.balances[searchAddress] - oldDiffBalance.amount += amount + oldDiffBalance.regular += amount diffSt.balances[searchAddress] = oldDiffBalance } @@ -69,6 +79,98 @@ func (diffSt *diffState) burnNewAsset(assetID crypto.Digest, quantity int64) { diffSt.newAssetsInfo[assetID.String()] = asset } +func (diffSt *diffState) createNewWavesBalance(account proto.Recipient) (*diffBalance, string) { + waves := crypto.Digest{} + balance := diffBalance{assetID: waves} + diffSt.balances[account.Address.String()+waves.String()] = balance + return &balance, account.Address.String() + waves.String() +} + +func (diffSt *diffState) cancelLease(searchLease lease, senderSearchAddress, recipientSearchAddress string) { + oldDiffBalanceRecipient := diffSt.balances[recipientSearchAddress] + oldDiffBalanceRecipient.leaseIn -= searchLease.leasedAmount + diffSt.balances[recipientSearchAddress] = oldDiffBalanceRecipient + + oldDiffBalanceSender := diffSt.balances[senderSearchAddress] + oldDiffBalanceSender.leaseOut -= searchLease.leasedAmount + diffSt.balances[senderSearchAddress] = oldDiffBalanceSender +} + +func (diffSt *diffState) findMinGenerating(effectiveHistory []int64, generatingFromState int64) int64 { + min := generatingFromState + for _, value := range effectiveHistory { + if value < min { + min = value + } + } + return min +} + +func (diffSt *diffState) addEffectiveToHistory(searchAddress string, effective int64) error { + oldDiffBalance, ok := diffSt.balances[searchAddress] + if !ok { + return errors.Errorf("Cannot find balance to add effective to history") + } + oldDiffBalance.effectiveHistory = append(oldDiffBalance.effectiveHistory, effective) + diffSt.balances[searchAddress] = oldDiffBalance + return nil +} + +func (diffSt *diffState) addNewLease(recipient proto.Recipient, sender proto.Recipient, leasedAmount int64, leaseID crypto.Digest) { + lease := lease{Recipient: recipient, Sender: sender, leasedAmount: leasedAmount} + diffSt.leases[leaseID.String()] = lease +} + +func (diffSt *diffState) addLeaseInTo(searchAddress string, leasedAmount int64) { + oldDiffBalance := diffSt.balances[searchAddress] + oldDiffBalance.leaseIn += leasedAmount + + diffSt.balances[searchAddress] = oldDiffBalance +} + +func (diffSt *diffState) changeLeaseIn(searchBalance *diffBalance, searchAddress string, leasedAmount int64, account proto.Recipient) error { + if searchBalance != nil { + diffSt.addLeaseInTo(searchAddress, leasedAmount) + return nil + } + address, err := diffSt.state.NewestRecipientToAddress(account) + if err != nil { + return err + } + + var balance diffBalance + balance.assetID = crypto.Digest{} + balance.leaseIn = leasedAmount + + diffSt.balances[address.String()+balance.assetID.String()] = balance + return nil +} + +func (diffSt *diffState) addLeaseOutTo(searchAddress string, leasedAmount int64) { + oldDiffBalance := diffSt.balances[searchAddress] + oldDiffBalance.leaseOut += leasedAmount + diffSt.balances[searchAddress] = oldDiffBalance +} + +func (diffSt *diffState) changeLeaseOut(searchBalance *diffBalance, searchAddress string, leasedAmount int64, account proto.Recipient) error { + if searchBalance != nil { + diffSt.addLeaseOutTo(searchAddress, leasedAmount) + return nil + } + + address, err := diffSt.state.NewestRecipientToAddress(account) + if err != nil { + return err + } + + var balance diffBalance + balance.assetID = crypto.Digest{} + balance.leaseOut = leasedAmount + + diffSt.balances[address.String()+balance.assetID.String()] = balance + return nil +} + func (diffSt *diffState) changeBalance(searchBalance *diffBalance, searchAddress string, amount int64, assetID crypto.Digest, account proto.Recipient) error { if searchBalance != nil { diffSt.addBalanceTo(searchAddress, amount) @@ -82,12 +184,34 @@ func (diffSt *diffState) changeBalance(searchBalance *diffBalance, searchAddress var balance diffBalance balance.assetID = assetID - balance.amount = amount + balance.regular = amount diffSt.balances[address.String()+assetID.String()] = balance return nil } +func (diffSt *diffState) findLeaseByIDForCancel(leaseID crypto.Digest) (*lease, error) { + if lease, ok := diffSt.leases[leaseID.String()]; ok { + return &lease, nil + } + leaseFromStore, err := diffSt.state.NewestLeasingInfo(leaseID, false) + if err != nil { + return nil, err + } + if leaseFromStore != nil { + if !leaseFromStore.IsActive { + return nil, nil + } + lease := lease{ + Recipient: proto.NewRecipientFromAddress(leaseFromStore.Recipient), + Sender: proto.NewRecipientFromAddress(leaseFromStore.Sender), + leasedAmount: int64(leaseFromStore.LeaseAmount), + } + return &lease, nil + } + return nil, nil +} + func (diffSt *diffState) findIntFromDataEntryByKey(key string, address string) *proto.IntegerDataEntry { if integerEntry, ok := diffSt.dataEntries.diffInteger[key+address]; ok { return &integerEntry @@ -129,12 +253,9 @@ func (diffSt *diffState) findBalance(recipient proto.Recipient, asset []byte) (* return nil, "", errors.Errorf("cannot get address from recipient") } if asset == nil { - if balance, ok := diffSt.balances[address.String()]; ok { - return &balance, address.String(), nil - } - emptyAsset := crypto.Digest{} - if balance, ok := diffSt.balances[address.String()+emptyAsset.String()]; ok { - return &balance, address.String(), nil + waves := crypto.Digest{} + if balance, ok := diffSt.balances[address.String()+waves.String()]; ok { + return &balance, address.String() + waves.String(), nil } return nil, "", nil } diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 6a042507f..45b0a1482 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -11,6 +11,10 @@ func (wrappedSt *wrappedState) AddingBlockHeight() (uint64, error) { return wrappedSt.diff.state.AddingBlockHeight() } +func (wrappedSt *wrappedState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + return wrappedSt.diff.state.NewestLeasingInfo(id, filter) +} + func (wrappedSt *wrappedState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { return wrappedSt.diff.state.NewestScriptPKByAddr(addr, filter) } @@ -41,7 +45,7 @@ func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, ass return 0, err } if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount + resBalance := int64(balance) + balanceDiff.regular return uint64(resBalance), nil } @@ -54,24 +58,38 @@ func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) ( return nil, err } - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, nil) if err != nil { return nil, err } if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance.Regular) - resGenerating := wavesBalanceDiff.amount + int64(balance.Generating) - resAvailable := wavesBalanceDiff.amount + int64(balance.Available) - resEffective := wavesBalanceDiff.amount + int64(balance.Effective) + resRegular := wavesBalanceDiff.regular + int64(balance.Regular) + resAvailable := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut) + int64(balance.Available) + resEffective := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut + wavesBalanceDiff.leaseIn) + int64(balance.Effective) + resLeaseIn := wavesBalanceDiff.leaseIn + int64(balance.LeaseIn) + resLeaseOut := wavesBalanceDiff.leaseOut + int64(balance.LeaseOut) - return &proto.FullWavesBalance{Regular: uint64(resRegular), + err := wrappedSt.diff.addEffectiveToHistory(searchAddress, resEffective) + if err != nil { + return nil, err + } + + resGenerating := wrappedSt.diff.findMinGenerating(wrappedSt.diff.balances[searchAddress].effectiveHistory, int64(balance.Generating)) + + return &proto.FullWavesBalance{ + Regular: uint64(resRegular), Generating: uint64(resGenerating), Available: uint64(resAvailable), Effective: uint64(resEffective), - LeaseIn: balance.LeaseIn, - LeaseOut: balance.LeaseOut}, nil + LeaseIn: uint64(resLeaseIn), + LeaseOut: uint64(resLeaseOut)}, nil } + _, searchAddr := wrappedSt.diff.createNewWavesBalance(account) + err = wrappedSt.diff.addEffectiveToHistory(searchAddr, int64(balance.Effective)) + if err != nil { + return nil, err + } return balance, nil } @@ -458,9 +476,73 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro } res.Sender = senderPK + case *proto.LeaseScriptAction: + senderAddress := proto.Address(wrappedSt.envThis) + + recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, nil) + if err != nil { + return nil, err + } + err = wrappedSt.diff.changeLeaseIn(recipientSearchBalance, recipientSearchAddress, res.Amount, res.Recipient) + if err != nil { + return nil, err + } + + senderAccount := proto.NewRecipientFromAddress(senderAddress) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, nil) + if err != nil { + return nil, err + } + + err = wrappedSt.diff.changeLeaseOut(senderSearchBalance, senderSearchAddr, res.Amount, senderAccount) + if err != nil { + return nil, err + } + + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(senderAddress, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + + wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) + + res.Sender = pk + case *proto.LeaseCancelScriptAction: + + searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) + if err != nil { + return nil, errors.Errorf("failed to find lease by leaseID") + } + if searchLease == nil { + return nil, errors.Errorf("there is no lease to cancel") + } + + recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, nil) + if err != nil { + return nil, err + } + if recipientBalance == nil { + _, recipientSearchAddress = wrappedSt.diff.createNewWavesBalance(searchLease.Recipient) + } + + senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, nil) + if err != nil { + return nil, err + } + if senderBalance == nil { + _, senderSearchAddress = wrappedSt.diff.createNewWavesBalance(searchLease.Sender) + } + + wrappedSt.diff.cancelLease(*searchLease, senderSearchAddress, recipientSearchAddress) + + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + + res.Sender = pk default: } - } return actions, nil } @@ -498,8 +580,9 @@ func newWrappedState(state types.SmartState, envThis rideType, envScheme proto.S sponsorships := map[string]diffSponsorship{} newAssetInfo := map[string]diffNewAssetInfo{} oldAssetInfo := map[string]diffOldAssetInfo{} + leases := map[string]lease{} - diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo} + diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo, leases: leases} wrappedSt := wrappedState{diff: *diffSt, envThis: envThis.(rideAddress)} return &wrappedSt } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 591d8f39e..91c456e7c 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -819,8 +819,9 @@ func initWrappedState(state types.SmartState, envThis rideAddress) *wrappedState sponsorships := map[string]diffSponsorship{} newAssetInfo := map[string]diffNewAssetInfo{} oldAssetInfo := map[string]diffOldAssetInfo{} + leases := map[string]lease{} - diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo} + diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo, leases: leases} wrappedSt := wrappedState{diff: *diffSt, envThis: envThis} return &wrappedSt } @@ -1022,13 +1023,79 @@ func smartStateDappFromDapp() types.SmartState { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = senderPK + case *proto.LeaseScriptAction: + senderAddress := proto.Address(wrappedSt.envThis) + recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, nil) + if err != nil { + return nil, err + } + err = wrappedSt.diff.changeLeaseIn(recipientSearchBalance, recipientSearchAddress, res.Amount, res.Recipient) + if err != nil { + return nil, err + } + + senderAccount := proto.NewRecipientFromAddress(senderAddress) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, nil) + if err != nil { + return nil, err + } + + err = wrappedSt.diff.changeLeaseOut(senderSearchBalance, senderSearchAddr, res.Amount, senderAccount) + if err != nil { + return nil, err + } + + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(senderAddress, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + + wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) + + res.Sender = pk + case *proto.LeaseCancelScriptAction: + + searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) + if err != nil { + return nil, errors.Errorf("failed to find lease by leaseID") + } + if searchLease == nil { + return nil, errors.Errorf("there is no lease to cancel") + } + recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, nil) + if err != nil { + return nil, err + } + if recipientBalance == nil { + return nil, errors.Errorf("there is no balance to cancel lease") + } + + senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, nil) + if err != nil { + return nil, err + } + if senderBalance == nil { + return nil, errors.Errorf("there is no balance to cancel lease") + } + + wrappedSt.diff.cancelLease(*searchLease, senderSearchAddress, recipientSearchAddress) + + pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + + res.Sender = pk default: } } return actions, nil }, + NewestLeasingInfoFunc: func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + return nil, nil + }, GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { var script proto.Script var err error @@ -1068,7 +1135,7 @@ func smartStateDappFromDapp() types.SmartState { return 0, err } if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.amount + resBalance := int64(balance) + balanceDiff.regular return uint64(resBalance), nil } @@ -1077,25 +1144,42 @@ func smartStateDappFromDapp() types.SmartState { NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { balance := 0 - wavesBalanceDiff, _, err := wrappedSt.diff.findBalance(account, nil) + wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, nil) if err != nil { return nil, err } if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.amount + int64(balance) - resGenerating := wavesBalanceDiff.amount + int64(balance) - resAvailable := wavesBalanceDiff.amount + int64(balance) - resEffective := wavesBalanceDiff.amount + int64(balance) + resRegular := wavesBalanceDiff.regular + int64(balance) + resAvailable := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut) + int64(balance) + resEffective := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut + wavesBalanceDiff.leaseIn) + int64(balance) + resLeaseIn := wavesBalanceDiff.leaseIn + int64(balance) + resLeaseOut := wavesBalanceDiff.leaseOut + int64(balance) + + err := wrappedSt.diff.addEffectiveToHistory(searchAddress, resEffective) + if err != nil { + return nil, err + } + + resGenerating := wrappedSt.diff.findMinGenerating(wrappedSt.diff.balances[searchAddress].effectiveHistory, int64(balance)) return &proto.FullWavesBalance{ Regular: uint64(resRegular), Generating: uint64(resGenerating), Available: uint64(resAvailable), Effective: uint64(resEffective), - LeaseIn: 0, - LeaseOut: 0}, nil + LeaseIn: uint64(resLeaseIn), + LeaseOut: uint64(resLeaseOut)}, nil } + waves := crypto.Digest{} + err = wrappedSt.diff.changeBalance(nil, "", 0, waves, account) + if err != nil { + return nil, err + } + err = wrappedSt.diff.addEffectiveToHistory(account.Address.String()+waves.String(), int64(balance)) + if err != nil { + return nil, err + } return &proto.FullWavesBalance{ Regular: 0, Generating: 0, @@ -1367,27 +1451,28 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { */ /* script 2 - {-# STDLIB_VERSION 5 #-} - {-# CONTENT_TYPE DAPP #-} - {-# SCRIPT_TYPE ACCOUNT #-} + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} - @Callable(i) - func testActions() = { - let asset = Issue("CatCoin", "", 1, 0, true, unit, 0) - let assetId = asset.calculateAssetId() - - ([ - ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 1, unit), - BinaryEntry("bin", base58''), - BooleanEntry("bool", true), - IntegerEntry("int", 1), - StringEntry("str", ""), - DeleteEntry("str"), - asset, - Reissue(assetId, 10, false), - Burn(assetId, 5) - ], 17) - } + @Callable(i) + func testActions() = { + let asset = Issue("CatCoin", "", 1, 0, true, unit, 0) + let assetId = asset.calculateAssetId() + + ([ + ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 1, unit), + Lease(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 10), + BinaryEntry("bin", base58''), + BooleanEntry("bool", true), + IntegerEntry("int", 1), + StringEntry("str", ""), + DeleteEntry("str"), + asset, + Reissue(assetId, 10, false), + Burn(assetId, 5) + ], 17) + } */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") @@ -1435,7 +1520,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { } firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" - secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAANzdHICAAAAAAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABAgAAAANzdHIJAARMAAAAAgUAAAAFYXNzZXQJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAdhc3NldElkAAAAAAAAAAAKBwkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAAB2Fzc2V0SWQAAAAAAAAAAAUFAAAAA25pbAAAAAAAAAAAEQAAAAD8KQzH" + secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAoJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQIAAAADc3RyCQAETAAAAAIFAAAABWFzc2V0CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAHYXNzZXRJZAAAAAAAAAAACgcJAARMAAAAAgkBAAAABEJ1cm4AAAACBQAAAAdhc3NldElkAAAAAAAAAAAFBQAAAANuaWwAAAAAAAAAABEAAAAAAOn+Sg==" id = bytes.Repeat([]byte{0}, 32) @@ -1464,6 +1549,10 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { {Sender: addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } + expectedLeaseWrites := []*proto.LeaseScriptAction{ + {Sender: addressCallablePK, Recipient: recipient, Amount: 10, Nonce: 0}, + } + smartState := smartStateDappFromDapp invCount = 0 @@ -1481,6 +1570,11 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { expectedReissueWrites[0].AssetID = expectedIssueWrites[0].ID expectedBurnWrites[0].AssetID = expectedIssueWrites[0].ID + // start balance + bal := wrappedSt.diff.balances[addr.String()+crypto.Digest{}.String()] + bal.regular = 2468 + wrappedSt.diff.balances[addr.String()+crypto.Digest{}.String()] = bal + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -1498,6 +1592,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) require.NoError(t, err) + expectedLeaseWrites[0].ID = sr.Leases[0].ID assetExp := proto.OptionalAsset{} expectedActionsResult := &proto.ScriptResult{ @@ -1507,17 +1602,41 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { Reissues: expectedReissueWrites, Burns: expectedBurnWrites, Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), + Leases: expectedLeaseWrites, LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } assert.Equal(t, expectedActionsResult, sr) + fullBalanceExpected := &proto.FullWavesBalance{ + Regular: 1, + Generating: 0, + Available: 1, + Effective: 11, + LeaseIn: 10, + LeaseOut: 0, + } + fullBalance, err := smartState().NewestFullWavesBalance(recipient) + require.NoError(t, err) + assert.Equal(t, fullBalance, fullBalanceExpected) + + fullBalanceCallableExpected := &proto.FullWavesBalance{ + Regular: 2467, + Generating: 0, + Available: 2457, + Effective: 2457, + LeaseIn: 0, + LeaseOut: 10, + } + fullBalanceCallable, err := smartState().NewestFullWavesBalance(recipientCallable) + require.NoError(t, err) + assert.Equal(t, fullBalanceCallable, fullBalanceCallableExpected) + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balance := diffBalance{amount: -2467, assetID: assetExp.ID} + balance := diffBalance{regular: 1, leaseIn: 10, assetID: assetExp.ID, effectiveHistory: []int64{11}} expectedDiffResult.balances[addr.String()+assetExp.ID.String()] = balance - balanceCallable := diffBalance{amount: 2467, assetID: assetExp.ID} + balanceCallable := diffBalance{regular: 2467, leaseOut: 10, assetID: assetExp.ID, effectiveHistory: []int64{2457}} expectedDiffResult.balances[addressCallable.String()+assetExp.ID.String()] = balanceCallable intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} @@ -1538,11 +1657,15 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { newAsset := diffNewAssetInfo{dAppIssuer: addressCallable, name: "CatCoin", description: "", quantity: 6, decimals: 0, reissuable: false, script: nil, nonce: 0} expectedDiffResult.newAssetsInfo[assetIDIssue.String()] = newAsset + lease := lease{Recipient: recipient, Sender: recipientCallable, leasedAmount: 10} + expectedDiffResult.leases[expectedLeaseWrites[0].ID.String()] = lease + assert.Equal(t, expectedDiffResult.newAssetsInfo, wrappedSt.diff.newAssetsInfo) assert.Equal(t, expectedDiffResult.oldAssetsInfo, wrappedSt.diff.oldAssetsInfo) assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) assert.Equal(t, expectedDiffResult.sponsorships, wrappedSt.diff.sponsorships) + assert.Equal(t, expectedDiffResult.leases, wrappedSt.diff.leases) tearDownDappFromDapp() } @@ -1824,14 +1947,15 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -14} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 14} + balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -14, effectiveHistory: []int64{0, -14}} + balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 14, effectiveHistory: []int64{0, 14}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() } @@ -2000,14 +2124,15 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -29, effectiveHistory: []int64{0, -14, -29}} + balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 29, effectiveHistory: []int64{0, 14, 29}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() } @@ -2174,8 +2299,8 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -16} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 16} + balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -16, effectiveHistory: []int64{0, -16}} + balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 16, effectiveHistory: []int64{0, 16}} intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 @@ -2184,6 +2309,7 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() } @@ -2348,14 +2474,15 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, amount: -29} - balanceCallable := diffBalance{assetID: crypto.Digest{}, amount: 29} + balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -13, effectiveHistory: []int64{0, -13}} + balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 13, effectiveHistory: []int64{0, 13}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() } diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index 4e5279c24..fd6cde6c5 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -59,6 +59,9 @@ var _ types.SmartState = &MockSmartState{} // NewestHeaderByHeightFunc: func(height uint64) (*proto.BlockHeader, error) { // panic("mock out the NewestHeaderByHeight method") // }, +// NewestLeasingInfoFunc: func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { +// panic("mock out the NewestLeasingInfo method") +// }, // NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { // panic("mock out the NewestRecipientToAddress method") // }, @@ -129,6 +132,9 @@ type MockSmartState struct { // NewestHeaderByHeightFunc mocks the NewestHeaderByHeight method. NewestHeaderByHeightFunc func(height uint64) (*proto.BlockHeader, error) + // NewestLeasingInfoFunc mocks the NewestLeasingInfo method. + NewestLeasingInfoFunc func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) + // NewestRecipientToAddressFunc mocks the NewestRecipientToAddress method. NewestRecipientToAddressFunc func(recipient proto.Recipient) (*proto.Address, error) @@ -220,6 +226,13 @@ type MockSmartState struct { // Height is the height argument value. Height uint64 } + // NewestLeasingInfo holds details about calls to the NewestLeasingInfo method. + NewestLeasingInfo []struct { + // ID is the id argument value. + ID crypto.Digest + // Filter is the filter argument value. + Filter bool + } // NewestRecipientToAddress holds details about calls to the NewestRecipientToAddress method. NewestRecipientToAddress []struct { // Recipient is the recipient argument value. @@ -284,6 +297,7 @@ type MockSmartState struct { lockNewestFullAssetInfo sync.RWMutex lockNewestFullWavesBalance sync.RWMutex lockNewestHeaderByHeight sync.RWMutex + lockNewestLeasingInfo sync.RWMutex lockNewestRecipientToAddress sync.RWMutex lockNewestScriptPKByAddr sync.RWMutex lockNewestTransactionByID sync.RWMutex @@ -695,6 +709,41 @@ func (mock *MockSmartState) NewestHeaderByHeightCalls() []struct { return calls } +// NewestLeasingInfo calls NewestLeasingInfoFunc. +func (mock *MockSmartState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + if mock.NewestLeasingInfoFunc == nil { + panic("MockSmartState.NewestLeasingInfoFunc: method is nil but SmartState.NewestLeasingInfo was just called") + } + callInfo := struct { + ID crypto.Digest + Filter bool + }{ + ID: id, + Filter: filter, + } + mock.lockNewestLeasingInfo.Lock() + mock.calls.NewestLeasingInfo = append(mock.calls.NewestLeasingInfo, callInfo) + mock.lockNewestLeasingInfo.Unlock() + return mock.NewestLeasingInfoFunc(id, filter) +} + +// NewestLeasingInfoCalls gets all the calls that were made to NewestLeasingInfo. +// Check the length with: +// len(mockedSmartState.NewestLeasingInfoCalls()) +func (mock *MockSmartState) NewestLeasingInfoCalls() []struct { + ID crypto.Digest + Filter bool +} { + var calls []struct { + ID crypto.Digest + Filter bool + } + mock.lockNewestLeasingInfo.RLock() + calls = mock.calls.NewestLeasingInfo + mock.lockNewestLeasingInfo.RUnlock() + return calls +} + // NewestRecipientToAddress calls NewestRecipientToAddressFunc. func (mock *MockSmartState) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { if mock.NewestRecipientToAddressFunc == nil { diff --git a/pkg/state/state.go b/pkg/state/state.go index 2e537b6a6..50aa6da99 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -680,6 +680,20 @@ func (s *stateManager) BlockByHeight(height uint64) (*proto.Block, error) { return s.Block(blockID) } +func (s *stateManager) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + leaseFromStore, err := s.stor.leases.newestLeasingInfo(id, filter) + if err != nil { + return nil, err + } + leaseInfo := proto.LeaseInfo{ + Sender: leaseFromStore.sender, + Recipient: leaseFromStore.recipient, + IsActive: leaseFromStore.isActive, + LeaseAmount: leaseFromStore.leaseAmount, + } + return &leaseInfo, nil +} + func (s *stateManager) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { return s.stor.scriptsStorage.NewestScriptPKByAddr(addr, filter) } diff --git a/pkg/types/types.go b/pkg/types/types.go index 678cb8c05..f282dbb98 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -42,7 +42,7 @@ type SmartState interface { GetByteTree(recipient proto.Recipient) (proto.Script, error) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) - + NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) // NewestAccountBalance retrieves balance of address in specific currency, asset is asset's ID. // nil asset = Waves. NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) From 16d58ecec507ba33029a18950e01bce2305169a5 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 25 Jan 2021 11:20:51 +0300 Subject: [PATCH 08/52] Fixed the sending of schema (#414) --- pkg/ride/environment.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 45b0a1482..11eeaa4fd 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -567,7 +567,7 @@ type Environment struct { invokeCount uint64 } -func newWrappedState(state types.SmartState, envThis rideType, envScheme proto.Scheme) types.SmartState { +func newWrappedState(state types.SmartState, envThis rideType, scheme proto.Scheme) types.SmartState { var dataEntries diffDataEntries dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} @@ -583,7 +583,7 @@ func newWrappedState(state types.SmartState, envThis rideType, envScheme proto.S leases := map[string]lease{} diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo, leases: leases} - wrappedSt := wrappedState{diff: *diffSt, envThis: envThis.(rideAddress)} + wrappedSt := wrappedState{diff: *diffSt, envThis: envThis.(rideAddress), envScheme: scheme} return &wrappedSt } From 6e5b8b73c5e10364cb136dcc57216dc0715b1070 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 26 Jan 2021 09:23:55 +0300 Subject: [PATCH 09/52] Added payments to version 5 (#415) --- pkg/ride/converters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index a26f0d25c..8fb579fda 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -933,7 +933,7 @@ func invocationToObject(v int, scheme byte, tx *proto.InvokeScriptWithProofs) (r r["caller"] = rideAddress(sender) r["callerPublicKey"] = rideBytes(common.Dup(tx.SenderPK.Bytes())) switch v { - case 4: + case 4, 5: payments := make(rideList, len(tx.Payments)) for i, p := range tx.Payments { payments[i] = attachedPaymentToObject(p) From 7b55ff021a26d4d8c88f20cdfc0cf591b825d713 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Wed, 27 Jan 2021 10:42:43 +0300 Subject: [PATCH 10/52] payments recovering by the end of invocation (#416) --- pkg/ride/functions_proto.go | 13 ++- pkg/ride/tree_evaluation_test.go | 164 ++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 6 deletions(-) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 6d924de05..0ff6b339e 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -48,10 +48,15 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { } var attachedPayments proto.ScriptPayments - payments := args[3].(rideList) - invocationParam := env.invocation() + oldInvocationParam := env.invocation() + + invocationParam := make(rideObject) + for key, value := range oldInvocationParam { + invocationParam[key] = value + } + invocationParam["caller"] = callerAddress callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(callerAddress), false) if err != nil { @@ -112,10 +117,12 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { } err = env.smartAppendActions(res.ScriptActions()) - env.setNewDAppAddress(proto.Address(callerAddress)) if err != nil { return nil, err } + env.setNewDAppAddress(proto.Address(callerAddress)) + + env.SetInvocation(oldInvocationParam) if res.UserResult() == nil { return rideUnit{}, nil diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 91c456e7c..1c1d0511c 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -1355,6 +1355,7 @@ var envActions []proto.ScriptAction var invCount uint64 var thisAddress proto.Address var tx *proto.InvokeScriptWithProofs +var inv rideObject var id []byte var envDappFromDapp = &MockRideEnvironment{ @@ -1364,7 +1365,8 @@ var envDappFromDapp = &MockRideEnvironment{ appendActionsFunc: func(actions []proto.ScriptAction) { envActions = append(envActions, actions...) }, - SetInvocationFunc: func(inv rideObject) { + SetInvocationFunc: func(invocation rideObject) { + inv = invocation }, smartAppendActionsFunc: func(actions []proto.ScriptAction) error { modifiedActions, err := smartStateDappFromDapp().ApplyToState(actions) @@ -1401,8 +1403,7 @@ var envDappFromDapp = &MockRideEnvironment{ return obj }, invocationFunc: func() rideObject { - obj, _ := invocationToObject(4, proto.MainNetScheme, tx) - return obj + return inv }, invCountFunc: func() uint64 { return invCount @@ -1519,6 +1520,8 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAoJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQIAAAADc3RyCQAETAAAAAIFAAAABWFzc2V0CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAHYXNzZXRJZAAAAAAAAAAACgcJAARMAAAAAgkBAAAABEJ1cm4AAAACBQAAAAdhc3NldElkAAAAAAAAAAAFBQAAAANuaWwAAAAAAAAAABEAAAAAAOn+Sg==" @@ -1736,6 +1739,8 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAANiYXIAAAAACQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQUAAAADbmlsAgAAAAZyZXR1cm4AAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANiYXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyAgAAAAZyZXR1cm4EAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIFAAAABHRoaXMCAAAAA2JhcgMJAAAAAAAAAgUAAAAEZGF0YQAAAAAAAAAAAQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAADz23Fz" id = bytes.Repeat([]byte{0}, 32) @@ -1889,6 +1894,8 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAALVWK3g==" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" @@ -2064,6 +2071,8 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" @@ -2239,6 +2248,7 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { Fee: 900000, Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAACP+w2w=" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" @@ -2414,6 +2424,7 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { Fee: 900000, Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFU+nlLLlJlc8+xTjSzsqlWzv76DyZcRlcJAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAADKkWnw==" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAADBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACzZnMp" @@ -2539,6 +2550,7 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { Fee: 900000, Timestamp: 1564703444249, } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" @@ -2591,6 +2603,152 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { tearDownDappFromDapp() } +func TestInvokeDAppFromDAppPayments(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let exchangeRate = 5 + + @Callable(i) + func test() = if ((i.payments[0].assetId != unit)) + then throw("unexpected asset") + else { + let res = Invoke(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), "testActions",[(i.payments[0].amount * exchangeRate)], nil) + if res == 17 + then + [ + ScriptTransfer(i.caller, (i.payments[0].amount * exchangeRate), unit) + ] + else + throw("Bad returned value") + } */ + + /* script 2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func testActions(a: Int) = { + ([ + IntegerEntry("int", 1) + ], 17) + } */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + + addressCallable, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + require.NoError(t, err) + + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: addrPK, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 500, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVcjs60SXJOkyuw5/k9G1s1WTS37EPtjmHoCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCQAAaAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAAMZXhjaGFuZ2VSYXRlBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlAAAAAJWUUMQ=" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgEBAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAABAAAAAWEJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADaW50AAAAAAAAAAABBQAAAANuaWwAAAAAAAAAABEAAAAAPWJMug==" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: addressCallablePK}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: crypto.PublicKey{}, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + } + + smartState := smartStateDappFromDapp + + invCount = 0 + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + addrSender := proto.Address(inv["caller"].(rideAddress)) + expectedTransferWrites[0].Recipient = proto.NewRecipientFromAddress(addrSender) + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + + intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + + tearDownDappFromDapp() +} + func TestMatchOverwrite(t *testing.T) { /* {-# STDLIB_VERSION 1 #-} From 0e0e3ae2b8a72ff208a452efdeb76081da7a81a4 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:00:19 +0300 Subject: [PATCH 11/52] Changed getting script by recipient (#417) --- pkg/ride/diff_state.go | 2 +- pkg/ride/functions_proto.go | 4 ++-- pkg/ride/tree_evaluation.go | 4 ++-- pkg/state/state.go | 14 ++++++++------ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pkg/ride/diff_state.go b/pkg/ride/diff_state.go index 6f0b01e9b..22f9c9ddf 100644 --- a/pkg/ride/diff_state.go +++ b/pkg/ride/diff_state.go @@ -109,7 +109,7 @@ func (diffSt *diffState) findMinGenerating(effectiveHistory []int64, generatingF func (diffSt *diffState) addEffectiveToHistory(searchAddress string, effective int64) error { oldDiffBalance, ok := diffSt.balances[searchAddress] if !ok { - return errors.Errorf("Cannot find balance to add effective to history") + return errors.Errorf("cannot find balance to add effective to history") } oldDiffBalance.effectiveHistory = append(oldDiffBalance.effectiveHistory, effective) diffSt.balances[searchAddress] = oldDiffBalance diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 0ff6b339e..2d23dff85 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -108,7 +108,7 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { err = env.smartAppendActions(paymentActions) if err != nil { - return nil, errors.Wrapf(err, "Failed to apply attachedPayments") + return nil, errors.Wrapf(err, "failed to apply attachedPayments") } if res.Result() { @@ -130,7 +130,7 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { return res.UserResult(), nil } - return nil, errors.Errorf("Result of Invoke is false") + return nil, errors.Errorf("result of Invoke is false") } func addressFromString(env RideEnvironment, args ...rideType) (rideType, error) { diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index 4994740e9..bb7e1e602 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -23,12 +23,12 @@ func invokeFunctionFromDApp(env RideEnvironment, recipient proto.Recipient, fnNa newScript, err := env.state().GetByteTree(recipient) if err != nil { - return nil, errors.Wrap(err, "Failed to get script by recipient") + return nil, errors.Wrap(err, "failed to get script by recipient") } tree, err := Parse(newScript) if err != nil { - return nil, errors.Wrap(err, "Failed to get tree by script") + return nil, errors.Wrap(err, "failed to get tree by script") } e, err := treeFunctionEvaluatorForInvokeDAppFromDApp(env, tree, string(fnName), listArgs) diff --git a/pkg/state/state.go b/pkg/state/state.go index 50aa6da99..184c6436f 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -474,24 +474,26 @@ func (s *stateManager) ApplyToState(actions []proto.ScriptAction) ([]proto.Scrip func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, error) { if recipient.Address != nil { - script, err := s.stor.scriptsStorage.scriptBytesByAddr(*recipient.Address, false) + key := accountScriptKey{*recipient.Address} + script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), false) if err != nil { - return nil, errors.Wrapf(err, "Failed to get script by address") + return nil, errors.Wrapf(err, "failed to get script by address") } return script, nil } if recipient.Alias != nil { address, err := s.NewestAddrByAlias(*recipient.Alias) if err != nil { - return nil, errors.Wrapf(err, "Failed to get address by alias") + return nil, errors.Wrapf(err, "failed to get address by alias") } - script, err := s.stor.scriptsStorage.scriptBytesByAddr(address, false) + key := accountScriptKey{address} + script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), false) if err != nil { - return nil, errors.Wrapf(err, "Failed to get script by address") + return nil, errors.Wrapf(err, "failed to get script by address") } return script, nil } - return nil, errors.Errorf("Address and alias from recipient are nil") + return nil, errors.Errorf("address and alias from recipient are nil") } func (s *stateManager) Mutex() *lock.RwMutex { From 3d437afdc944444f0dc3bfc1a4e3cbffece3d4fb Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Fri, 29 Jan 2021 16:01:52 +0300 Subject: [PATCH 12/52] Ride new type of asset in Invocation (#419) * Changed type of asset to optional * Fixed tests * Changed the type of asset to OptionalAsset and improved the test of payments * Changed creating of waves balance --- pkg/proto/types.go | 8 +++ pkg/ride/diff_state.go | 72 ++++++++++----------- pkg/ride/environment.go | 52 +++++++++++---- pkg/ride/functions_proto.go | 17 +++++ pkg/ride/runtime.go | 1 + pkg/ride/tree_evaluation_test.go | 106 +++++++++++++++++-------------- pkg/state/state.go | 6 +- pkg/types/types.go | 2 +- 8 files changed, 160 insertions(+), 104 deletions(-) diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 83d1393fe..f7a1ed1a4 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -151,9 +151,17 @@ func NewOptionalAssetFromBytes(b []byte) (*OptionalAsset, error) { } func NewOptionalAssetFromDigest(d crypto.Digest) *OptionalAsset { + waves := crypto.Digest{} + if d == waves { + return &OptionalAsset{Present: false} + } return &OptionalAsset{Present: true, ID: d} } +func NewOptionalAssetWaves() OptionalAsset { + return OptionalAsset{Present: false} +} + // String method converts OptionalAsset to its text representation func (a OptionalAsset) String() string { if a.Present { diff --git a/pkg/ride/diff_state.go b/pkg/ride/diff_state.go index 22f9c9ddf..887fda3db 100644 --- a/pkg/ride/diff_state.go +++ b/pkg/ride/diff_state.go @@ -22,7 +22,7 @@ type lease struct { } type diffBalance struct { - assetID crypto.Digest + asset proto.OptionalAsset regular int64 leaseIn int64 leaseOut int64 @@ -53,9 +53,9 @@ type diffState struct { dataEntries diffDataEntries balances map[string]diffBalance // map[address.String() + Digest.String()] or map[address.String()] sponsorships map[string]diffSponsorship // map[Digest.String()] - newAssetsInfo map[string]diffNewAssetInfo // map[assetID.String()] - oldAssetsInfo map[string]diffOldAssetInfo // map[assetID.String()] - leases map[string]lease // map[leaseID.String()] + newAssetsInfo map[string]diffNewAssetInfo // map[asset.String()] + oldAssetsInfo map[string]diffOldAssetInfo // map[asset.String()] + leases map[string]lease // map[lease.String()] } func (diffSt *diffState) addBalanceTo(searchAddress string, amount int64) { @@ -65,25 +65,26 @@ func (diffSt *diffState) addBalanceTo(searchAddress string, amount int64) { } func (diffSt *diffState) reissueNewAsset(assetID crypto.Digest, quantity int64, reissuable bool) { - - asset := diffSt.newAssetsInfo[assetID.String()] - asset.reissuable = reissuable - asset.quantity += quantity - diffSt.newAssetsInfo[assetID.String()] = asset + asset := proto.NewOptionalAssetFromDigest(assetID) + assetInfo := diffSt.newAssetsInfo[asset.String()] + assetInfo.reissuable = reissuable + assetInfo.quantity += quantity + diffSt.newAssetsInfo[asset.String()] = assetInfo } func (diffSt *diffState) burnNewAsset(assetID crypto.Digest, quantity int64) { + asset := proto.NewOptionalAssetFromDigest(assetID) - asset := diffSt.newAssetsInfo[assetID.String()] - asset.quantity -= quantity - diffSt.newAssetsInfo[assetID.String()] = asset + assetInfo := diffSt.newAssetsInfo[asset.String()] + assetInfo.quantity -= quantity + diffSt.newAssetsInfo[asset.String()] = assetInfo } func (diffSt *diffState) createNewWavesBalance(account proto.Recipient) (*diffBalance, string) { - waves := crypto.Digest{} - balance := diffBalance{assetID: waves} - diffSt.balances[account.Address.String()+waves.String()] = balance - return &balance, account.Address.String() + waves.String() + wavesAsset := proto.NewOptionalAssetWaves() + balance := diffBalance{asset: wavesAsset} + diffSt.balances[account.Address.String()+wavesAsset.String()] = balance + return &balance, account.Address.String() + wavesAsset.String() } func (diffSt *diffState) cancelLease(searchLease lease, senderSearchAddress, recipientSearchAddress string) { @@ -139,10 +140,10 @@ func (diffSt *diffState) changeLeaseIn(searchBalance *diffBalance, searchAddress } var balance diffBalance - balance.assetID = crypto.Digest{} + balance.asset = proto.NewOptionalAssetWaves() balance.leaseIn = leasedAmount - diffSt.balances[address.String()+balance.assetID.String()] = balance + diffSt.balances[address.String()+balance.asset.String()] = balance return nil } @@ -164,10 +165,10 @@ func (diffSt *diffState) changeLeaseOut(searchBalance *diffBalance, searchAddres } var balance diffBalance - balance.assetID = crypto.Digest{} + balance.asset = proto.NewOptionalAssetWaves() balance.leaseOut = leasedAmount - diffSt.balances[address.String()+balance.assetID.String()] = balance + diffSt.balances[address.String()+balance.asset.String()] = balance return nil } @@ -183,10 +184,11 @@ func (diffSt *diffState) changeBalance(searchBalance *diffBalance, searchAddress } var balance diffBalance - balance.assetID = assetID + asset := *proto.NewOptionalAssetFromDigest(assetID) + balance.asset = asset balance.regular = amount - diffSt.balances[address.String()+assetID.String()] = balance + diffSt.balances[address.String()+asset.String()] = balance return nil } @@ -247,46 +249,38 @@ func (diffSt *diffState) findDeleteFromDataEntryByKey(key string, address string return nil } -func (diffSt *diffState) findBalance(recipient proto.Recipient, asset []byte) (*diffBalance, string, error) { +func (diffSt *diffState) findBalance(recipient proto.Recipient, asset proto.OptionalAsset) (*diffBalance, string, error) { address, err := diffSt.state.NewestRecipientToAddress(recipient) if err != nil { return nil, "", errors.Errorf("cannot get address from recipient") } - if asset == nil { - waves := crypto.Digest{} - if balance, ok := diffSt.balances[address.String()+waves.String()]; ok { - return &balance, address.String() + waves.String(), nil - } - return nil, "", nil - } - assetID, err := crypto.NewDigestFromBytes(asset) - if err != nil { - return nil, "", err - } - if balance, ok := diffSt.balances[address.String()+assetID.String()]; ok { - return &balance, address.String() + assetID.String(), nil + if balance, ok := diffSt.balances[address.String()+asset.String()]; ok { + return &balance, address.String() + asset.String(), nil } return nil, "", nil } func (diffSt *diffState) findSponsorship(assetID crypto.Digest) *int64 { - if sponsorship, ok := diffSt.sponsorships[assetID.String()]; ok { + asset := proto.NewOptionalAssetFromDigest(assetID) + if sponsorship, ok := diffSt.sponsorships[asset.String()]; ok { return &sponsorship.MinFee } return nil } func (diffSt *diffState) findNewAsset(assetID crypto.Digest) *diffNewAssetInfo { - if newAsset, ok := diffSt.newAssetsInfo[assetID.String()]; ok { + asset := proto.NewOptionalAssetFromDigest(assetID) + if newAsset, ok := diffSt.newAssetsInfo[asset.String()]; ok { return &newAsset } return nil } func (diffSt *diffState) findOldAsset(assetID crypto.Digest) *diffOldAssetInfo { - if oldAsset, ok := diffSt.oldAssetsInfo[assetID.String()]; ok { + asset := proto.NewOptionalAssetFromDigest(assetID) + if oldAsset, ok := diffSt.oldAssetsInfo[asset.String()]; ok { return &oldAsset } return nil diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 11eeaa4fd..038236b9e 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -35,12 +35,17 @@ func (wrappedSt *wrappedState) NewestAddrByAlias(alias proto.Alias) (proto.Addre return wrappedSt.diff.state.NewestAddrByAlias(alias) } -func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) { - balance, err := wrappedSt.diff.state.NewestAccountBalance(account, asset) +func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { + balance, err := wrappedSt.diff.state.NewestAccountBalance(account, assetID) if err != nil { return 0, err } - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + + asset, err := proto.NewOptionalAssetFromBytes(assetID) + if err != nil { + return 0, err + } + balanceDiff, _, err := wrappedSt.diff.findBalance(account, *asset) if err != nil { return 0, err } @@ -57,8 +62,7 @@ func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) ( if err != nil { return nil, err } - - wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, nil) + wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -164,6 +168,7 @@ func (wrappedSt *wrappedState) NewestAssetIsSponsored(assetID crypto.Digest) (bo return wrappedSt.diff.state.NewestAssetIsSponsored(assetID) } func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { + // TODO searchNewAsset := wrappedSt.diff.findNewAsset(assetID) if searchNewAsset == nil { @@ -385,8 +390,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro senderAddress = proto.Address(wrappedSt.envThis) } - - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset) if err != nil { return nil, err } @@ -396,7 +400,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro } senderRecipient := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset.ID.Bytes()) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset) if err != nil { return nil, err } @@ -479,7 +483,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro case *proto.LeaseScriptAction: senderAddress := proto.Address(wrappedSt.envThis) - recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, nil) + recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -489,7 +493,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro } senderAccount := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, nil) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -517,7 +521,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro return nil, errors.Errorf("there is no lease to cancel") } - recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, nil) + recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -525,7 +529,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro _, recipientSearchAddress = wrappedSt.diff.createNewWavesBalance(searchLease.Recipient) } - senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, nil) + senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -732,6 +736,29 @@ func (e *Environment) appendActions(actions []proto.ScriptAction) { e.act = append(e.act, actions...) } +//func (e *Environment) validateInvokeResult(actions []proto.ScriptAction) (bool, error) { +// // validate diff +// wrappedSt, ok := e.st.(*wrappedState) +// if !ok { +// return false, errors.Errorf("validation: wrong state") +// } +// for _, value := range wrappedSt.diff.balances { +// if value.regular < 0 || value.leaseIn < 0 || value.leaseOut < 0 { +// return false, nil +// } +// for _, effective := range value.effectiveHistory { +// if effective < 0 { +// return false, nil +// } +// } +// } +// +// // validate actions +// // leaseCancel +// +// +//} + func (e *Environment) smartAppendActions(actions []proto.ScriptAction) error { _, ok := e.st.(*wrappedState) if !ok { @@ -746,6 +773,7 @@ func (e *Environment) smartAppendActions(actions []proto.ScriptAction) error { e.appendActions(modifiedActions) return nil } + func (e *Environment) checkMessageLength(l int) bool { return e.check(l) } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 2d23dff85..765914851 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -124,6 +124,23 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { env.SetInvocation(oldInvocationParam) + // validation + + /* + actions: + 1) Sender has rights + 2) Transfer and Lease don't try to send negative amount + 3) reissue/issue + 4) the limit length of coin name (issue) + 5) script of asset ??? + + diff: + 1) negative balance + + */ + + //env.validateInvokeResult(res.ScriptActions()) + if res.UserResult() == nil { return rideUnit{}, nil } diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index 4ddbbd4bd..e6bffd255 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -344,6 +344,7 @@ type RideEnvironment interface { applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) appendActions(actions []proto.ScriptAction) smartAppendActions(actions []proto.ScriptAction) error + //validateInvokeResult(actions []proto.ScriptAction) (bool, error) actions() []proto.ScriptAction invCount() uint64 incrementInvCount() diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 1c1d0511c..ce4576a56 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -933,7 +933,7 @@ func smartStateDappFromDapp() types.SmartState { senderAddress = proto.Address(wrappedSt.envThis) } - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset.ID.Bytes()) + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset) if err != nil { return nil, err } @@ -942,7 +942,7 @@ func smartStateDappFromDapp() types.SmartState { return nil, err } senderRecipient := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset.ID.Bytes()) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset) if err != nil { return nil, err } @@ -1026,7 +1026,7 @@ func smartStateDappFromDapp() types.SmartState { case *proto.LeaseScriptAction: senderAddress := proto.Address(wrappedSt.envThis) - recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, nil) + recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -1036,7 +1036,7 @@ func smartStateDappFromDapp() types.SmartState { } senderAccount := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, nil) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -1063,7 +1063,7 @@ func smartStateDappFromDapp() types.SmartState { if searchLease == nil { return nil, errors.Errorf("there is no lease to cancel") } - recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, nil) + recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -1071,7 +1071,7 @@ func smartStateDappFromDapp() types.SmartState { return nil, errors.Errorf("there is no balance to cancel lease") } - senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, nil) + senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -1117,20 +1117,34 @@ func smartStateDappFromDapp() types.SmartState { return 10, nil }, NewestScriptPKByAddrFunc: func(address proto.Address, filter bool) (crypto.PublicKey, error) { + // payments test + if address.String() == "3P8eZVKS7a4troGckytxaefLAi9w7P5aMna" { + return crypto.NewPublicKeyFromBase58("FztxsodUc9V7iVzodkGumnZFtHnNTxYSETZfxBFAw9R3") + } + if address.String() == "3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv" { + return crypto.NewPublicKeyFromBase58("pmDSxpnULiroUAerTDFBajffTpqgwVJjtMipQq6DQM5") + } + // if address == addr { - return crypto.MustPublicKeyFromBase58("JBjPD1xkTTcYUVhbLp1bLJLcjDKLT3c32RVk9Rue87ZD"), nil + return crypto.NewPublicKeyFromBase58("JBjPD1xkTTcYUVhbLp1bLJLcjDKLT3c32RVk9Rue87ZD") } if address == addressCallable { - return crypto.MustPublicKeyFromBase58("8TLsCqkkroVot9dVR1WcWUN9Qx96HDfzG3hnx7NpSJA9"), nil + return crypto.NewPublicKeyFromBase58("8TLsCqkkroVot9dVR1WcWUN9Qx96HDfzG3hnx7NpSJA9") } - return crypto.PublicKey{}, nil + + return crypto.PublicKey{}, errors.Errorf("No pk from address") }, NewestTransactionByIDFunc: func(id []byte) (proto.Transaction, error) { return nil, nil }, - NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { + NewestAccountBalanceFunc: func(account proto.Recipient, assetID []byte) (uint64, error) { balance := 0 - balanceDiff, _, err := wrappedSt.diff.findBalance(account, asset) + + asset, err := proto.NewOptionalAssetFromBytes(assetID) + if err != nil { + return 0, err + } + balanceDiff, _, err := wrappedSt.diff.findBalance(account, *asset) if err != nil { return 0, err } @@ -1144,7 +1158,7 @@ func smartStateDappFromDapp() types.SmartState { NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { balance := 0 - wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, nil) + wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -1171,12 +1185,8 @@ func smartStateDappFromDapp() types.SmartState { LeaseOut: uint64(resLeaseOut)}, nil } - waves := crypto.Digest{} - err = wrappedSt.diff.changeBalance(nil, "", 0, waves, account) - if err != nil { - return nil, err - } - err = wrappedSt.diff.addEffectiveToHistory(account.Address.String()+waves.String(), int64(balance)) + _, searchAddr := wrappedSt.diff.createNewWavesBalance(account) + err = wrappedSt.diff.addEffectiveToHistory(searchAddr, int64(balance)) if err != nil { return nil, err } @@ -1574,9 +1584,9 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { expectedBurnWrites[0].AssetID = expectedIssueWrites[0].ID // start balance - bal := wrappedSt.diff.balances[addr.String()+crypto.Digest{}.String()] + bal := wrappedSt.diff.balances[addr.String()+proto.OptionalAsset{}.String()] bal.regular = 2468 - wrappedSt.diff.balances[addr.String()+crypto.Digest{}.String()] = bal + wrappedSt.diff.balances[addr.String()+proto.OptionalAsset{}.String()] = bal src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -1620,6 +1630,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { LeaseOut: 0, } fullBalance, err := smartState().NewestFullWavesBalance(recipient) + require.NoError(t, err) assert.Equal(t, fullBalance, fullBalanceExpected) @@ -1636,11 +1647,11 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { assert.Equal(t, fullBalanceCallable, fullBalanceCallableExpected) expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balance := diffBalance{regular: 1, leaseIn: 10, assetID: assetExp.ID, effectiveHistory: []int64{11}} - expectedDiffResult.balances[addr.String()+assetExp.ID.String()] = balance + balance := diffBalance{regular: 1, leaseIn: 10, asset: assetExp, effectiveHistory: []int64{11}} + expectedDiffResult.balances[addr.String()+assetExp.String()] = balance - balanceCallable := diffBalance{regular: 2467, leaseOut: 10, assetID: assetExp.ID, effectiveHistory: []int64{2457}} - expectedDiffResult.balances[addressCallable.String()+assetExp.ID.String()] = balanceCallable + balanceCallable := diffBalance{regular: 2467, leaseOut: 10, asset: assetExp, effectiveHistory: []int64{2457}} + expectedDiffResult.balances[addressCallable.String()+assetExp.String()] = balanceCallable intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry1 @@ -1954,12 +1965,12 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -14, effectiveHistory: []int64{0, -14}} - balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 14, effectiveHistory: []int64{0, 14}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -14, effectiveHistory: []int64{0, -14}} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 14, effectiveHistory: []int64{0, 14}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable - expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+proto.NewOptionalAssetWaves().String()] = balanceCallable + expectedDiffResult.balances[addr.String()+proto.NewOptionalAssetWaves().String()] = balanceMain assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) @@ -2133,12 +2144,12 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -29, effectiveHistory: []int64{0, -14, -29}} - balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 29, effectiveHistory: []int64{0, 14, 29}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -29, effectiveHistory: []int64{0, -14, -29}} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 29, effectiveHistory: []int64{0, 14, 29}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain - expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) @@ -2309,14 +2320,14 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -16, effectiveHistory: []int64{0, -16}} - balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 16, effectiveHistory: []int64{0, 16}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -16, effectiveHistory: []int64{0, -16}} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 16, effectiveHistory: []int64{0, 16}} intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 - expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain - expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) @@ -2485,12 +2496,12 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balanceMain := diffBalance{assetID: crypto.Digest{}, regular: -13, effectiveHistory: []int64{0, -13}} - balanceCallable := diffBalance{assetID: crypto.Digest{}, regular: 13, effectiveHistory: []int64{0, 13}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -13, effectiveHistory: []int64{0, -13}} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 13, effectiveHistory: []int64{0, 13}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[addr.String()+crypto.Digest{}.String()] = balanceMain - expectedDiffResult.balances[addressCallable.String()+crypto.Digest{}.String()] = balanceCallable + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) @@ -2616,7 +2627,7 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { func test() = if ((i.payments[0].assetId != unit)) then throw("unexpected asset") else { - let res = Invoke(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), "testActions",[(i.payments[0].amount * exchangeRate)], nil) + let res = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "testActions",[(i.payments[0].amount * exchangeRate)], nil) if res == 17 then [ @@ -2645,14 +2656,13 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { proofs := proto.NewProofs() proofs.Proofs = []proto.B58Bytes{proof[:]} require.NoError(t, err) - addr, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - - addressCallable, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) @@ -2685,7 +2695,7 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVcjs60SXJOkyuw5/k9G1s1WTS37EPtjmHoCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCQAAaAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAAMZXhjaGFuZ2VSYXRlBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlAAAAAJWUUMQ=" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCQAAaAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAAMZXhjaGFuZ2VSYXRlBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlAAAAANOWG8w=" secondScript = "AAIFAAAAAAAAAAcIAhIDCgEBAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAABAAAAAWEJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADaW50AAAAAAAAAAABBQAAAANuaWwAAAAAAAAAABEAAAAAPWJMug==" id = bytes.Repeat([]byte{0}, 32) @@ -2695,7 +2705,7 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: crypto.PublicKey{}, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: crypto.PublicKey{}, Recipient: recipient, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp @@ -2724,8 +2734,6 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) require.NoError(t, err) - addrSender := proto.Address(inv["caller"].(rideAddress)) - expectedTransferWrites[0].Recipient = proto.NewRecipientFromAddress(addrSender) expectedActionsResult := &proto.ScriptResult{ DataEntries: expectedDataEntryWrites, Transfers: expectedTransferWrites, diff --git a/pkg/state/state.go b/pkg/state/state.go index 184c6436f..67cac215f 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -859,19 +859,19 @@ func (s *stateManager) NewestFullWavesBalance(account proto.Recipient) (*proto.F }, nil } -func (s *stateManager) NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) { +func (s *stateManager) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { addr, err := s.NewestRecipientToAddress(account) if err != nil { return 0, wrapErr(RetrievalError, err) } - if asset == nil { + if assetID == nil { profile, err := s.newestWavesBalanceProfile(*addr) if err != nil { return 0, wrapErr(RetrievalError, err) } return profile.balance, nil } - balance, err := s.newestAssetBalance(*addr, asset) + balance, err := s.newestAssetBalance(*addr, assetID) if err != nil { return 0, wrapErr(RetrievalError, err) } diff --git a/pkg/types/types.go b/pkg/types/types.go index f282dbb98..ba0d4ed02 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -45,7 +45,7 @@ type SmartState interface { NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) // NewestAccountBalance retrieves balance of address in specific currency, asset is asset's ID. // nil asset = Waves. - NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) + NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) From 96dcc978a3481f2e86268fcd74df0f447a5ab645 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Mon, 1 Feb 2021 09:37:22 +0300 Subject: [PATCH 13/52] Handling of script actions on different accounts added (#420) * Handling of script actions on different accounts added * Protobuf schemas v1.3.0 referenced * Error handling fixed --- pkg/proto/scripting.go | 72 ++++++++++++++++++---- pkg/proto/scripting_test.go | 20 +++---- pkg/ride/environment.go | 32 +++++----- pkg/ride/functions_proto.go | 2 +- pkg/ride/tree_evaluation_test.go | 100 +++++++++++++++---------------- pkg/state/invoke_applier.go | 99 ++++++++++++++++-------------- 6 files changed, 189 insertions(+), 136 deletions(-) diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index 35d28a547..d75253a4f 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -13,23 +13,28 @@ import ( // ScriptAction common interface of script invocation actions. type ScriptAction interface { scriptAction() + SenderPK() *crypto.PublicKey } // DataEntryScriptAction is an action to manipulate account data state. type DataEntryScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey Entry DataEntry } func (a DataEntryScriptAction) scriptAction() {} +func (a DataEntryScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *DataEntryScriptAction) ToProtobuf() *g.DataTransactionData_DataEntry { return a.Entry.ToProtobuf() } // TransferScriptAction is an action to emit transfer of asset. type TransferScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey Recipient Recipient Amount int64 Asset OptionalAsset @@ -38,6 +43,10 @@ type TransferScriptAction struct { func (a TransferScriptAction) scriptAction() {} +func (a TransferScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *TransferScriptAction) ToProtobuf() (*g.InvokeScriptResult_Payment, error) { amount := &g.Amount{ AssetId: a.Asset.ToID(), @@ -52,7 +61,7 @@ func (a *TransferScriptAction) ToProtobuf() (*g.InvokeScriptResult_Payment, erro // IssueScriptAction is an action to issue a new asset as a result of script invocation. type IssueScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey ID crypto.Digest // calculated field Name string // name Description string // description @@ -65,6 +74,10 @@ type IssueScriptAction struct { func (a IssueScriptAction) scriptAction() {} +func (a IssueScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *IssueScriptAction) ToProtobuf() *g.InvokeScriptResult_Issue { return &g.InvokeScriptResult_Issue{ AssetId: a.ID.Bytes(), @@ -106,7 +119,7 @@ func GenerateIssueScriptActionID(name, description string, decimals, quantity in // ReissueScriptAction is an action to emit Reissue transaction as a result of script invocation. type ReissueScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey AssetID crypto.Digest // assetId Quantity int64 // quantity Reissuable bool // isReissuable @@ -114,6 +127,10 @@ type ReissueScriptAction struct { func (a ReissueScriptAction) scriptAction() {} +func (a ReissueScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *ReissueScriptAction) ToProtobuf() *g.InvokeScriptResult_Reissue { return &g.InvokeScriptResult_Reissue{ AssetId: a.AssetID.Bytes(), @@ -124,13 +141,17 @@ func (a *ReissueScriptAction) ToProtobuf() *g.InvokeScriptResult_Reissue { // BurnScriptAction is an action to burn some assets in response to script invocation. type BurnScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey AssetID crypto.Digest // assetId Quantity int64 // quantity } func (a BurnScriptAction) scriptAction() {} +func (a BurnScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *BurnScriptAction) ToProtobuf() *g.InvokeScriptResult_Burn { return &g.InvokeScriptResult_Burn{ AssetId: a.AssetID.Bytes(), @@ -140,13 +161,17 @@ func (a *BurnScriptAction) ToProtobuf() *g.InvokeScriptResult_Burn { // SponsorshipScriptAction is an action to set sponsorship for given asset in response to script invocation. type SponsorshipScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey AssetID crypto.Digest // assetId MinFee int64 // minSponsoredAssetFee } func (a SponsorshipScriptAction) scriptAction() {} +func (a SponsorshipScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *SponsorshipScriptAction) ToProtobuf() *g.InvokeScriptResult_SponsorFee { return &g.InvokeScriptResult_SponsorFee{ MinFee: &g.Amount{ @@ -158,7 +183,7 @@ func (a *SponsorshipScriptAction) ToProtobuf() *g.InvokeScriptResult_SponsorFee // LeaseScriptAction is an action to lease Waves to given account. type LeaseScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey ID crypto.Digest Recipient Recipient Amount int64 @@ -167,6 +192,10 @@ type LeaseScriptAction struct { func (a LeaseScriptAction) scriptAction() {} +func (a LeaseScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *LeaseScriptAction) ToProtobuf() (*g.InvokeScriptResult_Lease, error) { rcp, err := a.Recipient.ToProtobuf() if err != nil { @@ -204,12 +233,16 @@ func GenerateLeaseScriptActionID(recipient Recipient, amount int64, nonce int64, // LeaseCancelScriptAction is an action that cancels previously created lease. type LeaseCancelScriptAction struct { - Sender crypto.PublicKey + Sender *crypto.PublicKey LeaseID crypto.Digest } func (a *LeaseCancelScriptAction) scriptAction() {} +func (a LeaseCancelScriptAction) SenderPK() *crypto.PublicKey { + return a.Sender +} + func (a *LeaseCancelScriptAction) ToProtobuf() *g.InvokeScriptResult_LeaseCancel { return &g.InvokeScriptResult_LeaseCancel{ LeaseId: a.LeaseID.Bytes(), @@ -393,6 +426,7 @@ type ActionsValidationRestrictions struct { DisableSelfTransfers bool ScriptAddress Address KeySizeValidationVersion byte + Scheme byte } func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestrictions) error { @@ -433,7 +467,15 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr return errors.New("invalid asset") } if restrictions.DisableSelfTransfers { - if ta.Recipient.Address.Eq(restrictions.ScriptAddress) { + senderAddress := restrictions.ScriptAddress + if ta.SenderPK() != nil { + var err error + senderAddress, err = NewAddressFromPublicKey(restrictions.Scheme, *ta.SenderPK()) + if err != nil { + return errors.Wrap(err, "failed to validate TransferScriptAction") + } + } + if ta.Recipient.Address.Eq(senderAddress) { return errors.New("transfers to DApp itself are forbidden since activation of RIDE V4") } } @@ -491,8 +533,16 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr if ta.Amount < 0 { return errors.New("negative leasing amount") } - if ta.Recipient.Address.Eq(restrictions.ScriptAddress) { - return errors.New("leasing to DApp itself are forbidden") + senderAddress := restrictions.ScriptAddress + if ta.SenderPK() != nil { + var err error + senderAddress, err = NewAddressFromPublicKey(restrictions.Scheme, *ta.SenderPK()) + if err != nil { + return errors.Wrap(err, "failed to validate TransferScriptAction") + } + } + if ta.Recipient.Address.Eq(senderAddress) { + return errors.New("leasing to DApp itself is forbidden") } case *LeaseCancelScriptAction: diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index 5c637d53b..9935a7c85 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -35,15 +35,15 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { for i, test := range []ScriptResult{ { DataEntries: []*DataEntryScriptAction{ - {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key", 12345}}, - {Sender: crypto.PublicKey{}, Entry: &BooleanDataEntry{"negative value", false}}, - {Sender: crypto.PublicKey{}, Entry: &StringDataEntry{"some key", "some value string"}}, - {Sender: crypto.PublicKey{}, Entry: &BinaryDataEntry{Key: "k3", Value: []byte{0x24, 0x7f, 0x71, 0x14, 0x1d}}}, - {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key2", -12345}}, - {Sender: crypto.PublicKey{}, Entry: &BooleanDataEntry{"negative value2", true}}, - {Sender: crypto.PublicKey{}, Entry: &StringDataEntry{"some key143", "some value2 string"}}, - {Sender: crypto.PublicKey{}, Entry: &BinaryDataEntry{Key: "k5", Value: []byte{0x24, 0x7f, 0x71, 0x10, 0x1d}}}, - {Sender: crypto.PublicKey{}, Entry: &DeleteDataEntry{Key: "xxx"}}, + {Entry: &IntegerDataEntry{"some key", 12345}}, + {Entry: &BooleanDataEntry{"negative value", false}}, + {Entry: &StringDataEntry{"some key", "some value string"}}, + {Entry: &BinaryDataEntry{Key: "k3", Value: []byte{0x24, 0x7f, 0x71, 0x14, 0x1d}}}, + {Entry: &IntegerDataEntry{"some key2", -12345}}, + {Entry: &BooleanDataEntry{"negative value2", true}}, + {Entry: &StringDataEntry{"some key143", "some value2 string"}}, + {Entry: &BinaryDataEntry{Key: "k5", Value: []byte{0x24, 0x7f, 0x71, 0x10, 0x1d}}}, + {Entry: &DeleteDataEntry{Key: "xxx"}}, }, Transfers: []*TransferScriptAction{ {Amount: math.MaxInt64, Asset: *waves, Recipient: rcp}, @@ -60,7 +60,7 @@ func TestScriptResultBinaryRoundTrip(t *testing.T) { }, { DataEntries: []*DataEntryScriptAction{ - {Sender: crypto.PublicKey{}, Entry: &IntegerDataEntry{"some key", 12345}}, + {Entry: &IntegerDataEntry{"some key", 12345}}, }, Transfers: emptyTransfers, Issues: emptyIssues, diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 038236b9e..b02adcb8a 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -314,7 +314,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.StringDataEntry: stringEntry := *dataEntry @@ -326,7 +326,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BooleanDataEntry: boolEntry := *dataEntry @@ -338,7 +338,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BinaryDataEntry: binaryEntry := *dataEntry @@ -350,7 +350,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.DeleteDataEntry: deleteEntry := *dataEntry @@ -362,20 +362,16 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK default: } case *proto.TransferScriptAction: var senderAddress proto.Address - - emptyPK := crypto.PublicKey{} - var senderPK crypto.PublicKey - - if res.Sender != emptyPK { - senderPK = res.Sender + if res.Sender != nil { + senderPK = *res.Sender var err error senderAddress, err = proto.NewAddressFromPublicKey(wrappedSt.envScheme, senderPK) if err != nil { @@ -410,7 +406,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro return nil, err } - res.Sender = senderPK + res.Sender = &senderPK case *proto.SponsorshipScriptAction: var sponsorship diffSponsorship @@ -422,7 +418,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.IssueScriptAction: var assetInfo diffNewAssetInfo @@ -441,7 +437,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.ReissueScriptAction: searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) @@ -459,7 +455,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BurnScriptAction: searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) @@ -478,7 +474,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.LeaseScriptAction: senderAddress := proto.Address(wrappedSt.envThis) @@ -510,7 +506,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) - res.Sender = pk + res.Sender = &pk case *proto.LeaseCancelScriptAction: searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) @@ -544,7 +540,7 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = pk + res.Sender = &pk default: } } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 765914851..f2617433a 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -96,7 +96,7 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { var paymentActions []proto.ScriptAction for _, payment := range attachedPayments { - action := &proto.TransferScriptAction{Sender: callerPublicKey, Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} + action := &proto.TransferScriptAction{Sender: &callerPublicKey, Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} paymentActions = append(paymentActions, action) } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index ce4576a56..600b2b21a 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -856,7 +856,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.StringDataEntry: stringEntry := *dataEntry address := proto.Address(wrappedSt.envThis) @@ -867,7 +867,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BooleanDataEntry: boolEntry := *dataEntry @@ -879,7 +879,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BinaryDataEntry: binaryEntry := *dataEntry @@ -891,7 +891,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.DeleteDataEntry: deleteEntry := *dataEntry @@ -903,20 +903,16 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK default: } case *proto.TransferScriptAction: var senderAddress proto.Address - - emptyPK := crypto.PublicKey{} - var senderPK crypto.PublicKey - - if res.Sender != emptyPK { - senderPK = res.Sender + if res.Sender != nil { + senderPK = *res.Sender if senderPK.String() == addrPK.String() { senderAddress = addr } else { @@ -952,7 +948,7 @@ func smartStateDappFromDapp() types.SmartState { return nil, err } - res.Sender = senderPK + res.Sender = &senderPK case *proto.SponsorshipScriptAction: var sponsorship diffSponsorship @@ -964,7 +960,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.IssueScriptAction: var assetInfo diffNewAssetInfo @@ -985,7 +981,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.ReissueScriptAction: searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) @@ -1003,7 +999,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.BurnScriptAction: searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) @@ -1022,7 +1018,7 @@ func smartStateDappFromDapp() types.SmartState { if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = senderPK + res.Sender = &senderPK case *proto.LeaseScriptAction: senderAddress := proto.Address(wrappedSt.envThis) @@ -1053,7 +1049,7 @@ func smartStateDappFromDapp() types.SmartState { wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) - res.Sender = pk + res.Sender = &pk case *proto.LeaseCancelScriptAction: searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) @@ -1086,7 +1082,7 @@ func smartStateDappFromDapp() types.SmartState { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = pk + res.Sender = &pk default: } @@ -1538,32 +1534,32 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedIssueWrites := []*proto.IssueScriptAction{ - {Sender: addressCallablePK, Name: "CatCoin", Description: "", Quantity: 1, Decimals: 0, Reissuable: true, Script: nil, Nonce: 0}, + {Sender: &addressCallablePK, Name: "CatCoin", Description: "", Quantity: 1, Decimals: 0, Reissuable: true, Script: nil, Nonce: 0}, } expectedReissueWrites := []*proto.ReissueScriptAction{ - {Sender: addressCallablePK, Quantity: 10, Reissuable: false}, + {Sender: &addressCallablePK, Quantity: 10, Reissuable: false}, } expectedBurnWrites := []*proto.BurnScriptAction{ - {Sender: addressCallablePK, Quantity: 5}, + {Sender: &addressCallablePK, Quantity: 5}, } expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.BinaryDataEntry{Key: "bin", Value: []byte("")}, Sender: addressCallablePK}, - {Entry: &proto.BooleanDataEntry{Key: "bool", Value: true}, Sender: addressCallablePK}, - {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: addressCallablePK}, - {Entry: &proto.StringDataEntry{Key: "str", Value: ""}, Sender: addressCallablePK}, - {Entry: &proto.DeleteDataEntry{Key: "str"}, Sender: addressCallablePK}, + {Entry: &proto.BinaryDataEntry{Key: "bin", Value: []byte("")}, Sender: &addressCallablePK}, + {Entry: &proto.BooleanDataEntry{Key: "bool", Value: true}, Sender: &addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, + {Entry: &proto.StringDataEntry{Key: "str", Value: ""}, Sender: &addressCallablePK}, + {Entry: &proto.DeleteDataEntry{Key: "str"}, Sender: &addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } expectedLeaseWrites := []*proto.LeaseScriptAction{ - {Sender: addressCallablePK, Recipient: recipient, Amount: 10, Nonce: 0}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 10, Nonce: 0}, } smartState := smartStateDappFromDapp @@ -1757,7 +1753,7 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addrPK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addrPK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } @@ -1913,13 +1909,13 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } @@ -2090,16 +2086,16 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addrPK, Recipient: recipientCallable, Amount: 18, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 18, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp @@ -2267,15 +2263,15 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: addrPK}, - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: &addrPK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp @@ -2443,15 +2439,15 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp @@ -2701,11 +2697,11 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: crypto.PublicKey{}, Recipient: recipient, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Recipient: recipient, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 84723b5b4..74fe294a5 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -61,7 +61,7 @@ type payment struct { asset proto.OptionalAsset } -func (ia *invokeApplier) newPaymentFromTransferScriptAction(scriptAddr *proto.Address, action *proto.TransferScriptAction) (*payment, error) { +func (ia *invokeApplier) newPaymentFromTransferScriptAction(senderAddress proto.Address, action *proto.TransferScriptAction) (*payment, error) { if action.Recipient.Address == nil { return nil, errors.New("transfer has unresolved aliases") } @@ -69,14 +69,14 @@ func (ia *invokeApplier) newPaymentFromTransferScriptAction(scriptAddr *proto.Ad return nil, errors.New("negative transfer amount") } return &payment{ - sender: *scriptAddr, + sender: senderAddress, receiver: *action.Recipient.Address, amount: uint64(action.Amount), asset: action.Asset, }, nil } -func (ia *invokeApplier) newTxDiffFromPayment(pmt *payment, updateMinIntermediateBalance bool, _ *fallibleValidationParams) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromPayment(pmt *payment, updateMinIntermediateBalance bool) (txDiff, error) { diff := newTxDiff() senderKey := byteKey(pmt.sender, pmt.asset.ToID()) senderBalanceDiff := -int64(pmt.amount) @@ -91,19 +91,19 @@ func (ia *invokeApplier) newTxDiffFromPayment(pmt *payment, updateMinIntermediat return diff, nil } -func (ia *invokeApplier) newTxDiffFromScriptTransfer(scriptAddr *proto.Address, action *proto.TransferScriptAction, info *fallibleValidationParams) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptTransfer(scriptAddr proto.Address, action *proto.TransferScriptAction) (txDiff, error) { pmt, err := ia.newPaymentFromTransferScriptAction(scriptAddr, action) if err != nil { return txDiff{}, err } // updateMinIntermediateBalance is set to false here, because in Scala implementation // only fee and payments are checked for temporary negative balance. - return ia.newTxDiffFromPayment(pmt, false, info) + return ia.newTxDiffFromPayment(pmt, false) } -func (ia *invokeApplier) newTxDiffFromScriptIssue(scriptAddr *proto.Address, action *proto.IssueScriptAction) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptIssue(senderAddress proto.Address, action *proto.IssueScriptAction) (txDiff, error) { diff := newTxDiff() - senderAssetKey := assetBalanceKey{address: *scriptAddr, asset: action.ID[:]} + senderAssetKey := assetBalanceKey{address: senderAddress, asset: action.ID[:]} senderAssetBalanceDiff := action.Quantity if err := diff.appendBalanceDiff(senderAssetKey.bytes(), newBalanceDiff(senderAssetBalanceDiff, 0, 0, false)); err != nil { return nil, err @@ -111,9 +111,9 @@ func (ia *invokeApplier) newTxDiffFromScriptIssue(scriptAddr *proto.Address, act return diff, nil } -func (ia *invokeApplier) newTxDiffFromScriptReissue(scriptAddr *proto.Address, action *proto.ReissueScriptAction) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptReissue(senderAddress proto.Address, action *proto.ReissueScriptAction) (txDiff, error) { diff := newTxDiff() - senderAssetKey := assetBalanceKey{address: *scriptAddr, asset: action.AssetID[:]} + senderAssetKey := assetBalanceKey{address: senderAddress, asset: action.AssetID[:]} senderAssetBalanceDiff := action.Quantity if err := diff.appendBalanceDiff(senderAssetKey.bytes(), newBalanceDiff(senderAssetBalanceDiff, 0, 0, false)); err != nil { return nil, err @@ -121,9 +121,9 @@ func (ia *invokeApplier) newTxDiffFromScriptReissue(scriptAddr *proto.Address, a return diff, nil } -func (ia *invokeApplier) newTxDiffFromScriptBurn(scriptAddr *proto.Address, action *proto.BurnScriptAction) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptBurn(senderAddress proto.Address, action *proto.BurnScriptAction) (txDiff, error) { diff := newTxDiff() - senderAssetKey := assetBalanceKey{address: *scriptAddr, asset: action.AssetID[:]} + senderAssetKey := assetBalanceKey{address: senderAddress, asset: action.AssetID[:]} senderAssetBalanceDiff := -action.Quantity if err := diff.appendBalanceDiff(senderAssetKey.bytes(), newBalanceDiff(senderAssetBalanceDiff, 0, 0, false)); err != nil { return nil, err @@ -131,10 +131,10 @@ func (ia *invokeApplier) newTxDiffFromScriptBurn(scriptAddr *proto.Address, acti return diff, nil } -func (ia *invokeApplier) newTxDiffFromScriptLease(scriptAddr, recipientAddress *proto.Address, action *proto.LeaseScriptAction) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptLease(senderAddress, recipientAddress proto.Address, action *proto.LeaseScriptAction) (txDiff, error) { diff := newTxDiff() - senderKey := wavesBalanceKey{address: *scriptAddr} - receiverKey := wavesBalanceKey{address: *recipientAddress} + senderKey := wavesBalanceKey{address: senderAddress} + receiverKey := wavesBalanceKey{address: recipientAddress} if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, action.Amount, false)); err != nil { return nil, err } @@ -144,9 +144,9 @@ func (ia *invokeApplier) newTxDiffFromScriptLease(scriptAddr, recipientAddress * return diff, nil } -func (ia *invokeApplier) newTxDiffFromScriptLeaseCancel(scriptAddr *proto.Address, leaseInfo *leasing) (txDiff, error) { +func (ia *invokeApplier) newTxDiffFromScriptLeaseCancel(senderAddress proto.Address, leaseInfo *leasing) (txDiff, error) { diff := newTxDiff() - senderKey := wavesBalanceKey{address: *scriptAddr} + senderKey := wavesBalanceKey{address: senderAddress} senderLeaseOutDiff := -int64(leaseInfo.leaseAmount) if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, senderLeaseOutDiff, false)); err != nil { return nil, err @@ -262,6 +262,20 @@ type addlInvokeInfo struct { libVersion byte } +func (ia *invokeApplier) senderCredentialsFromScriptAction(a proto.ScriptAction, info *addlInvokeInfo) (crypto.PublicKey, proto.Address, error) { + senderPK := info.scriptPK + senderAddress := *info.scriptAddr + if a.SenderPK() != nil { + var err error + senderPK = *a.SenderPK() + senderAddress, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, senderPK) + if err != nil { + return crypto.PublicKey{}, proto.Address{}, err + } + } + return senderPK, senderAddress, nil +} + func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, info *addlInvokeInfo) (proto.TxFailureReason, txBalanceChanges, error) { // Check smart asset scripts on payments. for _, smartAsset := range info.paymentSmartAssets { @@ -285,7 +299,6 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in } restrictions := proto.ActionsValidationRestrictions{ DisableSelfTransfers: info.disableSelfTransfers, - ScriptAddress: *info.scriptAddr, KeySizeValidationVersion: keySizeValidationVersion, } if err := proto.ValidateActions(info.actions, restrictions); err != nil { @@ -315,30 +328,26 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in } // Perform actions. for _, action := range info.actions { + senderPK, senderAddress, err := ia.senderCredentialsFromScriptAction(action, info) + if err != nil { + return proto.DAppError, info.failedChanges, err + } + totalChanges.appendAddr(senderAddress) switch a := action.(type) { case *proto.DataEntryScriptAction: - // Perform data storage writes. - ia.stor.accountsDataStor.appendEntryUncertain(*info.scriptAddr, a.Entry) + ia.stor.accountsDataStor.appendEntryUncertain(senderAddress, a.Entry) case *proto.TransferScriptAction: // Perform transfers. - addr := a.Recipient.Address - totalChanges.appendAddr(*addr) + recipientAddress := a.Recipient.Address + totalChanges.appendAddr(*recipientAddress) assetExists := ia.stor.assets.newestAssetExists(a.Asset, !info.initialisation) if !assetExists { return proto.DAppError, info.failedChanges, errors.New("invalid asset in transfer") } isSmartAsset := ia.stor.scriptsStorage.newestIsSmartAsset(a.Asset.ID, !info.initialisation) if isSmartAsset { - sender := tx.ScriptRecipient.Address - if sender == nil { - addr, err := recipientToAddress(tx.ScriptRecipient, ia.stor.aliases, !info.initialisation) - if err != nil { - return proto.DAppError, info.failedChanges, errors.Wrap(err, "fallibleValidation") - } - sender = addr - } - fullTr, err := proto.NewFullScriptTransfer(a, *sender, tx) + fullTr, err := proto.NewFullScriptTransfer(a, senderAddress, tx) if err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to convert transfer to full script transfer") } @@ -351,7 +360,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.SmartAssetOnActionFailure, info.failedChanges, errorForSmartAsset(res, a.Asset.ID) } } - txDiff, err := ia.newTxDiffFromScriptTransfer(info.scriptAddr, a, info.fallibleValidationParams) + txDiff, err := ia.newTxDiffFromScriptTransfer(senderAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -371,7 +380,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in // Create asset's info. assetInfo := &assetInfo{ assetConstInfo: assetConstInfo{ - issuer: info.scriptPK, + issuer: senderPK, decimals: int8(a.Decimals), }, assetChangeableInfo: assetChangeableInfo{ @@ -385,8 +394,8 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in // Currently asset script is always empty. // TODO: if this script is ever set, don't forget to // also save complexity for it here using saveComplexityForAsset(). - ia.stor.scriptsStorage.setAssetScriptUncertain(a.ID, proto.Script{}, info.scriptPK) - txDiff, err := ia.newTxDiffFromScriptIssue(info.scriptAddr, a) + ia.stor.scriptsStorage.setAssetScriptUncertain(a.ID, proto.Script{}, senderPK) + txDiff, err := ia.newTxDiffFromScriptIssue(senderAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -408,7 +417,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err != nil { return proto.DAppError, info.failedChanges, err } - if assetInfo.issuer != info.scriptPK { + if assetInfo.issuer != senderPK { return proto.DAppError, info.failedChanges, errs.NewAssetIssuedByOtherAddress("asset was issued by other address") } if !assetInfo.reissuable { @@ -417,7 +426,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if math.MaxInt64-a.Quantity < assetInfo.quantity.Int64() && info.block.Timestamp >= ia.settings.ReissueBugWindowTimeEnd { return proto.DAppError, info.failedChanges, errors.New("asset total value overflow") } - ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, info.scriptPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) + ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -432,7 +441,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err := ia.stor.assets.reissueAssetUncertain(a.AssetID, change, !info.initialisation); err != nil { return proto.DAppError, info.failedChanges, err } - txDiff, err := ia.newTxDiffFromScriptReissue(info.scriptAddr, a) + txDiff, err := ia.newTxDiffFromScriptReissue(senderAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -458,14 +467,14 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err != nil { return proto.DAppError, info.failedChanges, err } - if !burnAnyTokensEnabled && assetInfo.issuer != info.scriptPK { + if !burnAnyTokensEnabled && assetInfo.issuer != senderPK { return proto.DAppError, info.failedChanges, errors.New("asset was issued by other address") } quantityDiff := big.NewInt(a.Quantity) if assetInfo.quantity.Cmp(quantityDiff) == -1 { return proto.DAppError, info.failedChanges, errs.NewAccountBalanceError("trying to burn more assets than exist at all") } - ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, info.scriptPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) + ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -480,7 +489,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err := ia.stor.assets.burnAssetUncertain(a.AssetID, change, !info.initialisation); err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to burn asset") } - txDiff, err := ia.newTxDiffFromScriptBurn(info.scriptAddr, a) + txDiff, err := ia.newTxDiffFromScriptBurn(senderAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -508,7 +517,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if !sponsorshipActivated { return proto.DAppError, info.failedChanges, errors.New("sponsorship has not been activated yet") } - if assetInfo.issuer != info.scriptPK { + if assetInfo.issuer != senderPK { return proto.DAppError, info.failedChanges, errors.Errorf("asset %s was not issued by this DApp", a.AssetID.String()) } isSmart := ia.stor.scriptsStorage.newestIsSmartAsset(a.AssetID, !info.initialisation) @@ -534,7 +543,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in l := &leasing{true, uint64(a.Amount), *recipientAddress, *info.scriptAddr} ia.stor.leases.addLeasingUncertain(a.ID, l) - txDiff, err := ia.newTxDiffFromScriptLease(info.scriptAddr, recipientAddress, a) + txDiff, err := ia.newTxDiffFromScriptLease(senderAddress, *recipientAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -552,7 +561,9 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err != nil { return proto.DAppError, info.failedChanges, err } - + if senderAddress != li.sender { + return proto.DAppError, info.failedChanges, errors.Errorf("attempt to cancel leasing that was created by other account") //TODO: Create a scala compatible error in errs package and use it here + } // Update leasing info if err := ia.stor.leases.cancelLeasingUncertain(a.LeaseID, !info.initialisation); err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to cancel leasing") @@ -560,7 +571,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in totalChanges.appendAddr(li.sender) totalChanges.appendAddr(li.recipient) - txDiff, err := ia.newTxDiffFromScriptLeaseCancel(info.scriptAddr, li) + txDiff, err := ia.newTxDiffFromScriptLeaseCancel(senderAddress, li) if err != nil { return proto.DAppError, info.failedChanges, err } From 94234f2ae1d43a584c40631e199d951196c30f0f Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 1 Feb 2021 13:40:16 +0300 Subject: [PATCH 14/52] Changed receiving asset from payments (#421) * Changed receiving asset from payments * Changed error messages --- pkg/proto/types.go | 2 +- pkg/ride/functions_proto.go | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pkg/proto/types.go b/pkg/proto/types.go index f7a1ed1a4..b744213bb 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -145,7 +145,7 @@ func NewOptionalAssetFromBytes(b []byte) (*OptionalAsset, error) { a, err := crypto.NewDigestFromBytes(b) if err != nil { - return nil, errors.Wrap(err, "failed to create OptionalAsset from Base58 string") + return nil, errors.Wrap(err, "failed to create OptionalAsset from bytes") } return &OptionalAsset{Present: true, ID: a}, nil } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index f2617433a..bb764bda0 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -72,26 +72,35 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { return nil, errors.Errorf("invoke: unexpected argument type '%s'", payment.instanceOf()) } - assetID := payment["assetId"] - amount := payment["amount"] + assetID, err := payment.get("assetId") + if err != nil { + return nil, errors.Wrap(err, "invoke") + } + amount, err := payment.get("amount") + if err != nil { + return nil, errors.Wrap(err, "invoke") + } intAmount, ok := amount.(rideInt) if !ok { return nil, errors.Errorf("invoke: unexpected argument type '%s'", amount.instanceOf()) } - var asset crypto.Digest + var asset *proto.OptionalAsset switch asID := assetID.(type) { case rideBytes: - asset, _ = crypto.NewDigestFromBytes(asID) + asset, err = proto.NewOptionalAssetFromBytes(asID) + if err != nil { + return nil, errors.Errorf("invoke: failed to get optional asset from ride bytes") + } case rideUnit: - asset = crypto.Digest{} + waves := proto.NewOptionalAssetWaves() + asset = &waves default: return nil, errors.Errorf("attachedPayment: unexpected argument type '%s'", args[0].instanceOf()) } - optAsset := proto.OptionalAsset{ID: asset} - attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: optAsset, Amount: uint64(intAmount)}) + attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: *asset, Amount: uint64(intAmount)}) } var paymentActions []proto.ScriptAction From 546d9d0a8693bf9b72571d70b4553440dbf8dc2a Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 2 Feb 2021 11:37:18 +0300 Subject: [PATCH 15/52] Changed getting actions from invocaiton (#422) * Changed getting actions from invocaiton * Fixed a check mistake * Added one more test for nil result of basic script --- pkg/ride/tree_evaluation.go | 15 +++- pkg/ride/tree_evaluation_test.go | 149 +++++++++++++++++++++++++++++++ pkg/ride/tree_evaluator.go | 10 +-- 3 files changed, 166 insertions(+), 8 deletions(-) diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index bb7e1e602..ffd8e3c3c 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -46,5 +46,18 @@ func CallFunction(env RideEnvironment, tree *Tree, name string, args proto.Argum if err != nil { return nil, errors.Wrapf(err, "failed to call function '%s'", name) } - return e.evaluate() + rideResult, err := e.evaluate() + + DAppResult, ok := rideResult.(DAppResult) + if !ok { + return rideResult, err + } + if env.actions() == nil { + return rideResult, err + } + + fullActions := env.actions() + fullActions = append(fullActions, DAppResult.actions...) + DAppResult.actions = fullActions + return DAppResult, err } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 600b2b21a..1ca80307d 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -2753,6 +2753,155 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { tearDownDappFromDapp() } +func TestInvokeDAppFromDAppNilResult(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let exchangeRate = 5 + + @Callable(i) + func test() = if ((i.payments[0].assetId != unit)) + then throw("unexpected asset") + else { + let res = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "testActions",[(i.payments[0].amount * exchangeRate)], [AttachedPayment(unit, 1)]) + if res == 17 + then + nil + else + throw("Bad returned value") + } + */ + + /* script 2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func testActions(a: Int) = { + ([ + IntegerEntry("int", 1) + ], 17) + } */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: addrPK, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 500, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAgUAAAAEdW5pdAAAAAAAAAAAAQUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEFAAAAA25pbAkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUAAAAAbfvo1Q==" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgEBAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAABAAAAAWEJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADaW50AAAAAAAAAAABBQAAAANuaWwAAAAAAAAAABEAAAAAPWJMug==" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + } + + smartState := smartStateDappFromDapp + + invCount = 0 + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -1} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable + intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + + tearDownDappFromDapp() + +} + func TestMatchOverwrite(t *testing.T) { /* {-# STDLIB_VERSION 1 #-} diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index 7a17c902d..c950ca2f0 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -232,20 +232,16 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - act := e.env.actions() - act = append(act, a...) - return DAppResult{res: true, actions: act, msg: ""}, nil + return DAppResult{res: true, actions: a, msg: ""}, nil case rideList: - var newActions []proto.ScriptAction + var act []proto.ScriptAction for _, item := range res { a, err := convertToAction(e.env, item) if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - newActions = append(newActions, a) + act = append(act, a) } - act := e.env.actions() - act = append(act, newActions...) return DAppResult{res: true, actions: act}, nil case tuple2: From 1e4e73e8d88e1f8dad78428b49395dd34799d2b8 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 2 Feb 2021 17:20:59 +0300 Subject: [PATCH 16/52] Added a benchmark for recursive invocation call (#423) * Added a benchmark for recursive invocation call * Fixed benchmark --- pkg/ride/functions_proto.go | 2 +- pkg/ride/tree_evaluation_test.go | 97 ++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index bb764bda0..b8fa99d79 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -15,7 +15,7 @@ import ( func invoke(env RideEnvironment, args ...rideType) (rideType, error) { env.incrementInvCount() - if env.invCount() > 9 { + if env.invCount() > 100 { return rideUnit{}, nil } callerAddress, ok := env.this().(rideAddress) diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 1ca80307d..a403794c3 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -2610,6 +2610,103 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { tearDownDappFromDapp() } +func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let r = Invoke(this, "foo", [], []) + if r == r + then + [ + ] + else + throw("Imposible") + } + + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + recipient := proto.NewRecipientFromAddress(addr) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" + + id = bytes.Repeat([]byte{0}, 32) + + smartState := smartStateDappFromDapp + + envActions = nil + thisAddress = addr + invCount = 0 + + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + wrappedSt = *NewWrappedSt + + src, err := base64.StdEncoding.DecodeString(firstScript) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + + tree, err := Parse(src) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := CallFunction(env, tree, "foo", proto.Arguments{}) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + } + tearDownDappFromDapp() +} + func TestInvokeDAppFromDAppPayments(t *testing.T) { /* script 1 From 7568087fbe09bd544fc1059bc8121f252fe57d66 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:38:13 +0300 Subject: [PATCH 17/52] Ride validation dapp from dapp (#425) * Added validation * Added external payment's collection * Adding payments before script processing * Changed validation, added more checks * Deleted useless function * Deleted validation of external payments * Fixed error of addresses * Fix ride environment exposure (#426) * Attempt to reduce exposure of Environment * Attached payments initialization function moved from state package to the new constructor in ride package. All fields of Environment structure made private again. NewWrappedState constructor made private because it is no longer used outside the ride package. Structure declarations and functions reordered in environment.go. * Added issued assets amount to diff and validation of asset * Deleted env from wrapped state * Fixed validation of smart assets * Added test for smart asset * Fixed func getting waves balance from state * Review ride validation dapp from dapp (#431) * Two functions of diffState made non-public * Interface RideEnvironment renamed to Environment, implementation Environment renamed to EvaluationEnvironment. Unused public functions removed, unused parameters removed. Code generation of RIDE functions updated. Generated files regenerated. Co-authored-by: Alexey Kiselev --- go.sum | 6 - pkg/proto/scripting.go | 46 +- pkg/proto/transactions.go | 22 +- pkg/proto/transactions_test.go | 4 +- pkg/proto/transactions_with_proofs.go | 4 +- pkg/proto/types.go | 30 +- pkg/ride/constants.go | 80 +- pkg/ride/constructors.go | 14 +- pkg/ride/converters.go | 4 +- pkg/ride/environment.go | 981 ++++++++++++++------ pkg/ride/functions_boolean.go | 6 +- pkg/ride/functions_bytes.go | 30 +- pkg/ride/functions_common.go | 20 +- pkg/ride/functions_generated.go | 102 +-- pkg/ride/functions_int.go | 26 +- pkg/ride/functions_list.go | 56 +- pkg/ride/functions_proto.go | 171 ++-- pkg/ride/functions_strings.go | 32 +- pkg/ride/generate/main.go | 20 +- pkg/ride/parser.go | 2 +- pkg/ride/program.go | 6 +- pkg/ride/runtime.go | 16 +- pkg/ride/runtime_moq_test.go | 331 ++----- pkg/ride/tree_evaluation.go | 26 +- pkg/ride/tree_evaluation_test.go | 1220 +++++++++++-------------- pkg/ride/tree_evaluator.go | 12 +- pkg/ride/tuples.go | 42 +- pkg/ride/types_moq_test.go | 106 +-- pkg/ride/vm.go | 2 +- pkg/ride/vm_test.go | 4 +- pkg/state/script_caller.go | 12 +- pkg/state/state.go | 25 +- pkg/types/types.go | 2 +- 33 files changed, 1759 insertions(+), 1701 deletions(-) diff --git a/go.sum b/go.sum index b0cf6f6be..974cfae70 100644 --- a/go.sum +++ b/go.sum @@ -14,7 +14,6 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= @@ -55,7 +54,6 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coocood/freecache v1.1.0 h1:ENiHOsWdj1BrrlPwblhbn4GdAsMymK3pZORJ+bJGAjA= @@ -76,9 +74,7 @@ github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbT github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ericlagergren/decimal v0.0.0-20190912144844-2c3e3e1ef942 h1:Wm7GcUEhq0kioHEMLVVR9lyRezJsyzl9uLGnsQkijMU= github.com/ericlagergren/decimal v0.0.0-20190912144844-2c3e3e1ef942/go.mod h1:ZWP59etEywfyMG2lAqnoi3t8uoiZCiTmLtwt6iESIsQ= @@ -201,7 +197,6 @@ github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssy github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -352,7 +347,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index d75253a4f..c2833a2e0 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -437,28 +437,28 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr switch ta := a.(type) { case *DataEntryScriptAction: dataEntriesCount++ - if dataEntriesCount > maxDataEntryScriptActions { - return errors.Errorf("number of data entries produced by script is more than allowed %d", maxDataEntryScriptActions) + if dataEntriesCount > MaxDataEntryScriptActions { + return errors.Errorf("number of data entries produced by script is more than allowed %d", MaxDataEntryScriptActions) } switch restrictions.KeySizeValidationVersion { case 1: - if len(utf16.Encode([]rune(ta.Entry.GetKey()))) > maxKeySize { + if len(utf16.Encode([]rune(ta.Entry.GetKey()))) > MaxKeySize { return errs.NewTooBigArray("key is too large") } default: - if len([]byte(ta.Entry.GetKey())) > maxPBKeySize { + if len([]byte(ta.Entry.GetKey())) > MaxPBKeySize { return errs.NewTooBigArray("key is too large") } } dataEntriesSize += ta.Entry.BinarySize() - if dataEntriesSize > maxDataEntryScriptActionsSizeInBytes { - return errors.Errorf("total size of data entries produced by script is more than %d bytes", maxDataEntryScriptActionsSizeInBytes) + if dataEntriesSize > MaxDataEntryScriptActionsSizeInBytes { + return errors.Errorf("total size of data entries produced by script is more than %d bytes", MaxDataEntryScriptActionsSizeInBytes) } case *TransferScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.Amount < 0 { return errors.New("negative transfer amount") @@ -482,26 +482,26 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *IssueScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") } - if ta.Decimals < 0 || ta.Decimals > maxDecimals { + if ta.Decimals < 0 || ta.Decimals > MaxDecimals { return errors.New("invalid decimals") } - if l := len(ta.Name); l < minAssetNameLen || l > maxAssetNameLen { + if l := len(ta.Name); l < MinAssetNameLen || l > MaxAssetNameLen { return errors.New("invalid asset's name") } - if l := len(ta.Description); l > maxDescriptionLen { + if l := len(ta.Description); l > MaxDescriptionLen { return errors.New("invalid asset's description") } case *ReissueScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") @@ -509,8 +509,8 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *BurnScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") @@ -518,8 +518,8 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *SponsorshipScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.MinFee < 0 { return errors.New("negative minimal fee") @@ -527,8 +527,8 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *LeaseScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } if ta.Amount < 0 { return errors.New("negative leasing amount") @@ -547,8 +547,8 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *LeaseCancelScriptAction: otherActionsCount++ - if otherActionsCount > maxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) + if otherActionsCount > MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) } default: diff --git a/pkg/proto/transactions.go b/pkg/proto/transactions.go index fbb684b9b..ae389a956 100644 --- a/pkg/proto/transactions.go +++ b/pkg/proto/transactions.go @@ -52,10 +52,10 @@ const ( const ( maxAttachmentLengthBytes = 140 - maxDescriptionLen = 1000 - maxAssetNameLen = 16 - minAssetNameLen = 4 - maxDecimals = 8 + MaxDescriptionLen = 1000 + MaxAssetNameLen = 16 + MinAssetNameLen = 4 + MaxDecimals = 8 maxLongValue = ^uint64(0) >> 1 genesisBodyLen = 1 + 8 + AddressSize + 8 @@ -189,7 +189,7 @@ type Transaction interface { Validate() (Transaction, error) // Set transaction ID. - // For most transacions ID is hash of transaction body. + // For most transactions ID is hash of transaction body. // For Payment transactions ID is Signature. GenerateID(scheme Scheme) error // Sign transaction with given secret key. @@ -449,7 +449,7 @@ func (tx *Genesis) GenerateID(scheme Scheme) error { return tx.generateID(scheme) } -func (tx *Genesis) Sign(scheme Scheme, sk crypto.SecretKey) error { +func (tx *Genesis) Sign(scheme Scheme, _ crypto.SecretKey) error { if err := tx.generateID(scheme); err != nil { return err } @@ -701,7 +701,7 @@ func (tx Payment) GetVersion() byte { return tx.Version } -func (tx *Payment) GenerateID(scheme Scheme) error { +func (tx *Payment) GenerateID(_ Scheme) error { if tx.ID == nil { tx.ID = tx.Signature } @@ -1010,14 +1010,14 @@ func (i Issue) Valid() (bool, error) { if !validJVMLong(i.Fee) { return false, errors.New("fee is too big") } - if l := len(i.Name); l < minAssetNameLen || l > maxAssetNameLen { + if l := len(i.Name); l < MinAssetNameLen || l > MaxAssetNameLen { return false, errs.NewInvalidName("incorrect number of bytes in the asset's name") } - if l := len(i.Description); l > maxDescriptionLen { + if l := len(i.Description); l > MaxDescriptionLen { return false, errs.NewTooBigArray("incorrect number of bytes in the asset's description") } - if i.Decimals > maxDecimals { - return false, errs.NewTooBigArray(fmt.Sprintf("incorrect decimals, should be no more then %d", maxDecimals)) + if i.Decimals > MaxDecimals { + return false, errs.NewTooBigArray(fmt.Sprintf("incorrect decimals, should be no more then %d", MaxDecimals)) } return true, nil } diff --git a/pkg/proto/transactions_test.go b/pkg/proto/transactions_test.go index 7b085a72c..a2cd645c8 100644 --- a/pkg/proto/transactions_test.go +++ b/pkg/proto/transactions_test.go @@ -432,7 +432,7 @@ func TestIssueWithSigValidations(t *testing.T) { {"TOKEN", strings.Repeat("x", 1010), 1000000, 2, 100000, "incorrect number of bytes in the asset's description"}, {"TOKEN", "This is a valid description for the token", 0, 2, 100000, "quantity should be positive"}, {"TOKEN", "This is a valid description for the token", math.MaxInt64 + 100, 2, 100000, "quantity is too big"}, - {"TOKEN", "This is a valid description for the token", 100000, 12, 100000, fmt.Sprintf("incorrect decimals, should be no more then %d", maxDecimals)}, + {"TOKEN", "This is a valid description for the token", 100000, 12, 100000, fmt.Sprintf("incorrect decimals, should be no more then %d", MaxDecimals)}, {"TOKEN", "This is a valid description for the token", 100000, 2, 0, "fee should be positive"}, {"TOKEN", "This is a valid description for the token", 100000, 2, math.MaxInt64 + 100, "fee is too big"}, } @@ -610,7 +610,7 @@ func TestIssueWithProofsValidations(t *testing.T) { {"TOKEN", strings.Repeat("x", 1010), 1000000, 2, 100000, "incorrect number of bytes in the asset's description"}, {"TOKEN", "This is a valid description for the token", 0, 2, 100000, "quantity should be positive"}, {"TOKEN", "This is a valid description for the token", math.MaxInt64 + 1, 2, 100000, "quantity is too big"}, - {"TOKEN", "This is a valid description for the token", 100000, 12, 100000, fmt.Sprintf("incorrect decimals, should be no more then %d", maxDecimals)}, + {"TOKEN", "This is a valid description for the token", 100000, 12, 100000, fmt.Sprintf("incorrect decimals, should be no more then %d", MaxDecimals)}, {"TOKEN", "This is a valid description for the token", 100000, 2, 0, "fee should be positive"}, {"TOKEN", "This is a valid description for the token", 100000, 2, math.MaxInt64 + 1, "fee is too big"}, //TODO: add tests on script validation diff --git a/pkg/proto/transactions_with_proofs.go b/pkg/proto/transactions_with_proofs.go index 9dae0b0b2..9dfc7bfd8 100644 --- a/pkg/proto/transactions_with_proofs.go +++ b/pkg/proto/transactions_with_proofs.go @@ -4676,10 +4676,10 @@ func (tx *UpdateAssetInfoWithProofs) Validate() (Transaction, error) { if !validJVMLong(tx.Fee) { return tx, errors.New("fee is too big") } - if l := len(tx.Name); l < minAssetNameLen || l > maxAssetNameLen { + if l := len(tx.Name); l < MinAssetNameLen || l > MaxAssetNameLen { return tx, errs.NewInvalidName("incorrect number of bytes in the asset's name") } - if l := len(tx.Description); l > maxDescriptionLen { + if l := len(tx.Description); l > MaxDescriptionLen { return tx, errs.NewTooBigArray("incorrect number of bytes in the asset's description") } return tx, nil diff --git a/pkg/proto/types.go b/pkg/proto/types.go index b744213bb..a5dff32b4 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -42,13 +42,13 @@ const ( PriceConstant = 100000000 MaxOrderAmount = 100 * PriceConstant * PriceConstant MaxOrderTTL = uint64((30 * 24 * time.Hour) / time.Millisecond) - maxKeySize = 100 - maxPBKeySize = 400 + MaxKeySize = 100 + MaxPBKeySize = 400 maxValueSize = 32767 - maxScriptActions = 10 - maxDataEntryScriptActions = 100 - maxDataEntryScriptActionsSizeInBytes = 5 * 1024 + MaxScriptActions = 10 + MaxDataEntryScriptActions = 100 + MaxDataEntryScriptActionsSizeInBytes = 5 * 1024 ) type Timestamp = uint64 @@ -1789,11 +1789,11 @@ func (e IntegerDataEntry) Valid(version byte) error { } switch version { case 1: - if len(utf16.Encode([]rune(e.Key))) > maxKeySize { + if len(utf16.Encode([]rune(e.Key))) > MaxKeySize { return errs.NewTooBigArray("key is too large") } default: - if len([]byte(e.Key)) > maxPBKeySize { + if len([]byte(e.Key)) > MaxPBKeySize { return errs.NewTooBigArray("key is too large") } } @@ -1917,11 +1917,11 @@ func (e BooleanDataEntry) Valid(version byte) error { } switch version { case 1: - if len(utf16.Encode([]rune(e.Key))) > maxKeySize { + if len(utf16.Encode([]rune(e.Key))) > MaxKeySize { return errs.NewTooBigArray("key is too large11") } default: - if len([]byte(e.Key)) > maxPBKeySize { + if len([]byte(e.Key)) > MaxPBKeySize { return errs.NewTooBigArray("key is too large22") } } @@ -2049,11 +2049,11 @@ func (e BinaryDataEntry) Valid(version byte) error { } switch version { case 1: - if len(utf16.Encode([]rune(e.Key))) > maxKeySize { + if len(utf16.Encode([]rune(e.Key))) > MaxKeySize { return errs.NewTooBigArray("key is too large") } default: - if len([]byte(e.Key)) > maxPBKeySize { + if len([]byte(e.Key)) > MaxPBKeySize { return errs.NewTooBigArray("key is too large") } } @@ -2184,11 +2184,11 @@ func (e StringDataEntry) Valid(version byte) error { } switch version { case 1: - if len(utf16.Encode([]rune(e.Key))) > maxKeySize { + if len(utf16.Encode([]rune(e.Key))) > MaxKeySize { return errs.NewTooBigArray("key is too large") } default: - if len([]byte(e.Key)) > maxPBKeySize { + if len([]byte(e.Key)) > MaxPBKeySize { return errs.NewTooBigArray("key is too large") } } @@ -2318,11 +2318,11 @@ func (e DeleteDataEntry) Valid(version byte) error { } switch version { case 1: - if len(utf16.Encode([]rune(e.Key))) > maxKeySize { + if len(utf16.Encode([]rune(e.Key))) > MaxKeySize { return errs.NewTooBigArray("key is too large") } default: - if len([]byte(e.Key)) > maxPBKeySize { + if len([]byte(e.Key)) > MaxPBKeySize { return errs.NewTooBigArray("key is too large") } } diff --git a/pkg/ride/constants.go b/pkg/ride/constants.go index 15fc28ecf..78321617e 100644 --- a/pkg/ride/constants.go +++ b/pkg/ride/constants.go @@ -112,162 +112,162 @@ func checkConstantV5(name string) (uint16, bool) { return 0, false } -func newBuy(RideEnvironment) rideType { +func newBuy(Environment) rideType { return rideNamedType{name: "Buy"} } -func createBuy(env RideEnvironment, args ...rideType) (rideType, error) { +func createBuy(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Buy"}, nil } -func newCeiling(RideEnvironment) rideType { +func newCeiling(Environment) rideType { return rideNamedType{name: "Ceiling"} } -func createCeiling(env RideEnvironment, args ...rideType) (rideType, error) { +func createCeiling(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Ceiling"}, nil } -func newDown(RideEnvironment) rideType { +func newDown(Environment) rideType { return rideNamedType{name: "Down"} } -func createDown(env RideEnvironment, args ...rideType) (rideType, error) { +func createDown(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Down"}, nil } -func newFloor(RideEnvironment) rideType { +func newFloor(Environment) rideType { return rideNamedType{name: "Floor"} } -func createFloor(env RideEnvironment, args ...rideType) (rideType, error) { +func createFloor(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Floor"}, nil } -func newHalfDown(RideEnvironment) rideType { +func newHalfDown(Environment) rideType { return rideNamedType{name: "HalfDown"} } -func createHalfDown(env RideEnvironment, args ...rideType) (rideType, error) { +func createHalfDown(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "HalfDown"}, nil } -func newHalfEven(RideEnvironment) rideType { +func newHalfEven(Environment) rideType { return rideNamedType{name: "HalfEven"} } -func createHalfEven(env RideEnvironment, args ...rideType) (rideType, error) { +func createHalfEven(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "HalfEven"}, nil } -func newHalfUp(RideEnvironment) rideType { +func newHalfUp(Environment) rideType { return rideNamedType{name: "HalfUp"} } -func createHalfUp(env RideEnvironment, args ...rideType) (rideType, error) { +func createHalfUp(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "HalfUp"}, nil } -func newMd5(RideEnvironment) rideType { +func newMd5(Environment) rideType { return rideNamedType{name: "Md5"} } -func createMd5(env RideEnvironment, args ...rideType) (rideType, error) { +func createMd5(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Md5"}, nil } -func newNoAlg(RideEnvironment) rideType { +func newNoAlg(Environment) rideType { return rideNamedType{name: "NoAlg"} } -func createNoAlg(env RideEnvironment, args ...rideType) (rideType, error) { +func createNoAlg(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "NoAlg"}, nil } -func newSha1(RideEnvironment) rideType { +func newSha1(Environment) rideType { return rideNamedType{name: "Sha1"} } -func createSha1(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha1(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha1"}, nil } -func newSha224(RideEnvironment) rideType { +func newSha224(Environment) rideType { return rideNamedType{name: "Sha224"} } -func createSha224(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha224(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha224"}, nil } -func newSha256(RideEnvironment) rideType { +func newSha256(Environment) rideType { return rideNamedType{name: "Sha256"} } -func createSha256(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha256(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha256"}, nil } -func newSha3224(RideEnvironment) rideType { +func newSha3224(Environment) rideType { return rideNamedType{name: "Sha3224"} } -func createSha3224(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha3224(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3224"}, nil } -func newSha3256(RideEnvironment) rideType { +func newSha3256(Environment) rideType { return rideNamedType{name: "Sha3256"} } -func createSha3256(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha3256(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3256"}, nil } -func newSha3384(RideEnvironment) rideType { +func newSha3384(Environment) rideType { return rideNamedType{name: "Sha3384"} } -func createSha3384(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha3384(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3384"}, nil } -func newSha3512(RideEnvironment) rideType { +func newSha3512(Environment) rideType { return rideNamedType{name: "Sha3512"} } -func createSha3512(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha3512(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha3512"}, nil } -func newSha384(RideEnvironment) rideType { +func newSha384(Environment) rideType { return rideNamedType{name: "Sha384"} } -func createSha384(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha384(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha384"}, nil } -func newSha512(RideEnvironment) rideType { +func newSha512(Environment) rideType { return rideNamedType{name: "Sha512"} } -func createSha512(env RideEnvironment, args ...rideType) (rideType, error) { +func createSha512(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sha512"}, nil } -func newSell(RideEnvironment) rideType { +func newSell(Environment) rideType { return rideNamedType{name: "Sell"} } -func createSell(env RideEnvironment, args ...rideType) (rideType, error) { +func createSell(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Sell"}, nil } -func newUp(RideEnvironment) rideType { +func newUp(Environment) rideType { return rideNamedType{name: "Up"} } -func createUp(env RideEnvironment, args ...rideType) (rideType, error) { +func createUp(env Environment, args ...rideType) (rideType, error) { return rideNamedType{name: "Up"}, nil } diff --git a/pkg/ride/constructors.go b/pkg/ride/constructors.go index adb7e0e15..08b0fbdc5 100644 --- a/pkg/ride/constructors.go +++ b/pkg/ride/constructors.go @@ -1,13 +1,13 @@ package ride -func newHeight(env RideEnvironment) rideType { +func newHeight(env Environment) rideType { if env == nil { return rideUnit{} } return env.height() } -func newTx(env RideEnvironment) rideType { +func newTx(env Environment) rideType { if env == nil { return rideUnit{} } @@ -18,7 +18,7 @@ func newTx(env RideEnvironment) rideType { return tx } -func newLastBlock(env RideEnvironment) rideType { +func newLastBlock(env Environment) rideType { if env == nil { return rideUnit{} } @@ -29,7 +29,7 @@ func newLastBlock(env RideEnvironment) rideType { return b } -func newThis(env RideEnvironment) rideType { +func newThis(env Environment) rideType { if env == nil { return rideUnit{} } @@ -40,7 +40,7 @@ func newThis(env RideEnvironment) rideType { return this } -func newInvocation(env RideEnvironment) rideType { +func newInvocation(env Environment) rideType { if env == nil { return rideUnit{} } @@ -51,10 +51,10 @@ func newInvocation(env RideEnvironment) rideType { return inv } -func newUnit(RideEnvironment) rideType { +func newUnit(Environment) rideType { return rideUnit{} } -func newNil(RideEnvironment) rideType { +func newNil(Environment) rideType { return rideList(nil) } diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index 8fb579fda..610cb9440 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -979,7 +979,7 @@ func balanceDetailsToObject(fwb *proto.FullWavesBalance) rideObject { return r } -func objectToActions(env RideEnvironment, obj rideType) ([]proto.ScriptAction, error) { +func objectToActions(env Environment, obj rideType) ([]proto.ScriptAction, error) { switch obj.instanceOf() { case "WriteSet": data, err := obj.get("data") @@ -1057,7 +1057,7 @@ func getKeyProperty(v rideType) (string, error) { return string(key), nil } -func convertToAction(env RideEnvironment, obj rideType) (proto.ScriptAction, error) { +func convertToAction(env Environment, obj rideType) (proto.ScriptAction, error) { switch obj.instanceOf() { case "Burn": id, err := digestProperty(obj, "assetId") diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index b02adcb8a..ca63d2086 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1,51 +1,106 @@ package ride import ( + "unicode/utf16" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/wavesplatform/gowaves/pkg/errs" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/types" ) -func (wrappedSt *wrappedState) AddingBlockHeight() (uint64, error) { - return wrappedSt.diff.state.AddingBlockHeight() +type WrappedState struct { + diff diffState + cle rideAddress + scheme proto.Scheme + invokeCount uint64 + act []proto.ScriptAction +} + +func newWrappedState(env *EvaluationEnvironment) *WrappedState { + dataEntries := diffDataEntries{ + diffInteger: map[string]proto.IntegerDataEntry{}, + diffBool: map[string]proto.BooleanDataEntry{}, + diffString: map[string]proto.StringDataEntry{}, + diffBinary: map[string]proto.BinaryDataEntry{}, + diffDDelete: map[string]proto.DeleteDataEntry{}, + } + diffSt := diffState{ + state: env.st, + dataEntries: dataEntries, + balances: map[string]diffBalance{}, + sponsorships: map[string]diffSponsorship{}, + newAssetsInfo: map[string]diffNewAssetInfo{}, + oldAssetsInfo: map[string]diffOldAssetInfo{}, + leases: map[string]lease{}} + + return &WrappedState{diff: diffSt, cle: env.th.(rideAddress), scheme: env.sch} +} + +func (ws *WrappedState) appendActions(actions []proto.ScriptAction) { + ws.act = append(ws.act, actions...) +} + +func (ws *WrappedState) callee() proto.Address { + return proto.Address(ws.cle) } -func (wrappedSt *wrappedState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { - return wrappedSt.diff.state.NewestLeasingInfo(id, filter) +func (ws *WrappedState) smartAppendActions(actions []proto.ScriptAction, env Environment) error { + modifiedActions, err := ws.ApplyToState(actions, env) + if err != nil { + return err + } + ws.appendActions(modifiedActions) + return nil +} + +func (ws *WrappedState) AddingBlockHeight() (uint64, error) { + return ws.diff.state.AddingBlockHeight() +} + +func (ws *WrappedState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + return ws.diff.state.NewestLeasingInfo(id, filter) } -func (wrappedSt *wrappedState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return wrappedSt.diff.state.NewestScriptPKByAddr(addr, filter) +func (ws *WrappedState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { + return ws.diff.state.NewestScriptPKByAddr(addr, filter) } -func (wrappedSt *wrappedState) NewestTransactionByID(id []byte) (proto.Transaction, error) { - return wrappedSt.diff.state.NewestTransactionByID(id) +func (ws *WrappedState) NewestTransactionByID(id []byte) (proto.Transaction, error) { + return ws.diff.state.NewestTransactionByID(id) } -func (wrappedSt *wrappedState) NewestTransactionHeightByID(id []byte) (uint64, error) { - return wrappedSt.diff.state.NewestTransactionHeightByID(id) +func (ws *WrappedState) NewestTransactionHeightByID(id []byte) (uint64, error) { + return ws.diff.state.NewestTransactionHeightByID(id) } -func (wrappedSt *wrappedState) GetByteTree(recipient proto.Recipient) (proto.Script, error) { - return wrappedSt.diff.state.GetByteTree(recipient) +func (ws *WrappedState) GetByteTree(recipient proto.Recipient) (proto.Script, error) { + return ws.diff.state.GetByteTree(recipient) } -func (wrappedSt *wrappedState) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { - return wrappedSt.diff.state.NewestRecipientToAddress(recipient) +func (ws *WrappedState) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { + return ws.diff.state.NewestRecipientToAddress(recipient) } -func (wrappedSt *wrappedState) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) { - return wrappedSt.diff.state.NewestAddrByAlias(alias) +func (ws *WrappedState) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) { + return ws.diff.state.NewestAddrByAlias(alias) } -func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { - balance, err := wrappedSt.diff.state.NewestAccountBalance(account, assetID) +func (ws *WrappedState) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { + balance, err := ws.diff.state.NewestAccountBalance(account, assetID) if err != nil { return 0, err } + var asset *proto.OptionalAsset - asset, err := proto.NewOptionalAssetFromBytes(assetID) - if err != nil { - return 0, err + if isAssetWaves(assetID) { + waves := proto.NewOptionalAssetWaves() + asset = &waves + } else { + asset, err = proto.NewOptionalAssetFromBytes(assetID) + if err != nil { + return 0, err + } } - balanceDiff, _, err := wrappedSt.diff.findBalance(account, *asset) + + balanceDiff, _, err := ws.diff.findBalance(account, *asset) if err != nil { return 0, err } @@ -57,12 +112,12 @@ func (wrappedSt *wrappedState) NewestAccountBalance(account proto.Recipient, ass return balance, nil } -func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance, err := wrappedSt.diff.state.NewestFullWavesBalance(account) +func (ws *WrappedState) NewestFullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { + balance, err := ws.diff.state.NewestFullWavesBalance(account) if err != nil { return nil, err } - wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, proto.NewOptionalAssetWaves()) + wavesBalanceDiff, searchAddress, err := ws.diff.findBalance(account, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } @@ -73,12 +128,12 @@ func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) ( resLeaseIn := wavesBalanceDiff.leaseIn + int64(balance.LeaseIn) resLeaseOut := wavesBalanceDiff.leaseOut + int64(balance.LeaseOut) - err := wrappedSt.diff.addEffectiveToHistory(searchAddress, resEffective) + err := ws.diff.addEffectiveToHistory(searchAddress, resEffective) if err != nil { return nil, err } - resGenerating := wrappedSt.diff.findMinGenerating(wrappedSt.diff.balances[searchAddress].effectiveHistory, int64(balance.Generating)) + resGenerating := ws.diff.findMinGenerating(ws.diff.balances[searchAddress].effectiveHistory, int64(balance.Generating)) return &proto.FullWavesBalance{ Regular: uint64(resRegular), @@ -89,96 +144,95 @@ func (wrappedSt *wrappedState) NewestFullWavesBalance(account proto.Recipient) ( LeaseOut: uint64(resLeaseOut)}, nil } - _, searchAddr := wrappedSt.diff.createNewWavesBalance(account) - err = wrappedSt.diff.addEffectiveToHistory(searchAddr, int64(balance.Effective)) + _, searchAddr := ws.diff.createNewWavesBalance(account) + err = ws.diff.addEffectiveToHistory(searchAddr, int64(balance.Effective)) if err != nil { return nil, err } return balance, nil } -func (wrappedSt *wrappedState) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) +func (ws *WrappedState) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + address, err := ws.diff.state.NewestRecipientToAddress(account) if err != nil { return nil, err } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + if deletedDataEntry := ws.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { return nil, nil } - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { + if intDataEntry := ws.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { return intDataEntry, nil } - return wrappedSt.diff.state.RetrieveNewestIntegerEntry(account, key) + return ws.diff.state.RetrieveNewestIntegerEntry(account, key) } -func (wrappedSt *wrappedState) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) +func (ws *WrappedState) RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + address, err := ws.diff.state.NewestRecipientToAddress(account) if err != nil { return nil, err } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + if deletedDataEntry := ws.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { return nil, nil } - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { + if boolDataEntry := ws.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { return boolDataEntry, nil } - return wrappedSt.diff.state.RetrieveNewestBooleanEntry(account, key) + return ws.diff.state.RetrieveNewestBooleanEntry(account, key) } -func (wrappedSt *wrappedState) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) +func (ws *WrappedState) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + address, err := ws.diff.state.NewestRecipientToAddress(account) if err != nil { return nil, err } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + if deletedDataEntry := ws.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { return nil, nil } - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { + if stringDataEntry := ws.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { return stringDataEntry, nil } - return wrappedSt.diff.state.RetrieveNewestStringEntry(account, key) + return ws.diff.state.RetrieveNewestStringEntry(account, key) } -func (wrappedSt *wrappedState) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) +func (ws *WrappedState) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + address, err := ws.diff.state.NewestRecipientToAddress(account) if err != nil { return nil, err } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { + if deletedDataEntry := ws.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { return nil, nil } - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { + if binaryDataEntry := ws.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { return binaryDataEntry, nil } - return wrappedSt.diff.state.RetrieveNewestBinaryEntry(account, key) + return ws.diff.state.RetrieveNewestBinaryEntry(account, key) } -func (wrappedSt *wrappedState) NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { +func (ws *WrappedState) NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) { + if cost := ws.diff.findSponsorship(assetID); cost != nil { if *cost == 0 { return false, nil } return true, nil } - return wrappedSt.diff.state.NewestAssetIsSponsored(assetID) + return ws.diff.state.NewestAssetIsSponsored(assetID) } -func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { - // TODO - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) +func (ws *WrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { + searchNewAsset := ws.diff.findNewAsset(assetID) if searchNewAsset == nil { - assetFromStore, err := wrappedSt.diff.state.NewestAssetInfo(assetID) + assetFromStore, err := ws.diff.state.NewestAssetInfo(assetID) if err != nil { return nil, errors.Wrap(err, "failed to get asset's info from store") } - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + if oldAssetFromDiff := ws.diff.findOldAsset(assetID); oldAssetFromDiff != nil { quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity assetFromStore.Quantity = uint64(quantity) @@ -188,7 +242,7 @@ func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.As return assetFromStore, nil } - issuerPK, err := wrappedSt.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) if err != nil { return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") } @@ -198,7 +252,7 @@ func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.As scripted = true } - sponsored, err := wrappedSt.NewestAssetIsSponsored(assetID) + sponsored, err := ws.NewestAssetIsSponsored(assetID) if err != nil { return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") } @@ -214,17 +268,17 @@ func (wrappedSt *wrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.As Sponsored: sponsored, }, nil } -func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) +func (ws *WrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { + searchNewAsset := ws.diff.findNewAsset(assetID) if searchNewAsset == nil { - assetFromStore, err := wrappedSt.diff.state.NewestFullAssetInfo(assetID) + assetFromStore, err := ws.diff.state.NewestFullAssetInfo(assetID) if err != nil { return nil, errors.Wrap(err, "failed to get asset's info from store") } - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { + if oldAssetFromDiff := ws.diff.findOldAsset(assetID); oldAssetFromDiff != nil { quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity if quantity >= 0 { @@ -238,7 +292,7 @@ func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*prot return assetFromStore, nil } - issuerPK, err := wrappedSt.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) if err != nil { return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") } @@ -248,7 +302,7 @@ func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*prot scripted = true } - sponsored, err := wrappedSt.NewestAssetIsSponsored(assetID) + sponsored, err := ws.NewestAssetIsSponsored(assetID) if err != nil { return nil, errors.Wrap(err, "failed to find out sponsoring of the asset") } @@ -268,7 +322,7 @@ func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*prot } sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { + if sponsorship := ws.diff.findSponsorship(assetID); sponsorship != nil { sponsorshipCost = *sponsorship } @@ -281,88 +335,421 @@ func (wrappedSt *wrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*prot }, nil } -func (wrappedSt *wrappedState) NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { - return wrappedSt.diff.state.NewestHeaderByHeight(height) +func (ws *WrappedState) NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { + return ws.diff.state.NewestHeaderByHeight(height) +} +func (ws *WrappedState) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) { + return ws.diff.state.BlockVRF(blockHeader, height) +} + +func (ws *WrappedState) EstimatorVersion() (int, error) { + return ws.diff.state.EstimatorVersion() +} +func (ws *WrappedState) IsNotFound(err error) bool { + return ws.diff.state.IsNotFound(err) +} + +func (ws *WrappedState) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) { + return ws.diff.state.NewestScriptByAsset(asset) +} + +func (ws *WrappedState) validateAsset(action proto.ScriptAction, asset proto.OptionalAsset, env Environment) (bool, error) { + if !asset.Present { + return true, nil + } + + assetInfo, err := ws.NewestAssetInfo(asset.ID) + if err != nil { + return false, err + } + if !assetInfo.Scripted { + return true, nil + } + + txID, err := crypto.NewDigestFromBytes(env.txID().(rideBytes)) + if err != nil { + return false, err + } + + timestamp := env.timestamp() + + localEnv, err := NewEnvironment(env.scheme(), env.state()) + if err != nil { + return false, err + } + + switch res := action.(type) { + + case *proto.TransferScriptAction: + sender, err := proto.NewAddressFromPublicKey(localEnv.scheme(), *res.Sender) + if err != nil { + return false, err + } + + fullTr := &proto.FullScriptTransfer{ + Amount: uint64(res.Amount), + Asset: res.Asset, + Recipient: res.Recipient, + Sender: sender, + Timestamp: timestamp, + ID: &txID, + } + localEnv.SetTransactionFromScriptTransfer(fullTr) + + case *proto.ReissueScriptAction, *proto.BurnScriptAction: + err = localEnv.SetTransactionFromScriptAction(action, *action.SenderPK(), txID, timestamp) + if err != nil { + return false, err + } + + } + + script, err := ws.NewestScriptByAsset(asset) + if err != nil { + return false, err + } + + tree, err := Parse(script) + if err != nil { + return false, errors.Wrap(err, "failed to get tree by script") + } + + localEnv.ChooseSizeCheck(tree.LibVersion) + switch tree.LibVersion { + case 4, 5: + assetInfo, err := ws.NewestFullAssetInfo(asset.ID) + if err != nil { + return false, err + } + localEnv.SetThisFromFullAssetInfo(assetInfo) + default: + assetInfo, err := ws.NewestAssetInfo(asset.ID) + if err != nil { + return false, err + } + localEnv.SetThisFromAssetInfo(assetInfo) + } + r, err := CallVerifier(localEnv, tree) + if err != nil { + return false, errors.Wrapf(err, "failed to call script on asset '%s'", asset.String()) + } + if !r.Result() { + return false, errs.NewTransactionNotAllowedByScript(r.UserError(), asset.ID.Bytes()) + } + + return r.Result(), nil +} + +func (ws *WrappedState) validateTransferAction(otherActionsCount *int, res *proto.TransferScriptAction, restrictions proto.ActionsValidationRestrictions, sender proto.Address, env Environment) error { + *otherActionsCount++ + + assetResult, err := ws.validateAsset(res, res.Asset, env) + if err != nil { + return errors.Wrapf(err, "failed to validate asset") + } + if !assetResult { + return errors.New("action is forbidden by smart asset script") + } + + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.Amount < 0 { + return errors.New("negative transfer amount") + } + if res.InvalidAsset { + return errors.New("invalid asset") + } + if restrictions.DisableSelfTransfers { + senderAddress := restrictions.ScriptAddress + if res.SenderPK() != nil { + var err error + senderAddress, err = proto.NewAddressFromPublicKey(restrictions.Scheme, *res.SenderPK()) + if err != nil { + return errors.Wrap(err, "failed to validate TransferScriptAction") + } + } + if res.Recipient.Address.Eq(senderAddress) { + return errors.New("transfers to DApp itself are forbidden since activation of RIDE V4") + } + } + senderRcp := proto.NewRecipientFromAddress(sender) + balance, err := ws.NewestAccountBalance(senderRcp, res.Asset.ID.Bytes()) + if err != nil { + return err + } + + if balance < uint64(res.Amount) { + return errors.Errorf("not enough money in the DApp. balance of DApp with address %s is %d and it tried to transfer asset %s to %s, amount of %d", + sender.String(), balance, res.Asset.String(), res.Recipient.Address.String(), res.Amount) + } + + return nil +} + +func (ws *WrappedState) validateDataEntryAction(dataEntriesCount *int, dataEntriesSize *int, res *proto.DataEntryScriptAction, restrictions proto.ActionsValidationRestrictions) error { + *dataEntriesCount++ + if *dataEntriesCount > proto.MaxDataEntryScriptActions { + return errors.Errorf("number of data entries produced by script is more than allowed %d", proto.MaxDataEntryScriptActions) + } + switch restrictions.KeySizeValidationVersion { + case 1: + if len(utf16.Encode([]rune(res.Entry.GetKey()))) > proto.MaxKeySize { + return errs.NewTooBigArray("key is too large") + } + default: + if len([]byte(res.Entry.GetKey())) > proto.MaxPBKeySize { + return errs.NewTooBigArray("key is too large") + } + } + + *dataEntriesSize += res.Entry.BinarySize() + if *dataEntriesSize > proto.MaxDataEntryScriptActionsSizeInBytes { + return errors.Errorf("total size of data entries produced by script is more than %d bytes", proto.MaxDataEntryScriptActionsSizeInBytes) + } + return nil +} + +func (ws *WrappedState) validateIssueAction(otherActionsCount *int, res *proto.IssueScriptAction) error { + *otherActionsCount++ + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.Quantity < 0 { + return errors.New("negative quantity") + } + if res.Decimals < 0 || res.Decimals > proto.MaxDecimals { + return errors.New("invalid decimals") + } + if l := len(res.Name); l < proto.MinAssetNameLen || l > proto.MaxAssetNameLen { + return errors.New("invalid asset's name") + } + if l := len(res.Description); l > proto.MaxDescriptionLen { + return errors.New("invalid asset's description") + } + return nil +} + +func (ws *WrappedState) validateReissueAction(otherActionsCount *int, res *proto.ReissueScriptAction, env Environment) error { + *otherActionsCount++ + + asset := proto.NewOptionalAssetFromDigest(res.AssetID) + assetResult, err := ws.validateAsset(res, *asset, env) + if err != nil { + return errors.Wrapf(err, "failed to validate asset") + } + if !assetResult { + return errors.New("action is forbidden by smart asset script") + } + + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.Quantity < 0 { + return errors.New("negative quantity") + } + + assetInfo, err := ws.NewestAssetInfo(res.AssetID) + if err != nil { + return err + } + + if !assetInfo.Reissuable { + return errors.New("failed to reissue asset as it's not reissuable anymore") + } + + return nil +} + +func (ws *WrappedState) validateBurnAction(otherActionsCount *int, res *proto.BurnScriptAction, env Environment) error { + *otherActionsCount++ + + asset := proto.NewOptionalAssetFromDigest(res.AssetID) + assetResult, err := ws.validateAsset(res, *asset, env) + if err != nil { + return errors.Wrapf(err, "failed to validate asset") + } + if !assetResult { + return errors.New("action is forbidden by smart asset script") + } + + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.Quantity < 0 { + return errors.New("negative quantity") + } + assetInfo, err := ws.NewestAssetInfo(res.AssetID) + if err != nil { + return err + } + + if assetInfo.Quantity < uint64(res.Quantity) { + return errors.New("quantity of asset is less than what was tried to burn") + } + + return nil +} + +func (ws *WrappedState) validateSponsorshipAction(otherActionsCount *int, res *proto.SponsorshipScriptAction) error { + *otherActionsCount++ + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.MinFee < 0 { + return errors.New("negative minimal fee") + } + + return nil +} + +func (ws *WrappedState) validateLeaseAction(otherActionsCount *int, res *proto.LeaseScriptAction, restrictions proto.ActionsValidationRestrictions) error { + *otherActionsCount++ + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + if res.Amount < 0 { + return errors.New("negative leasing amount") + } + senderAddress := restrictions.ScriptAddress + if res.SenderPK() != nil { + var err error + senderAddress, err = proto.NewAddressFromPublicKey(restrictions.Scheme, *res.SenderPK()) + if err != nil { + return errors.Wrap(err, "failed to validate TransferScriptAction") + } + } + if res.Recipient.Address.Eq(senderAddress) { + return errors.New("leasing to DApp itself is forbidden") + } + + balance, err := ws.NewestFullWavesBalance(proto.NewRecipientFromAddress(ws.callee())) + if err != nil { + return err + } + if balance.Available < uint64(res.Amount) { + return errors.New("not enough money on the available balance of the account") + } + return nil +} + +func (ws *WrappedState) validateLeaseCancelAction(otherActionsCount *int) error { + *otherActionsCount++ + if *otherActionsCount > proto.MaxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + } + return nil } -func (wrappedSt *wrappedState) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) { - return wrappedSt.diff.state.BlockVRF(blockHeader, height) + +func (ws *WrappedState) getLibVersion() (int, error) { + script, err := ws.GetByteTree(proto.NewRecipientFromAddress(ws.callee())) + if err != nil { + return 0, errors.Wrap(err, "failed to get script by recipient") + } + tree, err := Parse(script) + if err != nil { + return 0, errors.Wrap(err, "failed to get tree by script") + } + return tree.LibVersion, nil } -func (wrappedSt *wrappedState) EstimatorVersion() (int, error) { - return wrappedSt.diff.state.EstimatorVersion() +func (ws *WrappedState) invCount() uint64 { + return ws.invokeCount } -func (wrappedSt *wrappedState) IsNotFound(err error) bool { - return wrappedSt.diff.state.IsNotFound(err) + +func (ws *WrappedState) incrementInvCount() { + ws.invokeCount++ } -func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { +func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environment) ([]proto.ScriptAction, error) { + dataEntriesCount := 0 + dataEntriesSize := 0 + otherActionsCount := 0 + libVersion, err := ws.getLibVersion() + if err != nil { + return nil, err + } + + disableSelfTransfers := libVersion >= 4 + var keySizeValidationVersion byte = 1 + if libVersion >= 4 { + keySizeValidationVersion = 2 + } + restrictions := proto.ActionsValidationRestrictions{ + DisableSelfTransfers: disableSelfTransfers, + KeySizeValidationVersion: keySizeValidationVersion, + } for _, action := range actions { switch res := action.(type) { case *proto.DataEntryScriptAction: + err := ws.validateDataEntryAction(&dataEntriesCount, &dataEntriesSize, res, restrictions) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of data entry action") + } switch dataEntry := res.Entry.(type) { case *proto.IntegerDataEntry: + addr := ws.callee() + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = &senderPK + intEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry + ws.diff.dataEntries.diffInteger[dataEntry.Key+addr.String()] = intEntry - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + case *proto.StringDataEntry: + addr := ws.callee() + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK - case *proto.StringDataEntry: stringEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry + ws.diff.dataEntries.diffString[dataEntry.Key+addr.String()] = stringEntry - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + case *proto.BooleanDataEntry: + addr := ws.callee() + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK - case *proto.BooleanDataEntry: boolEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry + ws.diff.dataEntries.diffBool[dataEntry.Key+addr.String()] = boolEntry - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + case *proto.BinaryDataEntry: + addr := ws.callee() + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK - case *proto.BinaryDataEntry: binaryEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry + ws.diff.dataEntries.diffBinary[dataEntry.Key+addr.String()] = binaryEntry - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) + case *proto.DeleteDataEntry: + addr := ws.callee() + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK - - case *proto.DeleteDataEntry: deleteEntry := *dataEntry - addr := proto.Address(wrappedSt.envThis) - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry + ws.diff.dataEntries.diffDDelete[dataEntry.Key+addr.String()] = deleteEntry - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(addr, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK default: } @@ -373,56 +760,71 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro if res.Sender != nil { senderPK = *res.Sender var err error - senderAddress, err = proto.NewAddressFromPublicKey(wrappedSt.envScheme, senderPK) + senderAddress, err = proto.NewAddressFromPublicKey(ws.scheme, senderPK) if err != nil { return nil, errors.Wrap(err, "failed to get address by public key") } } else { - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } senderPK = pk + senderAddress = ws.callee() + + res.Sender = &senderPK + } - senderAddress = proto.Address(wrappedSt.envThis) + err = ws.validateTransferAction(&otherActionsCount, res, restrictions, senderAddress, env) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of transfer action or attached payments") } - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset) + + searchBalance, searchAddr, err := ws.diff.findBalance(res.Recipient, res.Asset) if err != nil { return nil, err } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) + err = ws.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) if err != nil { return nil, err } senderRecipient := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset) + senderSearchBalance, senderSearchAddr, err := ws.diff.findBalance(senderRecipient, res.Asset) if err != nil { return nil, err } - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecipient) + err = ws.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecipient) if err != nil { return nil, err } + case *proto.SponsorshipScriptAction: + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } res.Sender = &senderPK - case *proto.SponsorshipScriptAction: + err = ws.validateSponsorshipAction(&otherActionsCount, res) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of issue action") + } + var sponsorship diffSponsorship sponsorship.MinFee = res.MinFee - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship + ws.diff.sponsorships[res.AssetID.String()] = sponsorship - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + case *proto.IssueScriptAction: + err := ws.validateIssueAction(&otherActionsCount, res) if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") + return nil, errors.Wrapf(err, "failed to pass validation of issue action") } - res.Sender = &senderPK - case *proto.IssueScriptAction: var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) + assetInfo.dAppIssuer = ws.callee() assetInfo.name = res.Name assetInfo.description = res.Description assetInfo.quantity = res.Quantity @@ -431,85 +833,129 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro assetInfo.script = res.Script assetInfo.nonce = res.Nonce - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo + ws.diff.newAssetsInfo[res.ID.String()] = assetInfo - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK + senderRcp := proto.NewRecipientFromAddress(ws.callee()) + asset := proto.NewOptionalAssetFromDigest(res.ID) + searchBalance, searchAddr, err := ws.diff.findBalance(senderRcp, *asset) + if err != nil { + return nil, err + } + err = ws.diff.changeBalance(searchBalance, searchAddr, res.Quantity, asset.ID, senderRcp) + if err != nil { + return nil, err + } + case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + if err != nil { + return nil, errors.Wrap(err, "failed to get public key by address") + } + res.Sender = &senderPK + + err = ws.validateReissueAction(&otherActionsCount, res, env) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of issue action") + } + + searchNewAsset := ws.diff.findNewAsset(res.AssetID) if searchNewAsset == nil { - var assetInfo diffOldAssetInfo + if oldAssetFromDiff := ws.diff.findOldAsset(res.AssetID); oldAssetFromDiff != nil { + oldAssetFromDiff.diffQuantity += res.Quantity + ws.diff.oldAssetsInfo[res.AssetID.String()] = *oldAssetFromDiff + break + } + var assetInfo diffOldAssetInfo assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + ws.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo break } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) + ws.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + case *proto.BurnScriptAction: + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } res.Sender = &senderPK - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity + err = ws.validateBurnAction(&otherActionsCount, res, env) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of issue action") + } - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo + searchAsset := ws.diff.findNewAsset(res.AssetID) + if searchAsset == nil { + if oldAssetFromDiff := ws.diff.findOldAsset(res.AssetID); oldAssetFromDiff != nil { + oldAssetFromDiff.diffQuantity -= res.Quantity + ws.diff.oldAssetsInfo[res.AssetID.String()] = *oldAssetFromDiff + break + } + var assetInfo diffOldAssetInfo + assetInfo.diffQuantity -= res.Quantity + ws.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo break } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) + ws.diff.burnNewAsset(res.AssetID, res.Quantity) - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) + case *proto.LeaseScriptAction: + senderAddress := ws.callee() + pk, err := ws.diff.state.NewestScriptPKByAddr(senderAddress, false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - res.Sender = &senderPK - case *proto.LeaseScriptAction: - senderAddress := proto.Address(wrappedSt.envThis) + res.Sender = &pk + + err = ws.validateLeaseAction(&otherActionsCount, res, restrictions) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of issue action") + } - recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, proto.NewOptionalAssetWaves()) + recipientSearchBalance, recipientSearchAddress, err := ws.diff.findBalance(res.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } - err = wrappedSt.diff.changeLeaseIn(recipientSearchBalance, recipientSearchAddress, res.Amount, res.Recipient) + err = ws.diff.changeLeaseIn(recipientSearchBalance, recipientSearchAddress, res.Amount, res.Recipient) if err != nil { return nil, err } senderAccount := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, proto.NewOptionalAssetWaves()) + senderSearchBalance, senderSearchAddr, err := ws.diff.findBalance(senderAccount, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } - err = wrappedSt.diff.changeLeaseOut(senderSearchBalance, senderSearchAddr, res.Amount, senderAccount) + err = ws.diff.changeLeaseOut(senderSearchBalance, senderSearchAddr, res.Amount, senderAccount) if err != nil { return nil, err } - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(senderAddress, false) + ws.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) + + case *proto.LeaseCancelScriptAction: + pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } - wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) - res.Sender = &pk - case *proto.LeaseCancelScriptAction: - searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) + err = ws.validateLeaseCancelAction(&otherActionsCount) + if err != nil { + return nil, errors.Wrapf(err, "failed to pass validation of issue action") + } + + searchLease, err := ws.diff.findLeaseByIDForCancel(res.LeaseID) if err != nil { return nil, errors.Errorf("failed to find lease by leaseID") } @@ -517,98 +963,110 @@ func (wrappedSt *wrappedState) ApplyToState(actions []proto.ScriptAction) ([]pro return nil, errors.Errorf("there is no lease to cancel") } - recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, proto.NewOptionalAssetWaves()) + recipientBalance, recipientSearchAddress, err := ws.diff.findBalance(searchLease.Recipient, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } if recipientBalance == nil { - _, recipientSearchAddress = wrappedSt.diff.createNewWavesBalance(searchLease.Recipient) + _, recipientSearchAddress = ws.diff.createNewWavesBalance(searchLease.Recipient) } - senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, proto.NewOptionalAssetWaves()) + senderBalance, senderSearchAddress, err := ws.diff.findBalance(searchLease.Sender, proto.NewOptionalAssetWaves()) if err != nil { return nil, err } if senderBalance == nil { - _, senderSearchAddress = wrappedSt.diff.createNewWavesBalance(searchLease.Sender) + _, senderSearchAddress = ws.diff.createNewWavesBalance(searchLease.Sender) } - wrappedSt.diff.cancelLease(*searchLease, senderSearchAddress, recipientSearchAddress) - - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } + ws.diff.cancelLease(*searchLease, senderSearchAddress, recipientSearchAddress) - res.Sender = &pk default: } } return actions, nil } -type wrappedState struct { - diff diffState - envThis rideAddress - envScheme proto.Scheme +type EvaluationEnvironment struct { + sch proto.Scheme + st types.SmartState + h rideInt + tx rideObject + id rideType + th rideType + time uint64 + b rideObject + check func(int) bool + inv rideObject } -type Environment struct { - sch proto.Scheme - st types.SmartState - act []proto.ScriptAction - h rideInt - tx rideObject - id rideType - th rideType - b rideObject - check func(int) bool - inv rideObject - invokeCount uint64 +func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*EvaluationEnvironment, error) { + height, err := state.AddingBlockHeight() + if err != nil { + return nil, err + } + + return &EvaluationEnvironment{ + sch: scheme, + st: state, + h: rideInt(height), + check: func(int) bool { return true }, + }, nil } -func newWrappedState(state types.SmartState, envThis rideType, scheme proto.Scheme) types.SmartState { - var dataEntries diffDataEntries +func NewEnvironmentWithWrappedState(env *EvaluationEnvironment, payments proto.ScriptPayments, callerPK crypto.PublicKey) (*EvaluationEnvironment, error) { + caller, err := proto.NewAddressFromPublicKey(env.sch, callerPK) + if err != nil { + return nil, errors.Wrap(err, "failed to create RIDE environment with wrapped state") + } + recipient := proto.NewRecipientFromAddress(proto.Address(env.th.(rideAddress))) - dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} - dataEntries.diffBool = map[string]proto.BooleanDataEntry{} - dataEntries.diffString = map[string]proto.StringDataEntry{} - dataEntries.diffBinary = map[string]proto.BinaryDataEntry{} - dataEntries.diffDDelete = map[string]proto.DeleteDataEntry{} + st := newWrappedState(env) - balances := map[string]diffBalance{} - sponsorships := map[string]diffSponsorship{} - newAssetInfo := map[string]diffNewAssetInfo{} - oldAssetInfo := map[string]diffOldAssetInfo{} - leases := map[string]lease{} + for _, payment := range payments { + senderBalance, err := st.NewestAccountBalance(proto.NewRecipientFromAddress(caller), payment.Asset.ID.Bytes()) + if err != nil { + return nil, err + } + if senderBalance < payment.Amount { + return nil, errors.New("not enough money for tx attached payments") + } - diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo, leases: leases} - wrappedSt := wrappedState{diff: *diffSt, envThis: envThis.(rideAddress), envScheme: scheme} - return &wrappedSt -} + searchBalance, searchAddr, err := st.diff.findBalance(recipient, payment.Asset) + if err != nil { + return nil, errors.Wrap(err, "failed to create RIDE environment with wrapped state") + } + err = st.diff.changeBalance(searchBalance, searchAddr, int64(payment.Amount), payment.Asset.ID, recipient) + if err != nil { + return nil, errors.Wrap(err, "failed to create RIDE environment with wrapped state") + } -func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*Environment, error) { - height, err := state.AddingBlockHeight() - if err != nil { - return nil, err + callerRcp := proto.NewRecipientFromAddress(caller) + senderSearchBalance, senderSearchAddr, err := st.diff.findBalance(callerRcp, payment.Asset) + if err != nil { + return nil, errors.Wrap(err, "failed to create RIDE environment with wrapped state") + } + + err = st.diff.changeBalance(senderSearchBalance, senderSearchAddr, -int64(payment.Amount), payment.Asset.ID, callerRcp) + if err != nil { + return nil, errors.Wrap(err, "failed to create RIDE environment with wrapped state") + } } - return &Environment{ - sch: scheme, - st: state, - act: nil, - h: rideInt(height), - tx: nil, - id: nil, - th: nil, - b: nil, - check: func(int) bool { return true }, - inv: nil, - invokeCount: 0, + return &EvaluationEnvironment{ + sch: env.sch, + st: st, + h: env.h, + tx: env.tx, + id: env.id, + th: env.th, + b: env.b, + check: env.check, + inv: env.inv, }, nil } -func (e *Environment) ChooseSizeCheck(v int) { +func (e *EvaluationEnvironment) ChooseSizeCheck(v int) { if v > 2 { e.check = func(l int) bool { return l <= maxMessageLength @@ -616,29 +1074,32 @@ func (e *Environment) ChooseSizeCheck(v int) { } } -func (e *Environment) SetThisFromFullAssetInfo(info *proto.FullAssetInfo) { +func (e *EvaluationEnvironment) SetThisFromFullAssetInfo(info *proto.FullAssetInfo) { e.th = fullAssetInfoToObject(info) } -func (e *Environment) SetThisFromAssetInfo(info *proto.AssetInfo) { +func (e *EvaluationEnvironment) SetTimestamp(timestamp uint64) { + e.time = timestamp +} + +func (e *EvaluationEnvironment) SetThisFromAssetInfo(info *proto.AssetInfo) { e.th = assetInfoToObject(info) } -func (e *Environment) SetThisFromAddress(addr proto.Address) { +func (e *EvaluationEnvironment) SetThisFromAddress(addr proto.Address) { e.th = rideAddress(addr) } -func (e *Environment) SetLastBlock(info *proto.BlockInfo) { +func (e *EvaluationEnvironment) SetLastBlock(info *proto.BlockInfo) { e.b = blockInfoToObject(info) } -func (e *Environment) SetTransactionFromScriptTransfer(transfer *proto.FullScriptTransfer) { +func (e *EvaluationEnvironment) SetTransactionFromScriptTransfer(transfer *proto.FullScriptTransfer) { e.id = rideBytes(transfer.ID.Bytes()) e.tx = scriptTransferToObject(transfer) } -func (e *Environment) SetTransactionWithoutProofs(tx proto.Transaction) error { - +func (e *EvaluationEnvironment) SetTransactionWithoutProofs(tx proto.Transaction) error { err := e.SetTransaction(tx) if err != nil { return err @@ -647,7 +1108,7 @@ func (e *Environment) SetTransactionWithoutProofs(tx proto.Transaction) error { return nil } -func (e *Environment) SetTransactionFromScriptAction(action proto.ScriptAction, pk crypto.PublicKey, id crypto.Digest, ts uint64) error { +func (e *EvaluationEnvironment) SetTransactionFromScriptAction(action proto.ScriptAction, pk crypto.PublicKey, id crypto.Digest, ts uint64) error { obj, err := scriptActionToObject(e.sch, action, pk, id, ts) if err != nil { return err @@ -656,7 +1117,7 @@ func (e *Environment) SetTransactionFromScriptAction(action proto.ScriptAction, return nil } -func (e *Environment) SetTransaction(tx proto.Transaction) error { +func (e *EvaluationEnvironment) SetTransaction(tx proto.Transaction) error { id, err := tx.GetID(e.sch) if err != nil { return err @@ -670,7 +1131,7 @@ func (e *Environment) SetTransaction(tx proto.Transaction) error { return nil } -func (e *Environment) SetTransactionFromOrder(order proto.Order) error { +func (e *EvaluationEnvironment) SetTransactionFromOrder(order proto.Order) error { obj, err := orderToObject(e.sch, order) if err != nil { return err @@ -679,7 +1140,7 @@ func (e *Environment) SetTransactionFromOrder(order proto.Order) error { return nil } -func (e *Environment) SetInvoke(tx *proto.InvokeScriptWithProofs, v int) error { +func (e *EvaluationEnvironment) SetInvoke(tx *proto.InvokeScriptWithProofs, v int) error { obj, err := invocationToObject(v, e.sch, tx) if err != nil { return err @@ -688,104 +1149,66 @@ func (e *Environment) SetInvoke(tx *proto.InvokeScriptWithProofs, v int) error { return nil } -func (e *Environment) scheme() byte { +func (e *EvaluationEnvironment) timestamp() uint64 { + return e.time +} + +func (e *EvaluationEnvironment) scheme() byte { return e.sch } -func (e *Environment) height() rideInt { +func (e *EvaluationEnvironment) height() rideInt { return e.h } -func (e *Environment) transaction() rideObject { +func (e *EvaluationEnvironment) transaction() rideObject { return e.tx } -func (e *Environment) this() rideType { +func (e *EvaluationEnvironment) this() rideType { return e.th } -func (e *Environment) block() rideObject { +func (e *EvaluationEnvironment) block() rideObject { return e.b } -func (e *Environment) txID() rideType { +func (e *EvaluationEnvironment) txID() rideType { return e.id } -func (e *Environment) state() types.SmartState { +func (e *EvaluationEnvironment) state() types.SmartState { return e.st } -func (e *Environment) actions() []proto.ScriptAction { - return e.act -} +func (e *EvaluationEnvironment) setNewDAppAddress(address proto.Address) { + ws, _ := e.st.(*WrappedState) + ws.cle = rideAddress(address) -func (e *Environment) setNewDAppAddress(address proto.Address) { e.SetThisFromAddress(address) } -func (e *Environment) applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - return e.st.ApplyToState(actions) -} - -func (e *Environment) appendActions(actions []proto.ScriptAction) { - e.act = append(e.act, actions...) -} - -//func (e *Environment) validateInvokeResult(actions []proto.ScriptAction) (bool, error) { -// // validate diff -// wrappedSt, ok := e.st.(*wrappedState) -// if !ok { -// return false, errors.Errorf("validation: wrong state") -// } -// for _, value := range wrappedSt.diff.balances { -// if value.regular < 0 || value.leaseIn < 0 || value.leaseOut < 0 { -// return false, nil -// } -// for _, effective := range value.effectiveHistory { -// if effective < 0 { -// return false, nil -// } -// } -// } -// -// // validate actions -// // leaseCancel -// -// -//} - -func (e *Environment) smartAppendActions(actions []proto.ScriptAction) error { - _, ok := e.st.(*wrappedState) - if !ok { - wrappedSt := newWrappedState(e.state(), e.this(), e.sch) - e.st = wrappedSt - } - - modifiedActions, err := e.applyToState(actions) - if err != nil { - return err - } - e.appendActions(modifiedActions) - return nil -} - -func (e *Environment) checkMessageLength(l int) bool { +func (e *EvaluationEnvironment) checkMessageLength(l int) bool { return e.check(l) } -func (e *Environment) invocation() rideObject { +func (e *EvaluationEnvironment) invocation() rideObject { return e.inv } -func (e *Environment) SetInvocation(inv rideObject) { +func (e *EvaluationEnvironment) SetInvocation(inv rideObject) { e.inv = inv } -func (e *Environment) invCount() uint64 { - return e.invokeCount -} - -func (e *Environment) incrementInvCount() { - e.invokeCount++ +func isAssetWaves(assetID []byte) bool { + wavesAsset := crypto.Digest{} + if len(wavesAsset) != len(assetID) { + return false + } + for i := range assetID { + if assetID[i] != wavesAsset[i] { + return false + } + } + return true } diff --git a/pkg/ride/functions_boolean.go b/pkg/ride/functions_boolean.go index 283e33e17..e603fa019 100644 --- a/pkg/ride/functions_boolean.go +++ b/pkg/ride/functions_boolean.go @@ -16,7 +16,7 @@ func booleanArg(args []rideType) (rideBoolean, error) { return b, nil } -func booleanToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func booleanToBytes(_ Environment, args ...rideType) (rideType, error) { b, err := booleanArg(args) if err != nil { return nil, errors.Wrap(err, "booleanToBytes") @@ -28,7 +28,7 @@ func booleanToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { } } -func booleanToString(_ RideEnvironment, args ...rideType) (rideType, error) { +func booleanToString(_ Environment, args ...rideType) (rideType, error) { b, err := booleanArg(args) if err != nil { return nil, errors.Wrap(err, "booleanToString") @@ -40,7 +40,7 @@ func booleanToString(_ RideEnvironment, args ...rideType) (rideType, error) { } } -func unaryNot(_ RideEnvironment, args ...rideType) (rideType, error) { +func unaryNot(_ Environment, args ...rideType) (rideType, error) { b, err := booleanArg(args) if err != nil { return nil, errors.Wrap(err, "unaryNot") diff --git a/pkg/ride/functions_bytes.go b/pkg/ride/functions_bytes.go index 4b89bc134..e6e086853 100644 --- a/pkg/ride/functions_bytes.go +++ b/pkg/ride/functions_bytes.go @@ -86,7 +86,7 @@ func bytesOrUnitArgAsBytes(args ...rideType) ([]byte, error) { } } -func sizeBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func sizeBytes(_ Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "sizeBytes") @@ -94,7 +94,7 @@ func sizeBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(len(b)), nil } -func takeBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func takeBytes(_ Environment, args ...rideType) (rideType, error) { b, n, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "takeBytes") @@ -102,7 +102,7 @@ func takeBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return takeRideBytes(b, n), nil } -func dropBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func dropBytes(_ Environment, args ...rideType) (rideType, error) { b, n, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "dropBytes") @@ -110,7 +110,7 @@ func dropBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return dropRideBytes(b, n), nil } -func concatBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func concatBytes(_ Environment, args ...rideType) (rideType, error) { b1, b2, err := bytesArgs2(args) if err != nil { return nil, errors.Wrap(err, "concatBytes") @@ -125,7 +125,7 @@ func concatBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(out), nil } -func toBase58(_ RideEnvironment, args ...rideType) (rideType, error) { +func toBase58(_ Environment, args ...rideType) (rideType, error) { b, err := bytesOrUnitArgAsBytes(args...) if err != nil { return nil, errors.Wrap(err, "toBase58") @@ -133,7 +133,7 @@ func toBase58(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(base58.Encode(b)), nil } -func fromBase58(_ RideEnvironment, args ...rideType) (rideType, error) { +func fromBase58(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "fromBase58") @@ -149,7 +149,7 @@ func fromBase58(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(r), nil } -func toBase64(_ RideEnvironment, args ...rideType) (rideType, error) { +func toBase64(_ Environment, args ...rideType) (rideType, error) { b, err := bytesOrUnitArgAsBytes(args...) if err != nil { return nil, errors.Wrap(err, "toBase64") @@ -157,7 +157,7 @@ func toBase64(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(base64.StdEncoding.EncodeToString(b)), nil } -func fromBase64(_ RideEnvironment, args ...rideType) (rideType, error) { +func fromBase64(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "fromBase64") @@ -174,7 +174,7 @@ func fromBase64(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(decoded), nil } -func toBase16(_ RideEnvironment, args ...rideType) (rideType, error) { +func toBase16(_ Environment, args ...rideType) (rideType, error) { b, err := bytesOrUnitArgAsBytes(args...) if err != nil { return nil, errors.Wrap(err, "toBase16") @@ -182,7 +182,7 @@ func toBase16(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(hex.EncodeToString(b)), nil } -func fromBase16(_ RideEnvironment, args ...rideType) (rideType, error) { +func fromBase16(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "fromBase16") @@ -195,7 +195,7 @@ func fromBase16(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(decoded), nil } -func dropRightBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func dropRightBytes(_ Environment, args ...rideType) (rideType, error) { b, n, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "dropRightBytes") @@ -203,7 +203,7 @@ func dropRightBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return takeRideBytes(b, len(b)-n), nil } -func takeRightBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func takeRightBytes(_ Environment, args ...rideType) (rideType, error) { b, n, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "takeRightBytes") @@ -211,7 +211,7 @@ func takeRightBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return dropRideBytes(b, len(b)-n), nil } -func bytesToUTF8String(_ RideEnvironment, args ...rideType) (rideType, error) { +func bytesToUTF8String(_ Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "bytesToUTF8String") @@ -222,7 +222,7 @@ func bytesToUTF8String(_ RideEnvironment, args ...rideType) (rideType, error) { return nil, errors.Errorf("invalid UTF-8 sequence") } -func bytesToInt(_ RideEnvironment, args ...rideType) (rideType, error) { +func bytesToInt(_ Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "bytesToInt") @@ -233,7 +233,7 @@ func bytesToInt(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(binary.BigEndian.Uint64(b)), nil } -func bytesToIntWithOffset(_ RideEnvironment, args ...rideType) (rideType, error) { +func bytesToIntWithOffset(_ Environment, args ...rideType) (rideType, error) { b, n, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "bytesToLongWithOffset") diff --git a/pkg/ride/functions_common.go b/pkg/ride/functions_common.go index d570169c0..a7765de47 100644 --- a/pkg/ride/functions_common.go +++ b/pkg/ride/functions_common.go @@ -20,21 +20,21 @@ func checkArgs(args []rideType, count int) error { return nil } -func eq(_ RideEnvironment, args ...rideType) (rideType, error) { +func eq(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "eq") } return rideBoolean(args[0].eq(args[1])), nil } -func neq(_ RideEnvironment, args ...rideType) (rideType, error) { +func neq(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "neq") } return rideBoolean(!args[0].eq(args[1])), nil } -func instanceOf(_ RideEnvironment, args ...rideType) (rideType, error) { +func instanceOf(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "instanceOf") } @@ -45,7 +45,7 @@ func instanceOf(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(args[0].instanceOf() == string(t)), nil } -func extract(_ RideEnvironment, args ...rideType) (rideType, error) { +func extract(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "extract") } @@ -55,7 +55,7 @@ func extract(_ RideEnvironment, args ...rideType) (rideType, error) { return args[0], nil } -func isDefined(_ RideEnvironment, args ...rideType) (rideType, error) { +func isDefined(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "isDefined") } @@ -65,7 +65,7 @@ func isDefined(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(true), nil } -func throw(_ RideEnvironment, args ...rideType) (rideType, error) { +func throw(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "throw") @@ -73,11 +73,11 @@ func throw(_ RideEnvironment, args ...rideType) (rideType, error) { return rideThrow(s), nil } -func throw0(_ RideEnvironment, _ ...rideType) (rideType, error) { +func throw0(_ Environment, _ ...rideType) (rideType, error) { return rideThrow(defaultThrowMessage), nil } -func value(_ RideEnvironment, args ...rideType) (rideType, error) { +func value(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "value") } @@ -87,7 +87,7 @@ func value(_ RideEnvironment, args ...rideType) (rideType, error) { return args[0], nil } -func valueOrErrorMessage(_ RideEnvironment, args ...rideType) (rideType, error) { +func valueOrErrorMessage(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "valueOrErrorMessage") } @@ -101,7 +101,7 @@ func valueOrErrorMessage(_ RideEnvironment, args ...rideType) (rideType, error) return args[0], nil } -func valueOrElse(_ RideEnvironment, args ...rideType) (rideType, error) { +func valueOrElse(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "valueOrErrorMessage") } diff --git a/pkg/ride/functions_generated.go b/pkg/ride/functions_generated.go index 27b364f0a..f02cb201a 100644 --- a/pkg/ride/functions_generated.go +++ b/pkg/ride/functions_generated.go @@ -11,7 +11,7 @@ import ( c2 "github.com/wavesplatform/gowaves/pkg/ride/crypto" ) -func bls12Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_1(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_1") } @@ -37,7 +37,7 @@ func bls12Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_2(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_2") } @@ -63,7 +63,7 @@ func bls12Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_3(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_3") } @@ -89,7 +89,7 @@ func bls12Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_4(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_4") } @@ -115,7 +115,7 @@ func bls12Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_5(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_5") } @@ -141,7 +141,7 @@ func bls12Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_6(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_6") } @@ -167,7 +167,7 @@ func bls12Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_7(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_7") } @@ -193,7 +193,7 @@ func bls12Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_8(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_8") } @@ -219,7 +219,7 @@ func bls12Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_9(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_9") } @@ -245,7 +245,7 @@ func bls12Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bls12Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_10(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_10") } @@ -271,7 +271,7 @@ func bls12Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bls12Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_11(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_11") } @@ -297,7 +297,7 @@ func bls12Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bls12Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_12(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_12") } @@ -323,7 +323,7 @@ func bls12Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bls12Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_13(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_13") } @@ -349,7 +349,7 @@ func bls12Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bls12Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_14(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_14") } @@ -375,7 +375,7 @@ func bls12Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bls12Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify_15(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify_15") } @@ -401,7 +401,7 @@ func bls12Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_1(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_1") } @@ -427,7 +427,7 @@ func bn256Groth16Verify_1(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_2(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_2") } @@ -453,7 +453,7 @@ func bn256Groth16Verify_2(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_3(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_3") } @@ -479,7 +479,7 @@ func bn256Groth16Verify_3(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_4(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_4") } @@ -505,7 +505,7 @@ func bn256Groth16Verify_4(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_5(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_5") } @@ -531,7 +531,7 @@ func bn256Groth16Verify_5(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_6(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_6") } @@ -557,7 +557,7 @@ func bn256Groth16Verify_6(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_7(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_7") } @@ -583,7 +583,7 @@ func bn256Groth16Verify_7(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_8(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_8") } @@ -609,7 +609,7 @@ func bn256Groth16Verify_8(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_9(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_9") } @@ -635,7 +635,7 @@ func bn256Groth16Verify_9(env RideEnvironment, args ...rideType) (rideType, erro return rideBoolean(ok), nil } -func bn256Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_10(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_10") } @@ -661,7 +661,7 @@ func bn256Groth16Verify_10(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_11(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_11") } @@ -687,7 +687,7 @@ func bn256Groth16Verify_11(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_12(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_12") } @@ -713,7 +713,7 @@ func bn256Groth16Verify_12(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_13(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_13") } @@ -739,7 +739,7 @@ func bn256Groth16Verify_13(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_14(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_14") } @@ -765,7 +765,7 @@ func bn256Groth16Verify_14(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func bn256Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify_15(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify_15") } @@ -791,7 +791,7 @@ func bn256Groth16Verify_15(env RideEnvironment, args ...rideType) (rideType, err return rideBoolean(ok), nil } -func sigVerify_8(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify_8(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify_8") } @@ -822,7 +822,7 @@ func sigVerify_8(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func sigVerify_16(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify_16(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify_16") } @@ -853,7 +853,7 @@ func sigVerify_16(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func sigVerify_32(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify_32(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify_32") } @@ -884,7 +884,7 @@ func sigVerify_32(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func sigVerify_64(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify_64(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify_64") } @@ -915,7 +915,7 @@ func sigVerify_64(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func sigVerify_128(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify_128(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify_128") } @@ -946,7 +946,7 @@ func sigVerify_128(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func rsaVerify_16(_ RideEnvironment, args ...rideType) (rideType, error) { +func rsaVerify_16(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify_16") } @@ -990,7 +990,7 @@ func rsaVerify_16(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func rsaVerify_32(_ RideEnvironment, args ...rideType) (rideType, error) { +func rsaVerify_32(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify_32") } @@ -1034,7 +1034,7 @@ func rsaVerify_32(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func rsaVerify_64(_ RideEnvironment, args ...rideType) (rideType, error) { +func rsaVerify_64(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify_64") } @@ -1078,7 +1078,7 @@ func rsaVerify_64(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func rsaVerify_128(_ RideEnvironment, args ...rideType) (rideType, error) { +func rsaVerify_128(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify_128") } @@ -1122,7 +1122,7 @@ func rsaVerify_128(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func keccak256_16(env RideEnvironment, args ...rideType) (rideType, error) { +func keccak256_16(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "keccak256_16") @@ -1137,7 +1137,7 @@ func keccak256_16(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func keccak256_32(env RideEnvironment, args ...rideType) (rideType, error) { +func keccak256_32(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "keccak256_32") @@ -1152,7 +1152,7 @@ func keccak256_32(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func keccak256_64(env RideEnvironment, args ...rideType) (rideType, error) { +func keccak256_64(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "keccak256_64") @@ -1167,7 +1167,7 @@ func keccak256_64(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func keccak256_128(env RideEnvironment, args ...rideType) (rideType, error) { +func keccak256_128(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "keccak256_128") @@ -1182,7 +1182,7 @@ func keccak256_128(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func blake2b256_16(_ RideEnvironment, args ...rideType) (rideType, error) { +func blake2b256_16(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "blake2b256_16") @@ -1197,7 +1197,7 @@ func blake2b256_16(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func blake2b256_32(_ RideEnvironment, args ...rideType) (rideType, error) { +func blake2b256_32(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "blake2b256_32") @@ -1212,7 +1212,7 @@ func blake2b256_32(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func blake2b256_64(_ RideEnvironment, args ...rideType) (rideType, error) { +func blake2b256_64(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "blake2b256_64") @@ -1227,7 +1227,7 @@ func blake2b256_64(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func blake2b256_128(_ RideEnvironment, args ...rideType) (rideType, error) { +func blake2b256_128(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "blake2b256_128") @@ -1242,7 +1242,7 @@ func blake2b256_128(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func sha256_16(_ RideEnvironment, args ...rideType) (rideType, error) { +func sha256_16(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "sha256_16") @@ -1258,7 +1258,7 @@ func sha256_16(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d), nil } -func sha256_32(_ RideEnvironment, args ...rideType) (rideType, error) { +func sha256_32(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "sha256_32") @@ -1274,7 +1274,7 @@ func sha256_32(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d), nil } -func sha256_64(_ RideEnvironment, args ...rideType) (rideType, error) { +func sha256_64(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "sha256_64") @@ -1290,7 +1290,7 @@ func sha256_64(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d), nil } -func sha256_128(_ RideEnvironment, args ...rideType) (rideType, error) { +func sha256_128(_ Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "sha256_128") diff --git a/pkg/ride/functions_int.go b/pkg/ride/functions_int.go index 77e5ad921..36c4df4e5 100644 --- a/pkg/ride/functions_int.go +++ b/pkg/ride/functions_int.go @@ -62,7 +62,7 @@ func intArgs(args []rideType, count int) ([]rideInt, error) { return r, nil } -func ge(_ RideEnvironment, args ...rideType) (rideType, error) { +func ge(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "ge") @@ -70,7 +70,7 @@ func ge(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(l1 >= l2), nil } -func gt(_ RideEnvironment, args ...rideType) (rideType, error) { +func gt(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "gt") @@ -78,7 +78,7 @@ func gt(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(l1 > l2), nil } -func intToString(_ RideEnvironment, args ...rideType) (rideType, error) { +func intToString(_ Environment, args ...rideType) (rideType, error) { l, err := intArg(args) if err != nil { return nil, errors.Wrap(err, "intToString") @@ -86,7 +86,7 @@ func intToString(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(strconv.Itoa(int(l))), nil } -func unaryMinus(_ RideEnvironment, args ...rideType) (rideType, error) { +func unaryMinus(_ Environment, args ...rideType) (rideType, error) { l, err := intArg(args) if err != nil { return nil, errors.Wrap(err, "unaryMinus") @@ -94,7 +94,7 @@ func unaryMinus(_ RideEnvironment, args ...rideType) (rideType, error) { return -l, nil } -func sum(_ RideEnvironment, args ...rideType) (rideType, error) { +func sum(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "sum") @@ -102,7 +102,7 @@ func sum(_ RideEnvironment, args ...rideType) (rideType, error) { return l1 + l2, nil } -func sub(_ RideEnvironment, args ...rideType) (rideType, error) { +func sub(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "sub") @@ -110,7 +110,7 @@ func sub(_ RideEnvironment, args ...rideType) (rideType, error) { return l1 - l2, nil } -func mul(_ RideEnvironment, args ...rideType) (rideType, error) { +func mul(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "mul") @@ -118,7 +118,7 @@ func mul(_ RideEnvironment, args ...rideType) (rideType, error) { return l1 * l2, nil } -func div(_ RideEnvironment, args ...rideType) (rideType, error) { +func div(_ Environment, args ...rideType) (rideType, error) { l1, l2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "div") @@ -129,7 +129,7 @@ func div(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(math.FloorDiv(int64(l1), int64(l2))), nil } -func mod(_ RideEnvironment, args ...rideType) (rideType, error) { +func mod(_ Environment, args ...rideType) (rideType, error) { i1, i2, err := twoIntArgs(args) if err != nil { return nil, errors.Wrap(err, "mod") @@ -140,7 +140,7 @@ func mod(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(math.ModDivision(int64(i1), int64(i2))), nil } -func fraction(_ RideEnvironment, args ...rideType) (rideType, error) { +func fraction(_ Environment, args ...rideType) (rideType, error) { values, err := intArgs(args, 3) if err != nil { return nil, errors.Wrap(err, "fraction") @@ -152,7 +152,7 @@ func fraction(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(res), nil } -func intToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func intToBytes(_ Environment, args ...rideType) (rideType, error) { i, err := intArg(args) if err != nil { return nil, errors.Wrap(err, "intToBytes") @@ -162,7 +162,7 @@ func intToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(out), nil } -func pow(_ RideEnvironment, args ...rideType) (rideType, error) { +func pow(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 6); err != nil { return nil, errors.Wrap(err, "pow") } @@ -197,7 +197,7 @@ func pow(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(r), nil } -func log(_ RideEnvironment, args ...rideType) (rideType, error) { +func log(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 6); err != nil { return nil, errors.Wrap(err, "log") } diff --git a/pkg/ride/functions_list.go b/pkg/ride/functions_list.go index dff321563..a6ef1a99f 100644 --- a/pkg/ride/functions_list.go +++ b/pkg/ride/functions_list.go @@ -86,7 +86,7 @@ func listAndElementArgs(args []rideType) (rideList, rideType, error) { return l, args[1], nil } -func intFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { +func intFromArray(_ Environment, args ...rideType) (rideType, error) { list, key, err := listAndStringArgs(args) if err != nil { return nil, errors.Wrap(err, "intFromArray") @@ -98,7 +98,7 @@ func intFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { return item, nil } -func booleanFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { +func booleanFromArray(_ Environment, args ...rideType) (rideType, error) { list, key, err := listAndStringArgs(args) if err != nil { return nil, errors.Wrap(err, "booleanFromArray") @@ -110,7 +110,7 @@ func booleanFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { return item, nil } -func bytesFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { +func bytesFromArray(_ Environment, args ...rideType) (rideType, error) { list, key, err := listAndStringArgs(args) if err != nil { return nil, errors.Wrap(err, "bytesFromArray") @@ -122,7 +122,7 @@ func bytesFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { return item, nil } -func stringFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { +func stringFromArray(_ Environment, args ...rideType) (rideType, error) { list, key, err := listAndStringArgs(args) if err != nil { return nil, errors.Wrap(err, "stringFromArray") @@ -134,7 +134,7 @@ func stringFromArray(_ RideEnvironment, args ...rideType) (rideType, error) { return item, nil } -func intFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error) { +func intFromArrayByIndex(_ Environment, args ...rideType) (rideType, error) { list, i, err := listAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "intFromArrayByIndex") @@ -154,7 +154,7 @@ func intFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error) } } -func booleanFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error) { +func booleanFromArrayByIndex(_ Environment, args ...rideType) (rideType, error) { list, i, err := listAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "booleanFromArrayByIndex") @@ -174,7 +174,7 @@ func booleanFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, err } } -func bytesFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error) { +func bytesFromArrayByIndex(_ Environment, args ...rideType) (rideType, error) { list, i, err := listAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "bytesFromArrayByIndex") @@ -194,7 +194,7 @@ func bytesFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error } } -func stringFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, error) { +func stringFromArrayByIndex(_ Environment, args ...rideType) (rideType, error) { list, i, err := listAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "stringFromArrayByIndex") @@ -214,7 +214,7 @@ func stringFromArrayByIndex(_ RideEnvironment, args ...rideType) (rideType, erro } } -func sizeList(_ RideEnvironment, args ...rideType) (rideType, error) { +func sizeList(_ Environment, args ...rideType) (rideType, error) { l, err := listArg(args) if err != nil { return nil, errors.Wrap(err, "sizeList") @@ -222,7 +222,7 @@ func sizeList(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(len(l)), nil } -func getList(_ RideEnvironment, args ...rideType) (rideType, error) { +func getList(_ Environment, args ...rideType) (rideType, error) { l, i, err := listAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "getList") @@ -230,7 +230,7 @@ func getList(_ RideEnvironment, args ...rideType) (rideType, error) { return l[i], nil } -func createList(_ RideEnvironment, args ...rideType) (rideType, error) { +func createList(_ Environment, args ...rideType) (rideType, error) { if len(args) != 2 { return nil, errors.Errorf("createList: %d is invalid number of arguments, expected %d", len(args), 2) } @@ -250,7 +250,7 @@ func createList(_ RideEnvironment, args ...rideType) (rideType, error) { return append(rideList{args[0]}, tail...), nil } -func intValueFromArray(env RideEnvironment, args ...rideType) (rideType, error) { +func intValueFromArray(env Environment, args ...rideType) (rideType, error) { v, err := intFromArray(env, args...) if err != nil { return nil, err @@ -258,7 +258,7 @@ func intValueFromArray(env RideEnvironment, args ...rideType) (rideType, error) return extractValue(v) } -func booleanValueFromArray(env RideEnvironment, args ...rideType) (rideType, error) { +func booleanValueFromArray(env Environment, args ...rideType) (rideType, error) { v, err := booleanFromArray(env, args...) if err != nil { return nil, err @@ -266,7 +266,7 @@ func booleanValueFromArray(env RideEnvironment, args ...rideType) (rideType, err return extractValue(v) } -func bytesValueFromArray(env RideEnvironment, args ...rideType) (rideType, error) { +func bytesValueFromArray(env Environment, args ...rideType) (rideType, error) { v, err := bytesFromArray(env, args...) if err != nil { return nil, err @@ -274,7 +274,7 @@ func bytesValueFromArray(env RideEnvironment, args ...rideType) (rideType, error return extractValue(v) } -func stringValueFromArray(env RideEnvironment, args ...rideType) (rideType, error) { +func stringValueFromArray(env Environment, args ...rideType) (rideType, error) { v, err := stringFromArray(env, args...) if err != nil { return nil, err @@ -282,7 +282,7 @@ func stringValueFromArray(env RideEnvironment, args ...rideType) (rideType, erro return extractValue(v) } -func intValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType, error) { +func intValueFromArrayByIndex(env Environment, args ...rideType) (rideType, error) { v, err := intFromArrayByIndex(env, args...) if err != nil { return nil, err @@ -290,7 +290,7 @@ func intValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType, return extractValue(v) } -func booleanValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType, error) { +func booleanValueFromArrayByIndex(env Environment, args ...rideType) (rideType, error) { v, err := booleanFromArrayByIndex(env, args...) if err != nil { return nil, err @@ -298,7 +298,7 @@ func booleanValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideTy return extractValue(v) } -func bytesValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType, error) { +func bytesValueFromArrayByIndex(env Environment, args ...rideType) (rideType, error) { v, err := bytesFromArrayByIndex(env, args...) if err != nil { return nil, err @@ -306,7 +306,7 @@ func bytesValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType return extractValue(v) } -func stringValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideType, error) { +func stringValueFromArrayByIndex(env Environment, args ...rideType) (rideType, error) { v, err := stringFromArrayByIndex(env, args...) if err != nil { return nil, err @@ -314,7 +314,7 @@ func stringValueFromArrayByIndex(env RideEnvironment, args ...rideType) (rideTyp return extractValue(v) } -func limitedCreateList(_ RideEnvironment, args ...rideType) (rideType, error) { +func limitedCreateList(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "limitedCreateList") } @@ -331,7 +331,7 @@ func limitedCreateList(_ RideEnvironment, args ...rideType) (rideType, error) { return append(rideList{args[0]}, tail...), nil } -func appendToList(_ RideEnvironment, args ...rideType) (rideType, error) { +func appendToList(_ Environment, args ...rideType) (rideType, error) { list, e, err := listAndElementArgs(args) if err != nil { return nil, errors.Wrap(err, "appendToList") @@ -345,7 +345,7 @@ func appendToList(_ RideEnvironment, args ...rideType) (rideType, error) { return append(list, e), nil } -func concatList(_ RideEnvironment, args ...rideType) (rideType, error) { +func concatList(_ Environment, args ...rideType) (rideType, error) { list1, e, err := listAndElementArgs(args) if err != nil { return nil, errors.Wrap(err, "concatList") @@ -365,7 +365,7 @@ func concatList(_ RideEnvironment, args ...rideType) (rideType, error) { return r, nil } -func indexOfList(_ RideEnvironment, args ...rideType) (rideType, error) { +func indexOfList(_ Environment, args ...rideType) (rideType, error) { list, e, err := listAndElementArgs(args) if err != nil { return nil, errors.Wrap(err, "indexOfList") @@ -381,7 +381,7 @@ func indexOfList(_ RideEnvironment, args ...rideType) (rideType, error) { return rideUnit{}, nil // not found returns Unit } -func lastIndexOfList(_ RideEnvironment, args ...rideType) (rideType, error) { +func lastIndexOfList(_ Environment, args ...rideType) (rideType, error) { list, e, err := listAndElementArgs(args) if err != nil { return nil, errors.Wrap(err, "lastIndexOfList") @@ -397,7 +397,7 @@ func lastIndexOfList(_ RideEnvironment, args ...rideType) (rideType, error) { return rideUnit{}, nil // not found returns Unit } -func median(_ RideEnvironment, args ...rideType) (rideType, error) { +func median(_ Environment, args ...rideType) (rideType, error) { list, err := listArg(args) if err != nil { return nil, errors.Wrap(err, "median") @@ -419,7 +419,7 @@ func median(_ RideEnvironment, args ...rideType) (rideType, error) { } } -func max(_ RideEnvironment, args ...rideType) (rideType, error) { +func max(_ Environment, args ...rideType) (rideType, error) { list, err := listArg(args) if err != nil { return nil, errors.Wrap(err, "max") @@ -436,7 +436,7 @@ func max(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(max), nil } -func min(_ RideEnvironment, args ...rideType) (rideType, error) { +func min(_ Environment, args ...rideType) (rideType, error) { list, err := listArg(args) if err != nil { return nil, errors.Wrap(err, "min") @@ -453,7 +453,7 @@ func min(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(min), nil } -func containsElement(_ RideEnvironment, args ...rideType) (rideType, error) { +func containsElement(_ Environment, args ...rideType) (rideType, error) { list, e, err := listAndElementArgs(args) if err != nil { return nil, errors.Wrap(err, "containsElement") diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index b8fa99d79..7a1278958 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -6,6 +6,7 @@ import ( "crypto/rsa" sh256 "crypto/sha256" "crypto/x509" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" @@ -13,11 +14,16 @@ import ( "github.com/wavesplatform/gowaves/pkg/util/common" ) -func invoke(env RideEnvironment, args ...rideType) (rideType, error) { - env.incrementInvCount() - if env.invCount() > 100 { +func invoke(env Environment, args ...rideType) (rideType, error) { + ws, ok := env.state().(*WrappedState) + if !ok { + return nil, errors.Wrapf(errors.New("wrong state"), "invoke") + } + ws.incrementInvCount() + if ws.invCount() > 100 { return rideUnit{}, nil } + callerAddress, ok := env.this().(rideAddress) if !ok { return rideUnit{}, errors.Errorf("invoke: this has an unexpected type '%s'", env.this().instanceOf()) @@ -109,47 +115,34 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { paymentActions = append(paymentActions, action) } - res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) - + address, err := env.state().NewestRecipientToAddress(recipient) if err != nil { - return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") } - - err = env.smartAppendActions(paymentActions) + env.setNewDAppAddress(*address) + err = ws.smartAppendActions(paymentActions, env) if err != nil { return nil, errors.Wrapf(err, "failed to apply attachedPayments") } + res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) + if err != nil { + return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + } + if res.Result() { if res.UserError() != "" { return nil, errors.Errorf(res.UserError()) } - err = env.smartAppendActions(res.ScriptActions()) + err = ws.smartAppendActions(res.ScriptActions(), env) if err != nil { return nil, err } - env.setNewDAppAddress(proto.Address(callerAddress)) + env.setNewDAppAddress(proto.Address(callerAddress)) env.SetInvocation(oldInvocationParam) - // validation - - /* - actions: - 1) Sender has rights - 2) Transfer and Lease don't try to send negative amount - 3) reissue/issue - 4) the limit length of coin name (issue) - 5) script of asset ??? - - diff: - 1) negative balance - - */ - - //env.validateInvokeResult(res.ScriptActions()) - if res.UserResult() == nil { return rideUnit{}, nil } @@ -159,7 +152,7 @@ func invoke(env RideEnvironment, args ...rideType) (rideType, error) { return nil, errors.Errorf("result of Invoke is false") } -func addressFromString(env RideEnvironment, args ...rideType) (rideType, error) { +func addressFromString(env Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "addressFromString") @@ -174,7 +167,7 @@ func addressFromString(env RideEnvironment, args ...rideType) (rideType, error) return rideAddress(a), nil } -func addressValueFromString(env RideEnvironment, args ...rideType) (rideType, error) { +func addressValueFromString(env Environment, args ...rideType) (rideType, error) { r, err := addressFromString(env, args...) if err != nil { return nil, errors.Wrap(err, "addressValueFromString") @@ -185,7 +178,7 @@ func addressValueFromString(env RideEnvironment, args ...rideType) (rideType, er return r, nil } -func transactionByID(env RideEnvironment, args ...rideType) (rideType, error) { +func transactionByID(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "transactionByID") @@ -204,7 +197,7 @@ func transactionByID(env RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func transactionHeightByID(env RideEnvironment, args ...rideType) (rideType, error) { +func transactionHeightByID(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "transactionHeightByID") @@ -219,7 +212,7 @@ func transactionHeightByID(env RideEnvironment, args ...rideType) (rideType, err return rideInt(h), nil } -func assetBalanceV3(env RideEnvironment, args ...rideType) (rideType, error) { +func assetBalanceV3(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "assetBalanceV3") } @@ -238,7 +231,7 @@ func assetBalanceV3(env RideEnvironment, args ...rideType) (rideType, error) { return rideInt(balance), nil } -func assetBalanceV4(env RideEnvironment, args ...rideType) (rideType, error) { +func assetBalanceV4(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "assetBalanceV4") } @@ -260,7 +253,7 @@ func assetBalanceV4(env RideEnvironment, args ...rideType) (rideType, error) { return rideInt(balance), nil } -func intFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func intFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { return rideUnit{}, nil @@ -272,7 +265,7 @@ func intFromState(env RideEnvironment, args ...rideType) (rideType, error) { return rideInt(entry.Value), nil } -func bytesFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func bytesFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { return rideUnit{}, nil @@ -284,7 +277,7 @@ func bytesFromState(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(entry.Value), nil } -func stringFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func stringFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { return rideUnit{}, nil @@ -296,7 +289,7 @@ func stringFromState(env RideEnvironment, args ...rideType) (rideType, error) { return rideString(entry.Value), nil } -func booleanFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func booleanFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { return rideUnit{}, nil @@ -308,7 +301,7 @@ func booleanFromState(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(entry.Value), nil } -func addressFromRecipient(env RideEnvironment, args ...rideType) (rideType, error) { +func addressFromRecipient(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "addressFromRecipient") } @@ -332,7 +325,7 @@ func addressFromRecipient(env RideEnvironment, args ...rideType) (rideType, erro } } -func sigVerify(env RideEnvironment, args ...rideType) (rideType, error) { +func sigVerify(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "sigVerify") } @@ -363,7 +356,7 @@ func sigVerify(env RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func keccak256(env RideEnvironment, args ...rideType) (rideType, error) { +func keccak256(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "keccak256") @@ -378,7 +371,7 @@ func keccak256(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func blake2b256(env RideEnvironment, args ...rideType) (rideType, error) { +func blake2b256(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "blake2b256") @@ -393,7 +386,7 @@ func blake2b256(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d.Bytes()), nil } -func sha256(env RideEnvironment, args ...rideType) (rideType, error) { +func sha256(env Environment, args ...rideType) (rideType, error) { data, err := bytesOrStringArg(args) if err != nil { return nil, errors.Wrap(err, "sha256") @@ -409,7 +402,7 @@ func sha256(env RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(d), nil } -func addressFromPublicKey(env RideEnvironment, args ...rideType) (rideType, error) { +func addressFromPublicKey(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "addressFromPublicKey") @@ -421,7 +414,7 @@ func addressFromPublicKey(env RideEnvironment, args ...rideType) (rideType, erro return rideAddress(addr), nil } -func wavesBalanceV3(env RideEnvironment, args ...rideType) (rideType, error) { +func wavesBalanceV3(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "wavesBalanceV3") } @@ -436,7 +429,7 @@ func wavesBalanceV3(env RideEnvironment, args ...rideType) (rideType, error) { return rideInt(balance), nil } -func wavesBalanceV4(env RideEnvironment, args ...rideType) (rideType, error) { +func wavesBalanceV4(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "wavesBalanceV4") } @@ -451,7 +444,7 @@ func wavesBalanceV4(env RideEnvironment, args ...rideType) (rideType, error) { return balanceDetailsToObject(balance), nil } -func assetInfoV3(env RideEnvironment, args ...rideType) (rideType, error) { +func assetInfoV3(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "assetInfoV3") @@ -467,7 +460,7 @@ func assetInfoV3(env RideEnvironment, args ...rideType) (rideType, error) { return assetInfoToObject(info), nil } -func assetInfoV4(env RideEnvironment, args ...rideType) (rideType, error) { +func assetInfoV4(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "assetInfoV4") @@ -483,7 +476,7 @@ func assetInfoV4(env RideEnvironment, args ...rideType) (rideType, error) { return fullAssetInfoToObject(info), nil } -func blockInfoByHeight(env RideEnvironment, args ...rideType) (rideType, error) { +func blockInfoByHeight(env Environment, args ...rideType) (rideType, error) { i, err := intArg(args) if err != nil { return nil, errors.Wrap(err, "blockInfoByHeight") @@ -504,7 +497,7 @@ func blockInfoByHeight(env RideEnvironment, args ...rideType) (rideType, error) return obj, nil } -func transferByID(env RideEnvironment, args ...rideType) (rideType, error) { +func transferByID(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "transferByID") @@ -523,7 +516,7 @@ func transferByID(env RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func addressToString(_ RideEnvironment, args ...rideType) (rideType, error) { +func addressToString(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "addressToString") } @@ -540,7 +533,7 @@ func addressToString(_ RideEnvironment, args ...rideType) (rideType, error) { } } -func rsaVerify(_ RideEnvironment, args ...rideType) (rideType, error) { +func rsaVerify(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify") } @@ -581,7 +574,7 @@ func rsaVerify(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func checkMerkleProof(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkMerkleProof(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "checkMerkleProof") } @@ -604,7 +597,7 @@ func checkMerkleProof(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(bytes.Equal(root, r)), nil } -func intValueFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func intValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := intFromState(env, args...) if err != nil { return nil, err @@ -612,7 +605,7 @@ func intValueFromState(env RideEnvironment, args ...rideType) (rideType, error) return extractValue(v) } -func booleanValueFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func booleanValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := booleanFromState(env, args...) if err != nil { return nil, err @@ -620,7 +613,7 @@ func booleanValueFromState(env RideEnvironment, args ...rideType) (rideType, err return extractValue(v) } -func bytesValueFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func bytesValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := bytesFromState(env, args...) if err != nil { return nil, err @@ -628,7 +621,7 @@ func bytesValueFromState(env RideEnvironment, args ...rideType) (rideType, error return extractValue(v) } -func stringValueFromState(env RideEnvironment, args ...rideType) (rideType, error) { +func stringValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := stringFromState(env, args...) if err != nil { return nil, err @@ -636,7 +629,7 @@ func stringValueFromState(env RideEnvironment, args ...rideType) (rideType, erro return extractValue(v) } -func transferFromProtobuf(env RideEnvironment, args ...rideType) (rideType, error) { +func transferFromProtobuf(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "transferFromProtobuf") @@ -658,7 +651,7 @@ func transferFromProtobuf(env RideEnvironment, args ...rideType) (rideType, erro return obj, nil } -func calcAssetID(env RideEnvironment, name, description rideString, decimals, quantity rideInt, reissuable rideBoolean, nonce rideInt) (rideBytes, error) { +func calcAssetID(env Environment, name, description rideString, decimals, quantity rideInt, reissuable rideBoolean, nonce rideInt) (rideBytes, error) { pid, ok := env.txID().(rideBytes) if !ok { return nil, errors.New("calculateAssetID: no parent transaction ID found") @@ -671,7 +664,7 @@ func calcAssetID(env RideEnvironment, name, description rideString, decimals, qu return id.Bytes(), nil } -func calculateAssetID(env RideEnvironment, args ...rideType) (rideType, error) { +func calculateAssetID(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "calculateAssetID") } @@ -709,7 +702,7 @@ func calculateAssetID(env RideEnvironment, args ...rideType) (rideType, error) { return calcAssetID(env, name, description, decimals, quantity, reissuable, nonce) } -func simplifiedIssue(_ RideEnvironment, args ...rideType) (rideType, error) { +func simplifiedIssue(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 5); err != nil { return nil, errors.Wrap(err, "simplifiedIssue") } @@ -736,7 +729,7 @@ func simplifiedIssue(_ RideEnvironment, args ...rideType) (rideType, error) { return newIssue(name, description, quantity, decimals, reissuable, rideUnit{}, 0), nil } -func fullIssue(_ RideEnvironment, args ...rideType) (rideType, error) { +func fullIssue(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 7); err != nil { return nil, errors.Wrap(err, "fullIssue") } @@ -776,7 +769,7 @@ func fullIssue(_ RideEnvironment, args ...rideType) (rideType, error) { return newIssue(name, description, quantity, decimals, reissuable, script, nonce), nil } -func rebuildMerkleRoot(_ RideEnvironment, args ...rideType) (rideType, error) { +func rebuildMerkleRoot(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "rebuildMerkleRoot") } @@ -820,7 +813,7 @@ func rebuildMerkleRoot(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(root[:]), nil } -func bls12Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { +func bls12Groth16Verify(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bls12Groth16Verify") } @@ -843,7 +836,7 @@ func bls12Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func bn256Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { +func bn256Groth16Verify(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "bn256Groth16Verify") } @@ -866,7 +859,7 @@ func bn256Groth16Verify(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBoolean(ok), nil } -func ecRecover(_ RideEnvironment, args ...rideType) (rideType, error) { +func ecRecover(_ Environment, args ...rideType) (rideType, error) { digest, signature, err := bytesArgs2(args) if err != nil { return nil, errors.Wrap(err, "ecRecover") @@ -886,7 +879,7 @@ func ecRecover(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(pkb[1:]), nil } -func checkedBytesDataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkedBytesDataEntry(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "checkedBytesDataEntry") } @@ -901,7 +894,7 @@ func checkedBytesDataEntry(_ RideEnvironment, args ...rideType) (rideType, error return newDataEntry("BinaryEntry", key, value), nil } -func checkedBooleanDataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkedBooleanDataEntry(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "checkedBooleanDataEntry") } @@ -916,7 +909,7 @@ func checkedBooleanDataEntry(_ RideEnvironment, args ...rideType) (rideType, err return newDataEntry("BooleanEntry", key, value), nil } -func checkedDeleteEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkedDeleteEntry(_ Environment, args ...rideType) (rideType, error) { key, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "checkedDeleteEntry") @@ -924,7 +917,7 @@ func checkedDeleteEntry(_ RideEnvironment, args ...rideType) (rideType, error) { return newDataEntry("DeleteEntry", key, rideUnit{}), nil } -func checkedIntDataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkedIntDataEntry(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "checkedIntDataEntry") } @@ -939,7 +932,7 @@ func checkedIntDataEntry(_ RideEnvironment, args ...rideType) (rideType, error) return newDataEntry("IntegerEntry", key, value), nil } -func checkedStringDataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func checkedStringDataEntry(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "checkedStringDataEntry") } @@ -956,7 +949,7 @@ func checkedStringDataEntry(_ RideEnvironment, args ...rideType) (rideType, erro // Constructors -func address(_ RideEnvironment, args ...rideType) (rideType, error) { +func address(_ Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { return nil, errors.Wrap(err, "address") @@ -968,7 +961,7 @@ func address(_ RideEnvironment, args ...rideType) (rideType, error) { return rideAddress(addr), nil } -func alias(env RideEnvironment, args ...rideType) (rideType, error) { +func alias(env Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "alias") @@ -977,7 +970,7 @@ func alias(env RideEnvironment, args ...rideType) (rideType, error) { return rideAlias(*alias), nil } -func assetPair(_ RideEnvironment, args ...rideType) (rideType, error) { +func assetPair(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "assetPair") } @@ -996,7 +989,7 @@ func assetPair(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func burn(_ RideEnvironment, args ...rideType) (rideType, error) { +func burn(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "burn") } @@ -1015,7 +1008,7 @@ func burn(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func dataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { +func dataEntry(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "dataEntry") } @@ -1033,7 +1026,7 @@ func dataEntry(_ RideEnvironment, args ...rideType) (rideType, error) { return newDataEntry("DataEntry", key, value), nil } -func dataTransaction(_ RideEnvironment, args ...rideType) (rideType, error) { +func dataTransaction(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 9); err != nil { return nil, errors.Wrap(err, "dataTransaction") } @@ -1087,7 +1080,7 @@ func dataTransaction(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func scriptResult(_ RideEnvironment, args ...rideType) (rideType, error) { +func scriptResult(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "scriptResult") } @@ -1104,7 +1097,7 @@ func scriptResult(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func writeSet(_ RideEnvironment, args ...rideType) (rideType, error) { +func writeSet(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "writeSet") } @@ -1126,7 +1119,7 @@ func writeSet(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func scriptTransfer(_ RideEnvironment, args ...rideType) (rideType, error) { +func scriptTransfer(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "scriptTransfer") } @@ -1153,7 +1146,7 @@ func scriptTransfer(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func transferSet(_ RideEnvironment, args ...rideType) (rideType, error) { +func transferSet(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "transferSet") } @@ -1175,11 +1168,11 @@ func transferSet(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func unit(_ RideEnvironment, _ ...rideType) (rideType, error) { +func unit(_ Environment, _ ...rideType) (rideType, error) { return rideUnit{}, nil } -func reissue(_ RideEnvironment, args ...rideType) (rideType, error) { +func reissue(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "reissue") } @@ -1203,7 +1196,7 @@ func reissue(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func sponsorship(_ RideEnvironment, args ...rideType) (rideType, error) { +func sponsorship(_ Environment, args ...rideType) (rideType, error) { asset, fee, err := bytesAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "sponsorship") @@ -1215,7 +1208,7 @@ func sponsorship(_ RideEnvironment, args ...rideType) (rideType, error) { return obj, nil } -func attachedPayment(_ RideEnvironment, args ...rideType) (rideType, error) { +func attachedPayment(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "attachedPayment") } @@ -1357,7 +1350,7 @@ func checkAsset(v rideType) (rideType, bool) { } } -func calcLeaseID(env RideEnvironment, recipient proto.Recipient, amount, nonce rideInt) (rideBytes, error) { +func calcLeaseID(env Environment, recipient proto.Recipient, amount, nonce rideInt) (rideBytes, error) { pid, ok := env.txID().(rideBytes) if !ok { return nil, errors.New("calcLeaseID: no parent transaction ID found") @@ -1370,7 +1363,7 @@ func calcLeaseID(env RideEnvironment, recipient proto.Recipient, amount, nonce r return id.Bytes(), nil } -func calculateLeaseID(env RideEnvironment, args ...rideType) (rideType, error) { +func calculateLeaseID(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "calculateLeaseID") } @@ -1408,7 +1401,7 @@ func newLease(recipient rideRecipient, amount, nonce rideInt) rideObject { return r } -func simplifiedLease(_ RideEnvironment, args ...rideType) (rideType, error) { +func simplifiedLease(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "simplifiedLease") } @@ -1423,7 +1416,7 @@ func simplifiedLease(_ RideEnvironment, args ...rideType) (rideType, error) { return newLease(rideRecipient(recipient), amount, 0), nil } -func fullLease(_ RideEnvironment, args ...rideType) (rideType, error) { +func fullLease(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 3); err != nil { return nil, errors.Wrap(err, "fullLease") } @@ -1442,7 +1435,7 @@ func fullLease(_ RideEnvironment, args ...rideType) (rideType, error) { return newLease(rideRecipient(recipient), amount, nonce), nil } -func leaseCancel(_ RideEnvironment, args ...rideType) (rideType, error) { +func leaseCancel(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "leaseCancel") } diff --git a/pkg/ride/functions_strings.go b/pkg/ride/functions_strings.go index 94ca2780c..c0473e7ea 100644 --- a/pkg/ride/functions_strings.go +++ b/pkg/ride/functions_strings.go @@ -94,7 +94,7 @@ func twoStringsArgs(args []rideType) (string, string, error) { return string(s1), string(s2), nil } -func concatStrings(_ RideEnvironment, args ...rideType) (rideType, error) { +func concatStrings(_ Environment, args ...rideType) (rideType, error) { s1, s2, err := twoStringsArgs(args) if err != nil { return nil, errors.Wrap(err, "concatStrings") @@ -111,7 +111,7 @@ func concatStrings(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(out), nil } -func takeString(_ RideEnvironment, args ...rideType) (rideType, error) { +func takeString(_ Environment, args ...rideType) (rideType, error) { s, n, err := stringAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "takeString") @@ -119,7 +119,7 @@ func takeString(_ RideEnvironment, args ...rideType) (rideType, error) { return takeRideString(s, n), nil } -func dropString(_ RideEnvironment, args ...rideType) (rideType, error) { +func dropString(_ Environment, args ...rideType) (rideType, error) { s, n, err := stringAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "dropString") @@ -127,7 +127,7 @@ func dropString(_ RideEnvironment, args ...rideType) (rideType, error) { return dropRideString(s, n), nil } -func sizeString(_ RideEnvironment, args ...rideType) (rideType, error) { +func sizeString(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "sizeString") @@ -135,7 +135,7 @@ func sizeString(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(utf8.RuneCountInString(string(s))), nil } -func indexOfSubstring(_ RideEnvironment, args ...rideType) (rideType, error) { +func indexOfSubstring(_ Environment, args ...rideType) (rideType, error) { s1, s2, err := twoStringsArgs(args) if err != nil { return nil, errors.Wrap(err, "indexOfSubstring") @@ -147,7 +147,7 @@ func indexOfSubstring(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(i), nil } -func indexOfSubstringWithOffset(_ RideEnvironment, args ...rideType) (rideType, error) { +func indexOfSubstringWithOffset(_ Environment, args ...rideType) (rideType, error) { s1, s2, n, err := twoStringsAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "lastIndexOfSubstringWithOffset") @@ -162,7 +162,7 @@ func indexOfSubstringWithOffset(_ RideEnvironment, args ...rideType) (rideType, return rideInt(i + n), nil } -func stringToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { +func stringToBytes(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "stringToBytes") @@ -170,7 +170,7 @@ func stringToBytes(_ RideEnvironment, args ...rideType) (rideType, error) { return rideBytes(s), nil } -func dropRightString(_ RideEnvironment, args ...rideType) (rideType, error) { +func dropRightString(_ Environment, args ...rideType) (rideType, error) { s, n, err := stringAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "dropRightString") @@ -178,7 +178,7 @@ func dropRightString(_ RideEnvironment, args ...rideType) (rideType, error) { return takeRideString(s, utf8.RuneCountInString(s)-n), nil } -func takeRightString(_ RideEnvironment, args ...rideType) (rideType, error) { +func takeRightString(_ Environment, args ...rideType) (rideType, error) { s, n, err := stringAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "takeRightString") @@ -186,7 +186,7 @@ func takeRightString(_ RideEnvironment, args ...rideType) (rideType, error) { return dropRideString(s, utf8.RuneCountInString(s)-n), nil } -func splitString(_ RideEnvironment, args ...rideType) (rideType, error) { +func splitString(_ Environment, args ...rideType) (rideType, error) { s1, s2, err := twoStringsArgs(args) if err != nil { return nil, errors.Wrap(err, "splitString") @@ -198,7 +198,7 @@ func splitString(_ RideEnvironment, args ...rideType) (rideType, error) { return r, nil } -func parseInt(_ RideEnvironment, args ...rideType) (rideType, error) { +func parseInt(_ Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { return nil, errors.Wrap(err, "parseInt") @@ -210,7 +210,7 @@ func parseInt(_ RideEnvironment, args ...rideType) (rideType, error) { return rideInt(i), nil } -func parseIntValue(env RideEnvironment, args ...rideType) (rideType, error) { +func parseIntValue(env Environment, args ...rideType) (rideType, error) { maybeInt, err := parseInt(env, args...) if err != nil { return nil, errors.Wrap(err, "parseIntValue") @@ -218,7 +218,7 @@ func parseIntValue(env RideEnvironment, args ...rideType) (rideType, error) { return extractValue(maybeInt) } -func lastIndexOfSubstring(_ RideEnvironment, args ...rideType) (rideType, error) { +func lastIndexOfSubstring(_ Environment, args ...rideType) (rideType, error) { s1, s2, err := twoStringsArgs(args) if err != nil { return nil, errors.Wrap(err, "lastIndexOfSubstring") @@ -230,7 +230,7 @@ func lastIndexOfSubstring(_ RideEnvironment, args ...rideType) (rideType, error) return rideInt(i), nil } -func lastIndexOfSubstringWithOffset(_ RideEnvironment, args ...rideType) (rideType, error) { +func lastIndexOfSubstringWithOffset(_ Environment, args ...rideType) (rideType, error) { s1, s2, n, err := twoStringsAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "lastIndexOfSubstringWithOffset") @@ -248,7 +248,7 @@ func lastIndexOfSubstringWithOffset(_ RideEnvironment, args ...rideType) (rideTy return rideInt(i), nil } -func makeString(_ RideEnvironment, args ...rideType) (rideType, error) { +func makeString(_ Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 2); err != nil { return nil, errors.Wrap(err, "makeString") } @@ -284,7 +284,7 @@ func makeString(_ RideEnvironment, args ...rideType) (rideType, error) { return rideString(strings.Join(parts, sep)), nil } -func contains(_ RideEnvironment, args ...rideType) (rideType, error) { +func contains(_ Environment, args ...rideType) (rideType, error) { s1, s2, err := twoStringsArgs(args) if err != nil { return nil, errors.Wrap(err, "contains") diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 60a26b756..e15cde301 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -612,10 +612,10 @@ func createConstructors(sb *strings.Builder, c map[string]constantDescription) { for _, k := range keys { if c[k].constructor == "" { tn := c[k].typeName - sb.WriteString(fmt.Sprintf("func new%s(RideEnvironment) rideType {\n", tn)) + sb.WriteString(fmt.Sprintf("func new%s(Environment) rideType {\n", tn)) sb.WriteString(fmt.Sprintf("return rideNamedType{name: \"%s\"}\n", tn)) sb.WriteString("}\n\n") - sb.WriteString(fmt.Sprintf("func create%s(env RideEnvironment, args ...rideType) (rideType, error) {\n", tn)) + sb.WriteString(fmt.Sprintf("func create%s(env Environment, args ...rideType) (rideType, error) {\n", tn)) sb.WriteString(fmt.Sprintf("return rideNamedType{name: \"%s\"}, nil\n", tn)) sb.WriteString("}\n\n") } @@ -717,7 +717,7 @@ func createTuples(sb *strings.Builder) { sb.WriteString(fmt.Sprintf("%s rideType\n", el)) } sb.WriteString("}\n\n") - sb.WriteString(fmt.Sprintf("func newTuple%d(_ RideEnvironment, args ...rideType) (rideType, error) {\n", n)) + sb.WriteString(fmt.Sprintf("func newTuple%d(_ Environment, args ...rideType) (rideType, error) {\n", n)) sb.WriteString(fmt.Sprintf("if len(args) != %d {\n", n)) sb.WriteString("return nil, errors.New(\"invalid number of arguments\")\n") sb.WriteString("}\n") @@ -813,7 +813,7 @@ func main() { sb.WriteString(")\n") for _, l := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} { fn := fmt.Sprintf("bls12Groth16Verify_%d", l) - sb.WriteString(fmt.Sprintf("func %s(env RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(env Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("if err := checkArgs(args, 3); err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") @@ -841,7 +841,7 @@ func main() { } for _, l := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} { fn := fmt.Sprintf("bn256Groth16Verify_%d", l) - sb.WriteString(fmt.Sprintf("func %s(env RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(env Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("if err := checkArgs(args, 3); err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") @@ -869,7 +869,7 @@ func main() { } for _, l := range []int{8, 16, 32, 64, 128} { fn := fmt.Sprintf("sigVerify_%d", l) - sb.WriteString(fmt.Sprintf("func %s(env RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(env Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("if err := checkArgs(args, 3); err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") @@ -902,7 +902,7 @@ func main() { } for _, l := range []int{16, 32, 64, 128} { fn := fmt.Sprintf("rsaVerify_%d", l) - sb.WriteString(fmt.Sprintf("func %s(_ RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(_ Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("if err := checkArgs(args, 4); err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) sb.WriteString("}\n") @@ -948,7 +948,7 @@ func main() { } for _, l := range []int{16, 32, 64, 128} { fn := fmt.Sprintf("keccak256_%d", l) - sb.WriteString(fmt.Sprintf("func %s(env RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(env Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("data, err := bytesOrStringArg(args)\n") sb.WriteString("if err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) @@ -965,7 +965,7 @@ func main() { } for _, l := range []int{16, 32, 64, 128} { fn := fmt.Sprintf("blake2b256_%d", l) - sb.WriteString(fmt.Sprintf("func %s(_ RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(_ Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("data, err := bytesOrStringArg(args)\n") sb.WriteString("if err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) @@ -982,7 +982,7 @@ func main() { } for _, l := range []int{16, 32, 64, 128} { fn := fmt.Sprintf("sha256_%d", l) - sb.WriteString(fmt.Sprintf("func %s(_ RideEnvironment, args ...rideType) (rideType, error) {\n", fn)) + sb.WriteString(fmt.Sprintf("func %s(_ Environment, args ...rideType) (rideType, error) {\n", fn)) sb.WriteString("data, err := bytesOrStringArg(args)\n") sb.WriteString("if err != nil {\n") sb.WriteString(fmt.Sprintf("return nil, errors.Wrap(err, \"%s\")\n", fn)) diff --git a/pkg/ride/parser.go b/pkg/ride/parser.go index 20e4542ef..9e5dcaeaa 100644 --- a/pkg/ride/parser.go +++ b/pkg/ride/parser.go @@ -77,7 +77,7 @@ func (p *parser) parse() (*Tree, error) { switch v := int(vb); v { case 0: return p.parseDApp() - case 1, 2, 3, 4: + case 1, 2, 3, 4, 5: return p.parseScript(v) default: return nil, errors.Errorf("unsupported script version %d", v) diff --git a/pkg/ride/program.go b/pkg/ride/program.go index e384d7b9b..9da036fa9 100644 --- a/pkg/ride/program.go +++ b/pkg/ride/program.go @@ -8,7 +8,7 @@ type callable struct { } type RideScript interface { - Run(env RideEnvironment) (RideResult, error) + Run(env Environment) (RideResult, error) code() []byte } @@ -19,7 +19,7 @@ type SimpleScript struct { Constants []rideType } -func (s *SimpleScript) Run(env RideEnvironment) (RideResult, error) { +func (s *SimpleScript) Run(env Environment) (RideResult, error) { fs, err := selectFunctions(s.LibVersion) if err != nil { return nil, errors.Wrap(err, "simple script execution failed") @@ -61,7 +61,7 @@ type DAppScript struct { EntryPoints map[string]callable } -func (s *DAppScript) Run(env RideEnvironment) (RideResult, error) { +func (s *DAppScript) Run(env Environment) (RideResult, error) { if _, ok := s.EntryPoints[""]; !ok { return nil, errors.Errorf("no verifier") } diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index e6bffd255..8cd4016ec 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -330,10 +330,10 @@ func (a rideList) get(prop string) (rideType, error) { return nil, errors.Errorf("type '%s' has no property '%s'", a.instanceOf(), prop) } -type rideFunction func(env RideEnvironment, args ...rideType) (rideType, error) +type rideFunction func(env Environment, args ...rideType) (rideType, error) -//go:generate moq -out runtime_moq_test.go . RideEnvironment:MockRideEnvironment -type RideEnvironment interface { +//go:generate moq -out runtime_moq_test.go . Environment:MockRideEnvironment +type Environment interface { scheme() byte height() rideInt transaction() rideObject @@ -341,17 +341,11 @@ type RideEnvironment interface { block() rideObject txID() rideType // Invoke transaction ID state() types.SmartState - applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) - appendActions(actions []proto.ScriptAction) - smartAppendActions(actions []proto.ScriptAction) error - //validateInvokeResult(actions []proto.ScriptAction) (bool, error) - actions() []proto.ScriptAction - invCount() uint64 - incrementInvCount() + timestamp() uint64 setNewDAppAddress(address proto.Address) checkMessageLength(int) bool invocation() rideObject // Invocation object made of invoke transaction SetInvocation(inv rideObject) } -type rideConstructor func(RideEnvironment) rideType +type rideConstructor func(Environment) rideType diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index 68bb9fa79..ef676e8f4 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -9,28 +9,19 @@ import ( "sync" ) -// Ensure, that MockRideEnvironment does implement RideEnvironment. +// Ensure, that MockRideEnvironment does implement Environment. // If this is not the case, regenerate this file with moq. -var _ RideEnvironment = &MockRideEnvironment{} +var _ Environment = &MockRideEnvironment{} -// MockRideEnvironment is a mock implementation of RideEnvironment. +// MockRideEnvironment is a mock implementation of Environment. // -// func TestSomethingThatUsesRideEnvironment(t *testing.T) { +// func TestSomethingThatUsesEnvironment(t *testing.T) { // -// // make and configure a mocked RideEnvironment -// mockedRideEnvironment := &MockRideEnvironment{ +// // make and configure a mocked Environment +// mockedEnvironment := &MockRideEnvironment{ // SetInvocationFunc: func(inv rideObject) { // panic("mock out the SetInvocation method") // }, -// actionsFunc: func() []proto.ScriptAction { -// panic("mock out the actions method") -// }, -// appendActionsFunc: func(actions []proto.ScriptAction) { -// panic("mock out the appendActions method") -// }, -// applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { -// panic("mock out the applyToState method") -// }, // blockFunc: func() rideObject { // panic("mock out the block method") // }, @@ -40,12 +31,6 @@ var _ RideEnvironment = &MockRideEnvironment{} // heightFunc: func() rideInt { // panic("mock out the height method") // }, -// incrementInvCountFunc: func() { -// panic("mock out the incrementInvCount method") -// }, -// invCountFunc: func() uint64 { -// panic("mock out the invCount method") -// }, // invocationFunc: func() rideObject { // panic("mock out the invocation method") // }, @@ -55,15 +40,15 @@ var _ RideEnvironment = &MockRideEnvironment{} // setNewDAppAddressFunc: func(address proto.Address) { // panic("mock out the setNewDAppAddress method") // }, -// smartAppendActionsFunc: func(actions []proto.ScriptAction) error { -// panic("mock out the smartAppendActions method") -// }, // stateFunc: func() types.SmartState { // panic("mock out the state method") // }, // thisFunc: func() rideType { // panic("mock out the this method") // }, +// timestampFunc: func() uint64 { +// panic("mock out the timestamp method") +// }, // transactionFunc: func() rideObject { // panic("mock out the transaction method") // }, @@ -72,7 +57,7 @@ var _ RideEnvironment = &MockRideEnvironment{} // }, // } // -// // use mockedRideEnvironment in code that requires RideEnvironment +// // use mockedEnvironment in code that requires Environment // // and then make assertions. // // } @@ -80,15 +65,6 @@ type MockRideEnvironment struct { // SetInvocationFunc mocks the SetInvocation method. SetInvocationFunc func(inv rideObject) - // actionsFunc mocks the actions method. - actionsFunc func() []proto.ScriptAction - - // appendActionsFunc mocks the appendActions method. - appendActionsFunc func(actions []proto.ScriptAction) - - // applyToStateFunc mocks the applyToState method. - applyToStateFunc func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) - // blockFunc mocks the block method. blockFunc func() rideObject @@ -98,12 +74,6 @@ type MockRideEnvironment struct { // heightFunc mocks the height method. heightFunc func() rideInt - // incrementInvCountFunc mocks the incrementInvCount method. - incrementInvCountFunc func() - - // invCountFunc mocks the invCount method. - invCountFunc func() uint64 - // invocationFunc mocks the invocation method. invocationFunc func() rideObject @@ -113,15 +83,15 @@ type MockRideEnvironment struct { // setNewDAppAddressFunc mocks the setNewDAppAddress method. setNewDAppAddressFunc func(address proto.Address) - // smartAppendActionsFunc mocks the smartAppendActions method. - smartAppendActionsFunc func(actions []proto.ScriptAction) error - // stateFunc mocks the state method. stateFunc func() types.SmartState // thisFunc mocks the this method. thisFunc func() rideType + // timestampFunc mocks the timestamp method. + timestampFunc func() uint64 + // transactionFunc mocks the transaction method. transactionFunc func() rideObject @@ -135,19 +105,6 @@ type MockRideEnvironment struct { // Inv is the inv argument value. Inv rideObject } - // actions holds details about calls to the actions method. - actions []struct { - } - // appendActions holds details about calls to the appendActions method. - appendActions []struct { - // Actions is the actions argument value. - Actions []proto.ScriptAction - } - // applyToState holds details about calls to the applyToState method. - applyToState []struct { - // Actions is the actions argument value. - Actions []proto.ScriptAction - } // block holds details about calls to the block method. block []struct { } @@ -159,12 +116,6 @@ type MockRideEnvironment struct { // height holds details about calls to the height method. height []struct { } - // incrementInvCount holds details about calls to the incrementInvCount method. - incrementInvCount []struct { - } - // invCount holds details about calls to the invCount method. - invCount []struct { - } // invocation holds details about calls to the invocation method. invocation []struct { } @@ -176,17 +127,15 @@ type MockRideEnvironment struct { // Address is the address argument value. Address proto.Address } - // smartAppendActions holds details about calls to the smartAppendActions method. - smartAppendActions []struct { - // Actions is the actions argument value. - Actions []proto.ScriptAction - } // state holds details about calls to the state method. state []struct { } // this holds details about calls to the this method. this []struct { } + // timestamp holds details about calls to the timestamp method. + timestamp []struct { + } // transaction holds details about calls to the transaction method. transaction []struct { } @@ -195,20 +144,15 @@ type MockRideEnvironment struct { } } lockSetInvocation sync.RWMutex - lockactions sync.RWMutex - lockappendActions sync.RWMutex - lockapplyToState sync.RWMutex lockblock sync.RWMutex lockcheckMessageLength sync.RWMutex lockheight sync.RWMutex - lockincrementInvCount sync.RWMutex - lockinvCount sync.RWMutex lockinvocation sync.RWMutex lockscheme sync.RWMutex locksetNewDAppAddress sync.RWMutex - locksmartAppendActions sync.RWMutex lockstate sync.RWMutex lockthis sync.RWMutex + locktimestamp sync.RWMutex locktransaction sync.RWMutex locktxID sync.RWMutex } @@ -216,7 +160,7 @@ type MockRideEnvironment struct { // SetInvocation calls SetInvocationFunc. func (mock *MockRideEnvironment) SetInvocation(inv rideObject) { if mock.SetInvocationFunc == nil { - panic("MockRideEnvironment.SetInvocationFunc: method is nil but RideEnvironment.SetInvocation was just called") + panic("MockRideEnvironment.SetInvocationFunc: method is nil but Environment.SetInvocation was just called") } callInfo := struct { Inv rideObject @@ -231,7 +175,7 @@ func (mock *MockRideEnvironment) SetInvocation(inv rideObject) { // SetInvocationCalls gets all the calls that were made to SetInvocation. // Check the length with: -// len(mockedRideEnvironment.SetInvocationCalls()) +// len(mockedEnvironment.SetInvocationCalls()) func (mock *MockRideEnvironment) SetInvocationCalls() []struct { Inv rideObject } { @@ -244,98 +188,10 @@ func (mock *MockRideEnvironment) SetInvocationCalls() []struct { return calls } -// actions calls actionsFunc. -func (mock *MockRideEnvironment) actions() []proto.ScriptAction { - if mock.actionsFunc == nil { - panic("MockRideEnvironment.actionsFunc: method is nil but RideEnvironment.actions was just called") - } - callInfo := struct { - }{} - mock.lockactions.Lock() - mock.calls.actions = append(mock.calls.actions, callInfo) - mock.lockactions.Unlock() - return mock.actionsFunc() -} - -// actionsCalls gets all the calls that were made to actions. -// Check the length with: -// len(mockedRideEnvironment.actionsCalls()) -func (mock *MockRideEnvironment) actionsCalls() []struct { -} { - var calls []struct { - } - mock.lockactions.RLock() - calls = mock.calls.actions - mock.lockactions.RUnlock() - return calls -} - -// appendActions calls appendActionsFunc. -func (mock *MockRideEnvironment) appendActions(actions []proto.ScriptAction) { - if mock.appendActionsFunc == nil { - panic("MockRideEnvironment.appendActionsFunc: method is nil but RideEnvironment.appendActions was just called") - } - callInfo := struct { - Actions []proto.ScriptAction - }{ - Actions: actions, - } - mock.lockappendActions.Lock() - mock.calls.appendActions = append(mock.calls.appendActions, callInfo) - mock.lockappendActions.Unlock() - mock.appendActionsFunc(actions) -} - -// appendActionsCalls gets all the calls that were made to appendActions. -// Check the length with: -// len(mockedRideEnvironment.appendActionsCalls()) -func (mock *MockRideEnvironment) appendActionsCalls() []struct { - Actions []proto.ScriptAction -} { - var calls []struct { - Actions []proto.ScriptAction - } - mock.lockappendActions.RLock() - calls = mock.calls.appendActions - mock.lockappendActions.RUnlock() - return calls -} - -// applyToState calls applyToStateFunc. -func (mock *MockRideEnvironment) applyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - if mock.applyToStateFunc == nil { - panic("MockRideEnvironment.applyToStateFunc: method is nil but RideEnvironment.applyToState was just called") - } - callInfo := struct { - Actions []proto.ScriptAction - }{ - Actions: actions, - } - mock.lockapplyToState.Lock() - mock.calls.applyToState = append(mock.calls.applyToState, callInfo) - mock.lockapplyToState.Unlock() - return mock.applyToStateFunc(actions) -} - -// applyToStateCalls gets all the calls that were made to applyToState. -// Check the length with: -// len(mockedRideEnvironment.applyToStateCalls()) -func (mock *MockRideEnvironment) applyToStateCalls() []struct { - Actions []proto.ScriptAction -} { - var calls []struct { - Actions []proto.ScriptAction - } - mock.lockapplyToState.RLock() - calls = mock.calls.applyToState - mock.lockapplyToState.RUnlock() - return calls -} - // block calls blockFunc. func (mock *MockRideEnvironment) block() rideObject { if mock.blockFunc == nil { - panic("MockRideEnvironment.blockFunc: method is nil but RideEnvironment.block was just called") + panic("MockRideEnvironment.blockFunc: method is nil but Environment.block was just called") } callInfo := struct { }{} @@ -347,7 +203,7 @@ func (mock *MockRideEnvironment) block() rideObject { // blockCalls gets all the calls that were made to block. // Check the length with: -// len(mockedRideEnvironment.blockCalls()) +// len(mockedEnvironment.blockCalls()) func (mock *MockRideEnvironment) blockCalls() []struct { } { var calls []struct { @@ -361,7 +217,7 @@ func (mock *MockRideEnvironment) blockCalls() []struct { // checkMessageLength calls checkMessageLengthFunc. func (mock *MockRideEnvironment) checkMessageLength(in1 int) bool { if mock.checkMessageLengthFunc == nil { - panic("MockRideEnvironment.checkMessageLengthFunc: method is nil but RideEnvironment.checkMessageLength was just called") + panic("MockRideEnvironment.checkMessageLengthFunc: method is nil but Environment.checkMessageLength was just called") } callInfo := struct { In1 int @@ -376,7 +232,7 @@ func (mock *MockRideEnvironment) checkMessageLength(in1 int) bool { // checkMessageLengthCalls gets all the calls that were made to checkMessageLength. // Check the length with: -// len(mockedRideEnvironment.checkMessageLengthCalls()) +// len(mockedEnvironment.checkMessageLengthCalls()) func (mock *MockRideEnvironment) checkMessageLengthCalls() []struct { In1 int } { @@ -392,7 +248,7 @@ func (mock *MockRideEnvironment) checkMessageLengthCalls() []struct { // height calls heightFunc. func (mock *MockRideEnvironment) height() rideInt { if mock.heightFunc == nil { - panic("MockRideEnvironment.heightFunc: method is nil but RideEnvironment.height was just called") + panic("MockRideEnvironment.heightFunc: method is nil but Environment.height was just called") } callInfo := struct { }{} @@ -404,7 +260,7 @@ func (mock *MockRideEnvironment) height() rideInt { // heightCalls gets all the calls that were made to height. // Check the length with: -// len(mockedRideEnvironment.heightCalls()) +// len(mockedEnvironment.heightCalls()) func (mock *MockRideEnvironment) heightCalls() []struct { } { var calls []struct { @@ -415,62 +271,10 @@ func (mock *MockRideEnvironment) heightCalls() []struct { return calls } -// incrementInvCount calls incrementInvCountFunc. -func (mock *MockRideEnvironment) incrementInvCount() { - if mock.incrementInvCountFunc == nil { - panic("MockRideEnvironment.incrementInvCountFunc: method is nil but RideEnvironment.incrementInvCount was just called") - } - callInfo := struct { - }{} - mock.lockincrementInvCount.Lock() - mock.calls.incrementInvCount = append(mock.calls.incrementInvCount, callInfo) - mock.lockincrementInvCount.Unlock() - mock.incrementInvCountFunc() -} - -// incrementInvCountCalls gets all the calls that were made to incrementInvCount. -// Check the length with: -// len(mockedRideEnvironment.incrementInvCountCalls()) -func (mock *MockRideEnvironment) incrementInvCountCalls() []struct { -} { - var calls []struct { - } - mock.lockincrementInvCount.RLock() - calls = mock.calls.incrementInvCount - mock.lockincrementInvCount.RUnlock() - return calls -} - -// invCount calls invCountFunc. -func (mock *MockRideEnvironment) invCount() uint64 { - if mock.invCountFunc == nil { - panic("MockRideEnvironment.invCountFunc: method is nil but RideEnvironment.invCount was just called") - } - callInfo := struct { - }{} - mock.lockinvCount.Lock() - mock.calls.invCount = append(mock.calls.invCount, callInfo) - mock.lockinvCount.Unlock() - return mock.invCountFunc() -} - -// invCountCalls gets all the calls that were made to invCount. -// Check the length with: -// len(mockedRideEnvironment.invCountCalls()) -func (mock *MockRideEnvironment) invCountCalls() []struct { -} { - var calls []struct { - } - mock.lockinvCount.RLock() - calls = mock.calls.invCount - mock.lockinvCount.RUnlock() - return calls -} - // invocation calls invocationFunc. func (mock *MockRideEnvironment) invocation() rideObject { if mock.invocationFunc == nil { - panic("MockRideEnvironment.invocationFunc: method is nil but RideEnvironment.invocation was just called") + panic("MockRideEnvironment.invocationFunc: method is nil but Environment.invocation was just called") } callInfo := struct { }{} @@ -482,7 +286,7 @@ func (mock *MockRideEnvironment) invocation() rideObject { // invocationCalls gets all the calls that were made to invocation. // Check the length with: -// len(mockedRideEnvironment.invocationCalls()) +// len(mockedEnvironment.invocationCalls()) func (mock *MockRideEnvironment) invocationCalls() []struct { } { var calls []struct { @@ -496,7 +300,7 @@ func (mock *MockRideEnvironment) invocationCalls() []struct { // scheme calls schemeFunc. func (mock *MockRideEnvironment) scheme() byte { if mock.schemeFunc == nil { - panic("MockRideEnvironment.schemeFunc: method is nil but RideEnvironment.scheme was just called") + panic("MockRideEnvironment.schemeFunc: method is nil but Environment.scheme was just called") } callInfo := struct { }{} @@ -508,7 +312,7 @@ func (mock *MockRideEnvironment) scheme() byte { // schemeCalls gets all the calls that were made to scheme. // Check the length with: -// len(mockedRideEnvironment.schemeCalls()) +// len(mockedEnvironment.schemeCalls()) func (mock *MockRideEnvironment) schemeCalls() []struct { } { var calls []struct { @@ -522,7 +326,7 @@ func (mock *MockRideEnvironment) schemeCalls() []struct { // setNewDAppAddress calls setNewDAppAddressFunc. func (mock *MockRideEnvironment) setNewDAppAddress(address proto.Address) { if mock.setNewDAppAddressFunc == nil { - panic("MockRideEnvironment.setNewDAppAddressFunc: method is nil but RideEnvironment.setNewDAppAddress was just called") + panic("MockRideEnvironment.setNewDAppAddressFunc: method is nil but Environment.setNewDAppAddress was just called") } callInfo := struct { Address proto.Address @@ -537,7 +341,7 @@ func (mock *MockRideEnvironment) setNewDAppAddress(address proto.Address) { // setNewDAppAddressCalls gets all the calls that were made to setNewDAppAddress. // Check the length with: -// len(mockedRideEnvironment.setNewDAppAddressCalls()) +// len(mockedEnvironment.setNewDAppAddressCalls()) func (mock *MockRideEnvironment) setNewDAppAddressCalls() []struct { Address proto.Address } { @@ -550,41 +354,10 @@ func (mock *MockRideEnvironment) setNewDAppAddressCalls() []struct { return calls } -// smartAppendActions calls smartAppendActionsFunc. -func (mock *MockRideEnvironment) smartAppendActions(actions []proto.ScriptAction) error { - if mock.smartAppendActionsFunc == nil { - panic("MockRideEnvironment.smartAppendActionsFunc: method is nil but RideEnvironment.smartAppendActions was just called") - } - callInfo := struct { - Actions []proto.ScriptAction - }{ - Actions: actions, - } - mock.locksmartAppendActions.Lock() - mock.calls.smartAppendActions = append(mock.calls.smartAppendActions, callInfo) - mock.locksmartAppendActions.Unlock() - return mock.smartAppendActionsFunc(actions) -} - -// smartAppendActionsCalls gets all the calls that were made to smartAppendActions. -// Check the length with: -// len(mockedRideEnvironment.smartAppendActionsCalls()) -func (mock *MockRideEnvironment) smartAppendActionsCalls() []struct { - Actions []proto.ScriptAction -} { - var calls []struct { - Actions []proto.ScriptAction - } - mock.locksmartAppendActions.RLock() - calls = mock.calls.smartAppendActions - mock.locksmartAppendActions.RUnlock() - return calls -} - // state calls stateFunc. func (mock *MockRideEnvironment) state() types.SmartState { if mock.stateFunc == nil { - panic("MockRideEnvironment.stateFunc: method is nil but RideEnvironment.state was just called") + panic("MockRideEnvironment.stateFunc: method is nil but Environment.state was just called") } callInfo := struct { }{} @@ -596,7 +369,7 @@ func (mock *MockRideEnvironment) state() types.SmartState { // stateCalls gets all the calls that were made to state. // Check the length with: -// len(mockedRideEnvironment.stateCalls()) +// len(mockedEnvironment.stateCalls()) func (mock *MockRideEnvironment) stateCalls() []struct { } { var calls []struct { @@ -610,7 +383,7 @@ func (mock *MockRideEnvironment) stateCalls() []struct { // this calls thisFunc. func (mock *MockRideEnvironment) this() rideType { if mock.thisFunc == nil { - panic("MockRideEnvironment.thisFunc: method is nil but RideEnvironment.this was just called") + panic("MockRideEnvironment.thisFunc: method is nil but Environment.this was just called") } callInfo := struct { }{} @@ -622,7 +395,7 @@ func (mock *MockRideEnvironment) this() rideType { // thisCalls gets all the calls that were made to this. // Check the length with: -// len(mockedRideEnvironment.thisCalls()) +// len(mockedEnvironment.thisCalls()) func (mock *MockRideEnvironment) thisCalls() []struct { } { var calls []struct { @@ -633,10 +406,36 @@ func (mock *MockRideEnvironment) thisCalls() []struct { return calls } +// timestamp calls timestampFunc. +func (mock *MockRideEnvironment) timestamp() uint64 { + if mock.timestampFunc == nil { + panic("MockRideEnvironment.timestampFunc: method is nil but Environment.timestamp was just called") + } + callInfo := struct { + }{} + mock.locktimestamp.Lock() + mock.calls.timestamp = append(mock.calls.timestamp, callInfo) + mock.locktimestamp.Unlock() + return mock.timestampFunc() +} + +// timestampCalls gets all the calls that were made to timestamp. +// Check the length with: +// len(mockedEnvironment.timestampCalls()) +func (mock *MockRideEnvironment) timestampCalls() []struct { +} { + var calls []struct { + } + mock.locktimestamp.RLock() + calls = mock.calls.timestamp + mock.locktimestamp.RUnlock() + return calls +} + // transaction calls transactionFunc. func (mock *MockRideEnvironment) transaction() rideObject { if mock.transactionFunc == nil { - panic("MockRideEnvironment.transactionFunc: method is nil but RideEnvironment.transaction was just called") + panic("MockRideEnvironment.transactionFunc: method is nil but Environment.transaction was just called") } callInfo := struct { }{} @@ -648,7 +447,7 @@ func (mock *MockRideEnvironment) transaction() rideObject { // transactionCalls gets all the calls that were made to transaction. // Check the length with: -// len(mockedRideEnvironment.transactionCalls()) +// len(mockedEnvironment.transactionCalls()) func (mock *MockRideEnvironment) transactionCalls() []struct { } { var calls []struct { @@ -662,7 +461,7 @@ func (mock *MockRideEnvironment) transactionCalls() []struct { // txID calls txIDFunc. func (mock *MockRideEnvironment) txID() rideType { if mock.txIDFunc == nil { - panic("MockRideEnvironment.txIDFunc: method is nil but RideEnvironment.txID was just called") + panic("MockRideEnvironment.txIDFunc: method is nil but Environment.txID was just called") } callInfo := struct { }{} @@ -674,7 +473,7 @@ func (mock *MockRideEnvironment) txID() rideType { // txIDCalls gets all the calls that were made to txID. // Check the length with: -// len(mockedRideEnvironment.txIDCalls()) +// len(mockedEnvironment.txIDCalls()) func (mock *MockRideEnvironment) txIDCalls() []struct { } { var calls []struct { diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index ffd8e3c3c..17040c321 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -5,7 +5,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -func CallVerifier(env RideEnvironment, tree *Tree) (RideResult, error) { +func CallVerifier(env Environment, tree *Tree) (RideResult, error) { e, err := treeVerifierEvaluator(env, tree) if err != nil { return nil, errors.Wrap(err, "failed to call verifier") @@ -13,14 +13,7 @@ func CallVerifier(env RideEnvironment, tree *Tree) (RideResult, error) { return e.evaluate() } -func invokeFunctionFromDApp(env RideEnvironment, recipient proto.Recipient, fnName rideString, listArgs rideList) (RideResult, error) { - - address, err := env.state().NewestRecipientToAddress(recipient) - if err != nil { - return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") - } - env.setNewDAppAddress(*address) - +func invokeFunctionFromDApp(env Environment, recipient proto.Recipient, fnName rideString, listArgs rideList) (RideResult, error) { newScript, err := env.state().GetByteTree(recipient) if err != nil { return nil, errors.Wrap(err, "failed to get script by recipient") @@ -38,7 +31,7 @@ func invokeFunctionFromDApp(env RideEnvironment, recipient proto.Recipient, fnNa return e.evaluate() } -func CallFunction(env RideEnvironment, tree *Tree, name string, args proto.Arguments) (RideResult, error) { +func CallFunction(env Environment, tree *Tree, name string, args proto.Arguments) (RideResult, error) { if name == "" { name = "default" } @@ -52,11 +45,20 @@ func CallFunction(env RideEnvironment, tree *Tree, name string, args proto.Argum if !ok { return rideResult, err } - if env.actions() == nil { + if tree.LibVersion < 5 { + return rideResult, err + } + + ws, ok := env.state().(*WrappedState) + if !ok { + return nil, errors.New("wrong state") + } + + if ws.act == nil { return rideResult, err } - fullActions := env.actions() + fullActions := ws.act fullActions = append(fullActions, DAppResult.actions...) DAppResult.actions = fullActions return DAppResult, err diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index a403794c3..6d8438081 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -26,9 +26,6 @@ func TestSimpleScriptEvaluation(t *testing.T) { stateFunc: func() types.SmartState { return state }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return 'T' }, @@ -36,7 +33,7 @@ func TestSimpleScriptEvaluation(t *testing.T) { for _, test := range []struct { comment string source string - env RideEnvironment + env Environment res bool }{ {`V1: true`, "AQa3b8tH", nil, true}, @@ -102,9 +99,6 @@ func TestFunctionsEvaluation(t *testing.T) { data := newDataTransaction() require.NoError(t, err) env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return nil - }, checkMessageLengthFunc: v3check, schemeFunc: func() byte { return 'W' @@ -189,7 +183,7 @@ func TestFunctionsEvaluation(t *testing.T) { name string text string script string - env RideEnvironment + env Environment result bool error bool }{ @@ -423,9 +417,6 @@ func TestDataFunctions(t *testing.T) { transactionFunc: func() rideObject { return txObj }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, heightFunc: func() rideInt { return rideInt(100500) }, @@ -461,7 +452,7 @@ func TestDataFunctions(t *testing.T) { } } -func testInvokeEnv(verifier bool) (RideEnvironment, *proto.InvokeScriptWithProofs) { +func testInvokeEnv(verifier bool) (Environment, *proto.InvokeScriptWithProofs) { tx := byte_helpers.InvokeScriptWithProofs.Transaction.Clone() txo, err := transactionToObject(proto.MainNetScheme, tx) if err != nil { @@ -479,9 +470,6 @@ func testInvokeEnv(verifier bool) (RideEnvironment, *proto.InvokeScriptWithProof } return txo }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -806,7 +794,7 @@ func TestScriptResult(t *testing.T) { ) } -func initWrappedState(state types.SmartState, envThis rideAddress) *wrappedState { +func initWrappedState(state types.SmartState, env *MockRideEnvironment) *WrappedState { var dataEntries diffDataEntries dataEntries.diffInteger = map[string]proto.IntegerDataEntry{} @@ -822,11 +810,11 @@ func initWrappedState(state types.SmartState, envThis rideAddress) *wrappedState leases := map[string]lease{} diffSt := &diffState{state: state, dataEntries: dataEntries, balances: balances, sponsorships: sponsorships, newAssetsInfo: newAssetInfo, oldAssetsInfo: oldAssetInfo, leases: leases} - wrappedSt := wrappedState{diff: *diffSt, envThis: envThis} - return &wrappedSt + + return &WrappedState{diff: *diffSt, cle: env.this().(rideAddress), scheme: env.scheme()} } -var wrappedSt wrappedState +var wrappedSt WrappedState var firstScript string var secondScript string var assetIDIssue crypto.Digest @@ -837,258 +825,6 @@ var addressCallablePK crypto.PublicKey func smartStateDappFromDapp() types.SmartState { return &MockSmartState{ - ApplyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - - for _, action := range actions { - switch res := action.(type) { - - case *proto.DataEntryScriptAction: - - switch dataEntry := res.Entry.(type) { - - case *proto.IntegerDataEntry: - intEntry := *dataEntry - address := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffInteger[dataEntry.Key+address.String()] = intEntry - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - case *proto.StringDataEntry: - stringEntry := *dataEntry - address := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffString[dataEntry.Key+address.String()] = stringEntry - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.BooleanDataEntry: - boolEntry := *dataEntry - address := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBool[dataEntry.Key+address.String()] = boolEntry - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.BinaryDataEntry: - binaryEntry := *dataEntry - address := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffBinary[dataEntry.Key+address.String()] = binaryEntry - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.DeleteDataEntry: - deleteEntry := *dataEntry - address := proto.Address(wrappedSt.envThis) - - wrappedSt.diff.dataEntries.diffDDelete[dataEntry.Key+address.String()] = deleteEntry - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(address, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - default: - - } - - case *proto.TransferScriptAction: - var senderAddress proto.Address - var senderPK crypto.PublicKey - if res.Sender != nil { - senderPK = *res.Sender - if senderPK.String() == addrPK.String() { - senderAddress = addr - } else { - senderAddress = addressCallable - } - - } else { - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - senderPK = pk - - senderAddress = proto.Address(wrappedSt.envThis) - } - - searchBalance, searchAddr, err := wrappedSt.diff.findBalance(res.Recipient, res.Asset) - if err != nil { - return nil, err - } - err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, res.Amount, res.Asset.ID, res.Recipient) - if err != nil { - return nil, err - } - senderRecipient := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderRecipient, res.Asset) - if err != nil { - return nil, err - } - - err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -res.Amount, res.Asset.ID, senderRecipient) - if err != nil { - return nil, err - } - - res.Sender = &senderPK - - case *proto.SponsorshipScriptAction: - var sponsorship diffSponsorship - sponsorship.MinFee = res.MinFee - - wrappedSt.diff.sponsorships[res.AssetID.String()] = sponsorship - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.IssueScriptAction: - var assetInfo diffNewAssetInfo - assetInfo.dAppIssuer = proto.Address(wrappedSt.envThis) - assetInfo.name = res.Name - assetInfo.description = res.Description - assetInfo.quantity = res.Quantity - assetInfo.decimals = res.Decimals - assetInfo.reissuable = res.Reissuable - assetInfo.script = res.Script - assetInfo.nonce = res.Nonce - - assetIDIssue = res.ID - - wrappedSt.diff.newAssetsInfo[res.ID.String()] = assetInfo - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.ReissueScriptAction: - searchNewAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchNewAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - break - } - wrappedSt.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - - case *proto.BurnScriptAction: - searchAsset := wrappedSt.diff.findNewAsset(res.AssetID) - if searchAsset == nil { - var assetInfo diffOldAssetInfo - - assetInfo.diffQuantity += -res.Quantity - - wrappedSt.diff.oldAssetsInfo[res.AssetID.String()] = assetInfo - - break - } - wrappedSt.diff.burnNewAsset(res.AssetID, res.Quantity) - - senderPK, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - res.Sender = &senderPK - case *proto.LeaseScriptAction: - senderAddress := proto.Address(wrappedSt.envThis) - - recipientSearchBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(res.Recipient, proto.NewOptionalAssetWaves()) - if err != nil { - return nil, err - } - err = wrappedSt.diff.changeLeaseIn(recipientSearchBalance, recipientSearchAddress, res.Amount, res.Recipient) - if err != nil { - return nil, err - } - - senderAccount := proto.NewRecipientFromAddress(senderAddress) - senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(senderAccount, proto.NewOptionalAssetWaves()) - if err != nil { - return nil, err - } - - err = wrappedSt.diff.changeLeaseOut(senderSearchBalance, senderSearchAddr, res.Amount, senderAccount) - if err != nil { - return nil, err - } - - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(senderAddress, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - - wrappedSt.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) - - res.Sender = &pk - case *proto.LeaseCancelScriptAction: - - searchLease, err := wrappedSt.diff.findLeaseByIDForCancel(res.LeaseID) - if err != nil { - return nil, errors.Errorf("failed to find lease by leaseID") - } - if searchLease == nil { - return nil, errors.Errorf("there is no lease to cancel") - } - recipientBalance, recipientSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Recipient, proto.NewOptionalAssetWaves()) - if err != nil { - return nil, err - } - if recipientBalance == nil { - return nil, errors.Errorf("there is no balance to cancel lease") - } - - senderBalance, senderSearchAddress, err := wrappedSt.diff.findBalance(searchLease.Sender, proto.NewOptionalAssetWaves()) - if err != nil { - return nil, err - } - if senderBalance == nil { - return nil, errors.Errorf("there is no balance to cancel lease") - } - - wrappedSt.diff.cancelLease(*searchLease, senderSearchAddress, recipientSearchAddress) - - pk, err := wrappedSt.diff.state.NewestScriptPKByAddr(proto.Address(wrappedSt.envThis), false) - if err != nil { - return nil, errors.Wrap(err, "failed to get public key by address") - } - - res.Sender = &pk - default: - } - - } - return actions, nil - }, NewestLeasingInfoFunc: func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { return nil, nil }, @@ -1106,6 +842,18 @@ func smartStateDappFromDapp() types.SmartState { } return script, nil }, + NewestScriptByAssetFunc: func(asset proto.OptionalAsset) (proto.Script, error) { + if asset.ID.String() == "13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ" { + script := "BQQAAAALZEFwcEFkZHJlc3MJAAQmAAAAAQIAAAAjM1A4ZVpWS1M3YTR0cm9HY2t5dHhhZWZMQWk5dzdQNWFNbmEEAAAAByRtYXRjaDAFAAAAAnR4AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAA9CdXJuVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABJSZWlzc3VlVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABlTZXRBc3NldFNjcmlwdFRyYW5zYWN0aW9uBAAAAAJ0eAUAAAAHJG1hdGNoMAkAAAAAAAACCAUAAAACdHgAAAAGc2VuZGVyBQAAAAtkQXBwQWRkcmVzcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAXTWFzc1RyYW5zZmVyVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABNUcmFuc2ZlclRyYW5zYWN0aW9uBAAAAAJ0eAUAAAAHJG1hdGNoMAkAAAAAAAACCAUAAAACdHgAAAAGc2VuZGVyBQAAAAtkQXBwQWRkcmVzcwf56Ssf" + + src, err := base64.StdEncoding.DecodeString(script) + if err != nil { + return nil, err + } + return src, nil + } + return nil, nil + }, NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { return recipient.Address, nil }, @@ -1135,57 +883,10 @@ func smartStateDappFromDapp() types.SmartState { }, NewestAccountBalanceFunc: func(account proto.Recipient, assetID []byte) (uint64, error) { balance := 0 - - asset, err := proto.NewOptionalAssetFromBytes(assetID) - if err != nil { - return 0, err - } - balanceDiff, _, err := wrappedSt.diff.findBalance(account, *asset) - if err != nil { - return 0, err - } - if balanceDiff != nil { - resBalance := int64(balance) + balanceDiff.regular - return uint64(resBalance), nil - - } return uint64(balance), nil }, NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { - balance := 0 - wavesBalanceDiff, searchAddress, err := wrappedSt.diff.findBalance(account, proto.NewOptionalAssetWaves()) - if err != nil { - return nil, err - } - if wavesBalanceDiff != nil { - resRegular := wavesBalanceDiff.regular + int64(balance) - resAvailable := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut) + int64(balance) - resEffective := (wavesBalanceDiff.regular - wavesBalanceDiff.leaseOut + wavesBalanceDiff.leaseIn) + int64(balance) - resLeaseIn := wavesBalanceDiff.leaseIn + int64(balance) - resLeaseOut := wavesBalanceDiff.leaseOut + int64(balance) - - err := wrappedSt.diff.addEffectiveToHistory(searchAddress, resEffective) - if err != nil { - return nil, err - } - - resGenerating := wrappedSt.diff.findMinGenerating(wrappedSt.diff.balances[searchAddress].effectiveHistory, int64(balance)) - - return &proto.FullWavesBalance{ - Regular: uint64(resRegular), - Generating: uint64(resGenerating), - Available: uint64(resAvailable), - Effective: uint64(resEffective), - LeaseIn: uint64(resLeaseIn), - LeaseOut: uint64(resLeaseOut)}, nil - - } - _, searchAddr := wrappedSt.diff.createNewWavesBalance(account) - err = wrappedSt.diff.addEffectiveToHistory(searchAddr, int64(balance)) - if err != nil { - return nil, err - } return &proto.FullWavesBalance{ Regular: 0, Generating: 0, @@ -1195,198 +896,96 @@ func smartStateDappFromDapp() types.SmartState { LeaseOut: 0}, nil }, RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if intDataEntry := wrappedSt.diff.findIntFromDataEntryByKey(key, address.String()); intDataEntry != nil { - return intDataEntry, nil - } - return nil, nil }, RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if boolDataEntry := wrappedSt.diff.findBoolFromDataEntryByKey(key, address.String()); boolDataEntry != nil { - return boolDataEntry, nil - } return nil, nil }, RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - - if stringDataEntry := wrappedSt.diff.findStringFromDataEntryByKey(key, address.String()); stringDataEntry != nil { - return stringDataEntry, nil - } return nil, nil }, RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { - address, err := wrappedSt.diff.state.NewestRecipientToAddress(account) - if err != nil { - return nil, err - } - - if deletedDataEntry := wrappedSt.diff.findDeleteFromDataEntryByKey(key, address.String()); deletedDataEntry != nil { - return nil, nil - } - if binaryDataEntry := wrappedSt.diff.findBinaryFromDataEntryByKey(key, address.String()); binaryDataEntry != nil { - return binaryDataEntry, nil - } return nil, nil }, NewestAssetIsSponsoredFunc: func(assetID crypto.Digest) (bool, error) { - if cost := wrappedSt.diff.findSponsorship(assetID); cost != nil { - if *cost == 0 { - return false, nil - } - return true, nil - } return false, nil }, NewestAssetInfoFunc: func(assetID crypto.Digest) (*proto.AssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - assetFromStore := proto.AssetInfo{} - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} - - scripted := false - if searchNewAsset.script != nil { - scripted = true + if assetID.String() == "13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ" { + + return &proto.AssetInfo{ + ID: assetID, + Quantity: 1000, + Decimals: '8', + Issuer: addressCallable, + IssuerPublicKey: addressCallablePK, + Reissuable: true, + Scripted: true, + Sponsored: false, + }, nil } - return &proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - }, nil - + return nil, nil }, NewestFullAssetInfoFunc: func(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - searchNewAsset := wrappedSt.diff.findNewAsset(assetID) - - if searchNewAsset == nil { - - assetFromStore := proto.FullAssetInfo{} - - if oldAssetFromDiff := wrappedSt.diff.findOldAsset(assetID); oldAssetFromDiff != nil { - quantity := int64(assetFromStore.Quantity) + oldAssetFromDiff.diffQuantity - - if quantity >= 0 { - assetFromStore.Quantity = uint64(quantity) - return &assetFromStore, nil - } - - return nil, errors.Errorf("quantity of the asset is negative") + if assetID.String() == "13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ" { + assetInfo := proto.AssetInfo{ + ID: assetID, + Quantity: 1000, + Decimals: '8', + Issuer: addressCallable, + IssuerPublicKey: addressCallablePK, + Reissuable: true, + Scripted: true, + Sponsored: false, } - return &assetFromStore, nil - } - - issuerPK := crypto.PublicKey{} + scriptB := "BQQAAAALZEFwcEFkZHJlc3MJAAQmAAAAAQIAAAAjM1A4ZVpWS1M3YTR0cm9HY2t5dHhhZWZMQWk5dzdQNWFNbmEEAAAAByRtYXRjaDAFAAAAAnR4AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAA9CdXJuVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABJSZWlzc3VlVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABlTZXRBc3NldFNjcmlwdFRyYW5zYWN0aW9uBAAAAAJ0eAUAAAAHJG1hdGNoMAkAAAAAAAACCAUAAAACdHgAAAAGc2VuZGVyBQAAAAtkQXBwQWRkcmVzcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAXTWFzc1RyYW5zZmVyVHJhbnNhY3Rpb24EAAAAAnR4BQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAJ0eAAAAAZzZW5kZXIFAAAAC2RBcHBBZGRyZXNzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABNUcmFuc2ZlclRyYW5zYWN0aW9uBAAAAAJ0eAUAAAAHJG1hdGNoMAkAAAAAAAACCAUAAAACdHgAAAAGc2VuZGVyBQAAAAtkQXBwQWRkcmVzcwf56Ssf" - scripted := false - if searchNewAsset.script != nil { - scripted = true - } + src, err := base64.StdEncoding.DecodeString(scriptB) + if err != nil { + return nil, err + } - assetInfo := proto.AssetInfo{ - ID: assetID, - Quantity: uint64(searchNewAsset.quantity), - Decimals: uint8(searchNewAsset.decimals), - Issuer: searchNewAsset.dAppIssuer, - IssuerPublicKey: issuerPK, - Reissuable: searchNewAsset.reissuable, - Scripted: scripted, - Sponsored: false, - } - scriptInfo := proto.ScriptInfo{ - Bytes: searchNewAsset.script, - } + scriptInfo := proto.ScriptInfo{ + Version: 5, + Bytes: src, + Base64: "", + Complexity: 0, + } - sponsorshipCost := int64(0) - if sponsorship := wrappedSt.diff.findSponsorship(assetID); sponsorship != nil { - sponsorshipCost = *sponsorship + return &proto.FullAssetInfo{ + AssetInfo: assetInfo, + Name: "CatCoin", + Description: "", + ScriptInfo: scriptInfo, + SponsorshipCost: uint64(0), + }, nil } - - return &proto.FullAssetInfo{ - AssetInfo: assetInfo, - Name: searchNewAsset.name, - Description: searchNewAsset.description, - ScriptInfo: scriptInfo, - SponsorshipCost: uint64(sponsorshipCost), - }, nil + return nil, nil }, } } -var envActions []proto.ScriptAction -var invCount uint64 var thisAddress proto.Address var tx *proto.InvokeScriptWithProofs var inv rideObject var id []byte +func WrappedStateFunc() types.SmartState { + return &wrappedSt +} + var envDappFromDapp = &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return envActions - }, - appendActionsFunc: func(actions []proto.ScriptAction) { - envActions = append(envActions, actions...) - }, SetInvocationFunc: func(invocation rideObject) { inv = invocation }, - smartAppendActionsFunc: func(actions []proto.ScriptAction) error { - modifiedActions, err := smartStateDappFromDapp().ApplyToState(actions) - if err != nil { - return nil - } - envActions = append(envActions, modifiedActions...) - return nil - }, schemeFunc: func() byte { return proto.MainNetScheme }, - stateFunc: smartStateDappFromDapp, - + stateFunc: WrappedStateFunc, txIDFunc: func() rideType { return rideBytes(id) }, @@ -1394,15 +993,8 @@ var envDappFromDapp = &MockRideEnvironment{ return rideAddress(thisAddress) }, setNewDAppAddressFunc: func(address proto.Address) { - wrappedSt.envThis = rideAddress(address) thisAddress = address - }, - applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - modifiedActions, err := smartStateDappFromDapp().ApplyToState(envActions) - if err != nil { - return nil, err - } - return modifiedActions, nil + wrappedSt.cle = rideAddress(address) }, transactionFunc: func() rideObject { obj, _ := transactionToObject(proto.MainNetScheme, tx) @@ -1411,17 +1003,13 @@ var envDappFromDapp = &MockRideEnvironment{ invocationFunc: func() rideObject { return inv }, - invCountFunc: func() uint64 { - return invCount - }, - incrementInvCountFunc: func() { - invCount++ + timestampFunc: func() uint64 { + return 1564703444249 }, } func tearDownDappFromDapp() { - - wrappedSt = wrappedState{} + wrappedSt = WrappedState{} firstScript = "" secondScript = "" assetIDIssue = crypto.Digest{} @@ -1430,13 +1018,65 @@ func tearDownDappFromDapp() { addrPK = crypto.PublicKey{} addressCallablePK = crypto.PublicKey{} - envActions = nil - invCount = 0 thisAddress = proto.Address{} tx = nil id = nil } +func AddExternalPayments(externalPayments proto.ScriptPayments, callerPK crypto.PublicKey) error { + caller, err := proto.NewAddressFromPublicKey(envDappFromDapp.scheme(), callerPK) + if err != nil { + return err + } + recipient := proto.NewRecipientFromAddress(wrappedSt.callee()) + + for _, payment := range externalPayments { + senderBalance, err := wrappedSt.NewestAccountBalance(proto.NewRecipientFromAddress(caller), payment.Asset.ID.Bytes()) + if err != nil { + return err + } + if senderBalance < payment.Amount { + return errors.New("not enough money for tx attached payments") + } + + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(recipient, payment.Asset) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, int64(payment.Amount), payment.Asset.ID, recipient) + if err != nil { + return err + } + + callerRcp := proto.NewRecipientFromAddress(caller) + senderSearchBalance, senderSearchAddr, err := wrappedSt.diff.findBalance(callerRcp, payment.Asset) + if err != nil { + return err + } + + err = wrappedSt.diff.changeBalance(senderSearchBalance, senderSearchAddr, -int64(payment.Amount), payment.Asset.ID, callerRcp) + if err != nil { + return err + } + } + return nil +} + +func AddWavesToSender(senderAddress proto.Address, amount int64, asset proto.OptionalAsset) error { + senderRecipient := proto.NewRecipientFromAddress(senderAddress) + + searchBalance, searchAddr, err := wrappedSt.diff.findBalance(senderRecipient, asset) + if err != nil { + return err + } + err = wrappedSt.diff.changeBalance(searchBalance, searchAddr, amount, asset.ID, senderRecipient) + if err != nil { + return err + } + + return nil +} + func TestInvokeDAppFromDAppAllActions(t *testing.T) { /* script 1 @@ -1446,7 +1086,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { @Callable(i) func test() = { - let res = Invoke(Address(base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP'), "testActions",[], [AttachedPayment(base58'', 1234), AttachedPayment(base58'', 1234)]) + let res = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "testActions",[], [AttachedPayment(base58'', 1234), AttachedPayment(base58'', 1234)]) if res == 17 then [ @@ -1468,8 +1108,8 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { let assetId = asset.calculateAssetId() ([ - ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 1, unit), - Lease(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 10), + ScriptTransfer(Address(base58'3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv'), 1, unit), + Lease(Address(base58'3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv'), 10), BinaryEntry("bin", base58''), BooleanEntry("bool", true), IntegerEntry("int", 1), @@ -1490,16 +1130,18 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(addr) - addressCallable, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) - + recipient := proto.NewRecipientFromAddress(addr) addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) @@ -1520,16 +1162,18 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } - inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXI7OtElyTpMrsOf5PRtbNVk0t+xD7Y5h6AgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAA3aHKo" - secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAANiaW4BAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAEYm9vbAYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAoJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQIAAAADc3RyCQAETAAAAAIFAAAABWFzc2V0CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAHYXNzZXRJZAAAAAAAAAAACgcJAARMAAAAAgkBAAAABEJ1cm4AAAACBQAAAAdhc3NldElkAAAAAAAAAAAFBQAAAANuaWwAAAAAAAAAABEAAAAAAOn+Sg==" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEdGVzdAAAAAAEAAAAA3JlcwkAA/wAAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXSbIqC+dSm+dDCCL8KamODy9oLyPQygrLAgAAAAt0ZXN0QWN0aW9ucwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACAQAAAAAAAAAAAAAABNIJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIBAAAAAAAAAAAAAAAE0gUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAABtSYQY" + secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAAABAAAAAVhc3NldAkABEMAAAAHAgAAAAdDYXRDb2luAgAAAAAAAAAAAAAAAAEAAAAAAAAAAAAGBQAAAAR1bml0AAAAAAAAAAAABAAAAAdhc3NldElkCQAEOAAAAAEFAAAABWFzc2V0CQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABAQAAABoBV5hs3CAFUz6eTef/H4C7v1yCbCqvykvRuQAAAAAAAAAAAQUAAAAEdW5pdAkABEwAAAACCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVeYbNwgBVM+nk3n/x+Au79cgmwqr8pL0bkAAAAAAAAAAAoJAARMAAAAAgkBAAAAC0JpbmFyeUVudHJ5AAAAAgIAAAADYmluAQAAAAAJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANpbnQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQIAAAADc3RyCQAETAAAAAIFAAAABWFzc2V0CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAHYXNzZXRJZAAAAAAAAAAACgcJAARMAAAAAgkBAAAABEJ1cm4AAAACBQAAAAdhc3NldElkAAAAAAAAAAAFBQAAAANuaWwAAAAAAAAAABEAAAAAeF27eQ==" id = bytes.Repeat([]byte{0}, 32) @@ -1564,13 +1208,17 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { smartState := smartStateDappFromDapp - invCount = 0 thisAddress = addr env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + pid, ok := env.txID().(rideBytes) require.True(t, ok) d, err := crypto.NewDigestFromBytes(pid) @@ -1578,11 +1226,7 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { expectedIssueWrites[0].ID = proto.GenerateIssueScriptActionID(expectedIssueWrites[0].Name, expectedIssueWrites[0].Description, int64(expectedIssueWrites[0].Decimals), expectedIssueWrites[0].Quantity, expectedIssueWrites[0].Reissuable, expectedIssueWrites[0].Nonce, d) expectedReissueWrites[0].AssetID = expectedIssueWrites[0].ID expectedBurnWrites[0].AssetID = expectedIssueWrites[0].ID - - // start balance - bal := wrappedSt.diff.balances[addr.String()+proto.OptionalAsset{}.String()] - bal.regular = 2468 - wrappedSt.diff.balances[addr.String()+proto.OptionalAsset{}.String()] = bal + assetIDIssue = expectedIssueWrites[0].ID src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -1618,14 +1262,14 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { assert.Equal(t, expectedActionsResult, sr) fullBalanceExpected := &proto.FullWavesBalance{ - Regular: 1, + Regular: 7533, Generating: 0, - Available: 1, - Effective: 11, + Available: 7533, + Effective: 7543, LeaseIn: 10, LeaseOut: 0, } - fullBalance, err := smartState().NewestFullWavesBalance(recipient) + fullBalance, err := wrappedSt.NewestFullWavesBalance(recipient) require.NoError(t, err) assert.Equal(t, fullBalance, fullBalanceExpected) @@ -1638,17 +1282,24 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { LeaseIn: 0, LeaseOut: 10, } - fullBalanceCallable, err := smartState().NewestFullWavesBalance(recipientCallable) + fullBalanceCallable, err := wrappedSt.NewestFullWavesBalance(recipientCallable) require.NoError(t, err) assert.Equal(t, fullBalanceCallable, fullBalanceCallableExpected) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff - balance := diffBalance{regular: 1, leaseIn: 10, asset: assetExp, effectiveHistory: []int64{11}} + expectedDiffResult := initWrappedState(smartState(), env).diff + balance := diffBalance{regular: 7533, leaseIn: 10, asset: assetExp, effectiveHistory: []int64{7543}} expectedDiffResult.balances[addr.String()+assetExp.String()] = balance - balanceCallable := diffBalance{regular: 2467, leaseOut: 10, asset: assetExp, effectiveHistory: []int64{2457}} + balanceSender := diffBalance{regular: 0, leaseOut: 0, asset: assetExp} + expectedDiffResult.balances[senderAddress.String()+assetExp.String()] = balanceSender + + balanceCallable := diffBalance{regular: 2467, leaseOut: 10, asset: assetExp, effectiveHistory: []int64{2467, 2457}} expectedDiffResult.balances[addressCallable.String()+assetExp.String()] = balanceCallable + assetFromIssue := *proto.NewOptionalAssetFromDigest(sr.Issues[0].ID) + balanceCallableAsset := diffBalance{regular: 1, leaseOut: 0, asset: assetFromIssue} + expectedDiffResult.balances[addressCallable.String()+assetFromIssue.String()] = balanceCallableAsset + intEntry1 := proto.IntegerDataEntry{Key: "int", Value: 1} expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry1 @@ -1717,10 +1368,9 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) @@ -1759,13 +1409,10 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { smartState := smartStateDappFromDapp - envActions = nil - - invCount = 0 thisAddress = addr env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -1797,7 +1444,7 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff intEntry1 := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addr.String()] = intEntry1 @@ -1817,15 +1464,15 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) + let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW'), "bar") + let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW')) + let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if data == 1 then if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 @@ -1864,23 +1511,24 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(addr) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err = proto.NewAddressFromString("3Mt4Xf9aoGcdcMZNb8eJn41QK2qthTJQbCW") - require.NoError(t, err) - - recipientCallable := proto.NewRecipientFromAddress(addressCallable) - call := proto.FunctionCall{ Default: false, Name: "cancel", @@ -1895,15 +1543,18 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQteW/kI73AqAt068nsEPWCEr5LDuT5hssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAALVWK3g==" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAAjMpPSg==" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" id = bytes.Repeat([]byte{0}, 32) @@ -1921,15 +1572,18 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { smartState := smartStateDappFromDapp - envActions = nil - invCount = 0 thisAddress = addr env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -1959,13 +1613,15 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -14, effectiveHistory: []int64{0, -14}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9986, effectiveHistory: []int64{10000, 9986}} + balanceSender := diffBalance{regular: 0, leaseOut: 0, asset: proto.OptionalAsset{}} balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 14, effectiveHistory: []int64{0, 14}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry expectedDiffResult.balances[addressCallable.String()+proto.NewOptionalAssetWaves().String()] = balanceCallable + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender expectedDiffResult.balances[addr.String()+proto.NewOptionalAssetWaves().String()] = balanceMain assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) @@ -1984,24 +1640,24 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar") + let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if data == 1 then if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 then - let r1 = Invoke(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) + let r1 = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 18)]) if r1 == r1 then let b3 = wavesBalance(this) - let ob3 = wavesBalance(Address(base58'3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6')) + let ob3 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if ob2.regular+15 == ob3.regular && b2.regular == b3.regular+15 then [ @@ -2020,7 +1676,6 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { else throw("Imposible") } - */ /* @@ -2043,21 +1698,24 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(addr) - arguments := proto.Arguments{} - arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err = proto.NewAddressFromString("3MsbuBXcYd8NbvP1bi4LVwKAzscz85GeYe6") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) - + recipient := proto.NewRecipientFromAddress(addr) addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ Default: false, Name: "cancel", @@ -2072,15 +1730,18 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQocCxa4m9Bw8yStUOQlGgM9H8M0U0Z5zsDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVChwLFrib0HDzJK1Q5CUaAz0fwzRTRnnOwMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB/eYz1" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADggFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAAOBwQAAAACcjEJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABIFAAAAA25pbAMJAAAAAAAAAgUAAAACcjEFAAAAAnIxBAAAAAJiMwkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjMJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywMDCQAAAAAAAAIJAABkAAAAAggFAAAAA29iMgAAAAdyZWd1bGFyAAAAAAAAAAAPCAUAAAADb2IzAAAAB3JlZ3VsYXIJAAAAAAAAAggFAAAAAmIyAAAAB3JlZ3VsYXIJAABkAAAAAggFAAAAAmIzAAAAB3JlZ3VsYXIAAAAAAAAAAA8HCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANrZXkAAAAAAAAAAAEFAAAAA25pbAkAAAIAAAABAgAAAB9CYWQgYmFsYW5jZSBhZnRlciBzZWNvbmQgaW52b2tlCQAAAgAAAAECAAAACUltcG9zaWJsZQkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAABDUPNk" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2JhcgAAAAAAAAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAMFAAAABHVuaXQFAAAAA25pbAAAAAAAAAAAEQAAAAAyrXjp" id = bytes.Repeat([]byte{0}, 32) @@ -2100,15 +1761,18 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { smartState := smartStateDappFromDapp - envActions = nil thisAddress = addr - invCount = 0 env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2138,13 +1802,15 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -29, effectiveHistory: []int64{0, -14, -29}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9971, effectiveHistory: []int64{10000, 9986, 9971}} + balanceSender := diffBalance{regular: 0, leaseOut: 0, asset: proto.OptionalAsset{}} balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 29, effectiveHistory: []int64{0, 14, 29}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) @@ -2162,22 +1828,22 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { @Callable(i) func back() = { - [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), 2, unit)] + [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] } @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak'), "bar") + let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") let tdata = getIntegerValue(this, "key") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak')) + let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if data == 1 && tdata == 0 then if ob1.regular+16 == ob2.regular && b1.regular == b2.regular+16 @@ -2221,21 +1887,24 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(addr) - arguments := proto.Arguments{} - arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err = proto.NewAddressFromString("3NCXaXdPf9wQSR5HRV9t6mcYk1N4fJ5Luak") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) - + recipient := proto.NewRecipientFromAddress(addr) addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ Default: false, Name: "cancel", @@ -2250,14 +1919,17 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT4CVQEBqpuGv8qY0Og5VDARYVZ6wivPc0AAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVPgJVAQGqm4a/ypjQ6DlUMBFhVnrCK89zQMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAACP+w2w=" + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssAAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAOgXYAY=" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" id = bytes.Repeat([]byte{0}, 32) @@ -2269,22 +1941,25 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp - envActions = nil thisAddress = addr - invCount = 0 env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2314,15 +1989,17 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -16, effectiveHistory: []int64{0, -16}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9984, effectiveHistory: []int64{10000, 9984}} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 16, effectiveHistory: []int64{0, 16}} intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) @@ -2340,21 +2017,21 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { @Callable(i) func back() = { - [ScriptTransfer(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), 2, unit)] + [ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] } @Callable(i) func foo() = { let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc')) + let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if b1 == b1 && ob1 == ob1 then - let r = Invoke(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) if r == 17 then - let data = getIntegerValue(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc'), "bar") + let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc')) + let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) if data == 1 then if ob1.regular+13 == ob2.regular && b1.regular == b2.regular+13 @@ -2397,21 +2074,24 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) require.NoError(t, err) - recipient := proto.NewRecipientFromAddress(addr) - arguments := proto.Arguments{} - arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - addressCallable, err = proto.NewAddressFromString("3NCkU1WZUjP5a8EwVRQRrmSBZKTucBNEPxc") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) - + recipient := proto.NewRecipientFromAddress(addr) addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) require.NoError(t, err) + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ Default: false, Name: "cancel", @@ -2426,14 +2106,17 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: nil, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFU+nlLLlJlc8+xTjSzsqlWzv76DyZcRlcJAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVT6eUsuUmVzz7FONLOyqVbO/voPJlxGVwkDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAADKkWnw==" + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXSbIqC+dSm+dDCCL8KamODy9oLyPQygrLAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAA0WFyhQ==" secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAADBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACzZnMp" id = bytes.Repeat([]byte{0}, 32) @@ -2444,23 +2127,25 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp - envActions = nil thisAddress = addr - - invCount = 0 env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2490,19 +2175,22 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -13, effectiveHistory: []int64{0, -13}} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9987, effectiveHistory: []int64{10000, 9987}} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 13, effectiveHistory: []int64{0, 13}} intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() + } func TestInvokeDAppFromDAppScript6(t *testing.T) { @@ -2532,7 +2220,7 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) @@ -2565,13 +2253,11 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { smartState := smartStateDappFromDapp - envActions = nil thisAddress = addr - invCount = 0 env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -2603,7 +2289,7 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { } assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) @@ -2643,7 +2329,7 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { if err != nil { b.Fatal("Expected no errors, got error ", err) } - addr, err = proto.NewAddressFromString("3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP") + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") if err != nil { b.Fatal("Expected no errors, got error ", err) } @@ -2678,13 +2364,11 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { smartState := smartStateDappFromDapp - envActions = nil thisAddress = addr - invCount = 0 env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) @@ -2749,6 +2433,11 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { proofs := proto.NewProofs() proofs.Proofs = []proto.B58Bytes{proof[:]} require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + senderRecipient := proto.NewRecipientFromAddress(senderAddress) addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) @@ -2774,18 +2463,17 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { ID: &txID, Proofs: proofs, ChainID: proto.MainNetScheme, - SenderPK: addrPK, + SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, Payments: proto.ScriptPayments{proto.ScriptPayment{ - Amount: 500, + Amount: 10000, Asset: proto.OptionalAsset{}, }}, FeeAsset: proto.OptionalAsset{}, Fee: 900000, Timestamp: 1564703444249, } - inv, _ = invocationToObject(4, proto.MainNetScheme, tx) firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMAAAAAAAAAABEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCQAAaAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAAMZXhjaGFuZ2VSYXRlBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlAAAAANOWG8w=" @@ -2798,18 +2486,22 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Recipient: recipient, Amount: 2500, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Recipient: senderRecipient, Amount: 50000, Asset: proto.OptionalAsset{}, InvalidAsset: false}, } smartState := smartStateDappFromDapp - invCount = 0 thisAddress = addr env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2840,12 +2532,18 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 10000} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() } @@ -2882,7 +2580,8 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { ([ IntegerEntry("int", 1) ], 17) - } */ + } + */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) @@ -2891,6 +2590,10 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { proofs := proto.NewProofs() proofs.Proofs = []proto.B58Bytes{proof[:]} require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) @@ -2917,11 +2620,11 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { ID: &txID, Proofs: proofs, ChainID: proto.MainNetScheme, - SenderPK: addrPK, + SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, Payments: proto.ScriptPayments{proto.ScriptPayment{ - Amount: 500, + Amount: 10000, Asset: proto.OptionalAsset{}, }}, FeeAsset: proto.OptionalAsset{}, @@ -2946,13 +2649,17 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { smartState := smartStateDappFromDapp - invCount = 0 thisAddress = addr env := envDappFromDapp - NewWrappedSt := initWrappedState(smartState(), rideAddress(addr)) + NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2983,11 +2690,13 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { assert.Equal(t, expectedActionsResult, sr) - expectedDiffResult := initWrappedState(smartState(), rideAddress(addr)).diff + expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: -1} + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9999} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry @@ -2999,6 +2708,185 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { } +func TestInvokeDAppFromDAppSmartAssetValidation(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + let assetId = base58'13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ' + + @Callable(i) + func test() = { + let res = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "call",nil, nil) + if res == 17 + then + nil + else + throw("Bad returned value") + } + */ + + /* script 2 + + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let assetId = base58'13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ' + + @Callable(i) + func call() = { + ([ + Reissue(assetId, 100, false), + Burn(assetId, 50), + ScriptTransfer(i.caller, 1, assetId) + ], 17) + } + */ + /* smart asset script + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE EXPRESSION #-} + {-# SCRIPT_TYPE ASSET #-} + + let dAppAddress = addressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + match tx { + case tx: BurnTransaction => + (tx.sender == dAppAddress) + case tx: ReissueTransaction => + (tx.sender == dAppAddress) + case tx: SetAssetScriptTransaction => + (tx.sender == dAppAddress) + case tx: MassTransferTransaction => + (tx.sender == dAppAddress) + case tx: TransferTransaction => + (tx.sender == dAppAddress) + case _ => + false + } + */ + + assetCat, err := proto.NewOptionalAssetFromString("13YvHUb3bg7sXgExc6kFcCUKm6WYpJX9rLpHVhiyJNGJ") + require.NoError(t, err) + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + inv, _ = invocationToObject(5, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAHYXNzZXRJZAEAAAAgAKdAj/iZUd+zAOo6DTO6IvheatMyaLi7as+C+lV4EDMAAAABAAAAAWkBAAAABHRlc3QAAAAABAAAAANyZXMJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAAEY2FsbAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA3JlcwAAAAAAAAAAEQUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAAnQdRv" + secondScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAHYXNzZXRJZAEAAAAgAKdAj/iZUd+zAOo6DTO6IvheatMyaLi7as+C+lV4EDMAAAABAAAAAWkBAAAABGNhbGwAAAAACQAFFAAAAAIJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAdhc3NldElkAAAAAAAAAABkBwkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAAB2Fzc2V0SWQAAAAAAAAAADIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyAAAAAAAAAAABBQAAAAdhc3NldElkBQAAAANuaWwAAAAAAAAAABEAAAAA4X8UHg==" + + id = bytes.Repeat([]byte{0}, 32) + + expectedReissueWrites := []*proto.ReissueScriptAction{ + {Sender: &addressCallablePK, Quantity: 100, Reissuable: false, AssetID: assetCat.ID}, + } + expectedBurnWrites := []*proto.BurnScriptAction{ + {Sender: &addressCallablePK, Quantity: 50, AssetID: assetCat.ID}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: *assetCat, InvalidAsset: false}, + } + + smartState := smartStateDappFromDapp + + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(addressCallable, 10000, *assetCat) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: expectedReissueWrites, + Burns: expectedBurnWrites, + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + balance := diffBalance{regular: 1, leaseIn: 0, asset: *assetCat} + expectedDiffResult.balances[addr.String()+assetCat.String()] = balance + + balanceCallable := diffBalance{regular: 9999, leaseOut: 0, asset: *assetCat} + expectedDiffResult.balances[addressCallable.String()+assetCat.String()] = balanceCallable + + oldAsset := diffOldAssetInfo{diffQuantity: 50} + expectedDiffResult.oldAssetsInfo[assetIDIssue.String()] = oldAsset + + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + assert.Equal(t, expectedDiffResult.sponsorships, wrappedSt.diff.sponsorships) + assert.Equal(t, expectedDiffResult.leases, wrappedSt.diff.leases) + + tearDownDappFromDapp() +} + func TestMatchOverwrite(t *testing.T) { /* {-# STDLIB_VERSION 1 #-} @@ -3038,9 +2926,6 @@ func TestMatchOverwrite(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - applyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - return nil, nil - }, heightFunc: func() rideInt { return 368430 }, @@ -3298,9 +3183,6 @@ func TestWhaleDApp(t *testing.T) { heightFunc: func() rideInt { return 368430 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -3435,9 +3317,6 @@ func TestExchangeDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.MainNetScheme }, @@ -3606,9 +3485,6 @@ func TestBankDApp(t *testing.T) { schemeFunc: func() byte { return proto.MainNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -3733,9 +3609,6 @@ func TestLigaDApp1(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -3895,9 +3768,6 @@ func TestLigaDApp1(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -4077,9 +3947,6 @@ func TestTestingDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -4207,9 +4074,6 @@ func TestDropElementDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -4329,9 +4193,6 @@ func TestMathDApp(t *testing.T) { heightFunc: func() rideInt { return 1642207 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.TestNetScheme }, @@ -4452,9 +4313,6 @@ func TestDAppWithInvalidAddress(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -4583,9 +4441,6 @@ func Test8Ball(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -4709,9 +4564,6 @@ func TestIntegerEntry(t *testing.T) { heightFunc: func() rideInt { return 844761 }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.StageNetScheme }, @@ -4772,9 +4624,6 @@ func TestAssetInfoV3V4(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, stateFunc: func() types.SmartState { return &MockSmartState{ NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { @@ -4863,9 +4712,6 @@ func TestDAppWithFullIssue(t *testing.T) { txIDFunc: func() rideType { return rideBytes(id) }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, } res, err := CallFunction(env, tree, "issue", proto.Arguments{&proto.StringArgument{Value: "xxx"}}) require.NoError(t, err) @@ -4892,9 +4738,6 @@ func TestDAppWithSimpleIssue(t *testing.T) { txIDFunc: func() rideType { return rideBytes(id) }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, } res, err := CallFunction(env, tree, "issue", proto.Arguments{&proto.StringArgument{Value: "xxx"}}) require.NoError(t, err) @@ -4960,9 +4803,6 @@ func TestBadType(t *testing.T) { schemeFunc: func() byte { return proto.TestNetScheme }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, @@ -5116,9 +4956,6 @@ func TestNoDeclaration(t *testing.T) { blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, - actionsFunc: func() []proto.ScriptAction { - return nil - }, stateFunc: func() types.SmartState { return &MockSmartState{ AddingBlockHeightFunc: func() (uint64, error) { @@ -5285,9 +5122,6 @@ func TestZeroReissue(t *testing.T) { "share_token_id": mustBytesFromBase64("Q3Uk9ZN5g5+xynU7VGPXUg1eVga04VYXnnZ0q+M1dxQ="), } env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return nil - }, heightFunc: func() rideInt { return 451323 }, @@ -5526,9 +5360,6 @@ func TestStageNet2(t *testing.T) { } dp := newJsonDataProvider(`[{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"aa","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"dappAddress","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"total_amount","intValue":"600900000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"masterAddress","stringValue":"3MkT3qvGwdLrSs2Cfx3E29ffaM5GYrEZegz"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"assetId_2020-10-3","stringValue":"Eo7N1sjexrfu6mx5LrG3suovSaXaBNnmYfvqJsMzSYE8"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"assetId_2020-10-5","stringValue":"J2j4PRKXuUKUZCP345EXAHYF2gRg15JsYQYtFT4GNPda"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_total_amount_2020-10-3","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_total_amount_2020-10-5","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","stringValue":"2020-11-23"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","stringValue":"2020-11-11"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","stringValue":"2021-01-31"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","stringValue":"2020-10-01"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"limit_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","stringValue":"2020-09-30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"unitPrice_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_limit","stringValue":"2020-10-3"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_limit","stringValue":"2020-10-5"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_limit","stringValue":"2020-10-3"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_limit","stringValue":"2020-10-5"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_owner","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_amount","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"owned_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_amount","intValue":"400000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_amount","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_amount","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_assetId","stringValue":"GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_assetId","stringValue":"9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_assetId","stringValue":"3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_assetId","stringValue":"fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_assetId","stringValue":"Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_assetId","stringValue":"AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_assetId","stringValue":"DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_assetId","stringValue":"5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_assetId","stringValue":"6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_assetId","stringValue":"BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_unitPrice","intValue":"300"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_unitPrice","intValue":"30"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_unitPrice","intValue":"300"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_unitPrice","intValue":"20"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_Qysv1EeAG3svSgY4rXeXYVd5UDWLijge5GTSMJBZWAE","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_fnWceyvSknkwSvwg3a8viP4BbqZbJ9Xw4bKAuXfgpCf","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_kq1zuYsA6epnS1KeduHLUYVfShfMdjzS88xYutzWwRR_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_3ZwqiyJ71v2RL9ynFfhbhrL6exVvpBXq4tMZsM8BMjS2","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_5WUifJaLLAQwmZdBujmsDRRjd4j75PTqAPFNex3cD1BE","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_6pooGSU35S9beXySXnfB2Pd8graz6JRvZr6pk9tFRkVX","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_9QbcTW1TnEG9UtMXj7Qn6QGonY2sbQnDuhADJHRUfYkR","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_AeRfbghRJkE9De7wpBZBSSunmgrZ1WXAqzp6HEW3thes","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_BCJ5nmSeoT7o7PGbqPXeFGLmTbrbhGvdYGqFSTGPLQak","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_DevmCm3b6ciwmcoGtf7amdsbobmSjEQFZdsbS7No6ye4","intValue":"100000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"asset_total_amount_GHTzwH5nGskQJc6LH3Z9q2rE5dKA1UkhW44ZToKcTU6J","intValue":"100000000"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_29i7ZQAhzWzMV8Dfjqt1jyp8y3GHDBFnV4qWhqLmoZvy_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_2metSrd6Gn7VDVB61LF7DkZfxP3sx7Ag9Evx9JomcdTb_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_5ypDJF3LJAYdHBDEQLbmKcu9NzcumLHL3QZpW3DkuHJ4_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_7nZycAMeNvuiivEJdD1X8U6YF62P4BJb8TNS9QkSMtDS_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_93pNpaap3RT9bVGjGPkFHmJtyXphiUMY68VB5WCEif9G_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_AT3LBUYgVcf7SjNLJLXRsTvgw9Lb94wupN9YSkge3Axy_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_Bk5dKUfzPRCkY4ZMN3rG5xaSACueB3XvKoM5KQTJN1qQ_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_CPNhFYsDBJs8a4KXtGCCu7uGc45QeYNxwkFCGMoqeifW_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_EHuZ1jhXoXeYNY244PC5pzh2fgpDJ1oSoSntMr4yWvGW_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_ExF6Be3WrUyW4aeS4qBnfcH2aEDQXyScDY8u3cG87M8n_description","stringValue":"みんな電力公式"}},{"address":"AVNR0DAPNgBsCKRIvPT9wVRvDtiQBUHm8sU=","entry":{"key":"listed_GF8HGGqPLDfAjZvkLGhamioZouV6uH6vS92mZv1zA8hu_description","stringValue":"みんな電力公式"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"dappAddress","stringValue":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"masterAddress","stringValue":"3MSvD3m1R8Z3v8SAztrt1afp28vRdsMwxAu"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"asset_total_amount","intValue":"100000"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MgvX2f2ExVwTMkAk6dua8yE2iRmuBV4heT","stringValue":"{\"name\":\"ママママママママっまm\",\"description\":\"retail user\"}"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MktJgV2eTmcCqtyQaeqiiHkQ1eY3EH5Tdb","stringValue":"{\"name\":\"ママママママママっまm\",\"description\":\"retail user\"}"}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MRiqDCpFntSEud3Co8bdQygjSwB515zyS5_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MSvD3m1R8Z3v8SAztrt1afp28vRdsMwxAu_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MUJS7P4W3XyP2pnAJUGqkstSAiU4Ac2YdA_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MY34vVDzBnYxE34Ug4K1Y1GyRyVSgcfnpC_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MZyZAgAJmXmJs5gDihnMvZ7HCLxe6zVVpU_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MfF8z9y9nUUuHTeKiGFGoWXnUrRPbEcNiD_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MgvX2f2ExVwTMkAk6dua8yE2iRmuBV4heT_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3Mh5b5UttYteWjd5Mku43kajZFKX9z5WNxZ_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MjBN2kiRB6JmoEVEC42ZNMX9ibx5iZ9Mih_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MkT3qvGwdLrSs2Cfx3E29ffaM5GYrEZegz_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MktJgV2eTmcCqtyQaeqiiHkQ1eY3EH5Tdb_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3Mm9VfS5424Vn4oNKv1DSh7Htk6FhQReEuP_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3MmNtj9n49UgGapeh1Sg8Nd8jfQGDbqRTkx_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3P35F9e1QdcHkBMbYtovuMUmsxxCqo9DF1d_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PLXmyBua1pAH4y3aHjMqJrcJEcyrWMP1EB_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PMoTnMU6U4hx8km23iZJ6Akis6JKhcxhUn_active","boolValue":true}},{"address":"AVPewZB4PhL4dXSM6B1zWwYdeqFAtf/yW7I=","entry":{"key":"3PNVubsGCrnMHLXvg1gYidcP3G7HUC5fAuZ_active","boolValue":true}}]`) env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return nil - }, heightFunc: func() rideInt { return 451323 }, @@ -5661,9 +5492,6 @@ func TestRecipientAddressToString(t *testing.T) { } env := &MockRideEnvironment{ - actionsFunc: func() []proto.ScriptAction { - return nil - }, schemeFunc: func() byte { return proto.TestNetScheme }, diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index c950ca2f0..eb2e44b04 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -22,7 +22,7 @@ type esFunction struct { } type evaluationScope struct { - env RideEnvironment + env Environment constants map[string]esConstant cs [][]esValue system map[string]rideFunction @@ -115,7 +115,7 @@ func (s *evaluationScope) userFunction(id string) (*FunctionDeclarationNode, int return nil, 0, errors.Errorf("user function '%s' is not found", id) } -func newEvaluationScope(v int, env RideEnvironment) (evaluationScope, error) { +func newEvaluationScope(v int, env Environment) (evaluationScope, error) { constants, err := selectConstantNames(v) if err != nil { return evaluationScope{}, err @@ -210,7 +210,7 @@ type treeEvaluator struct { //cost int f Node s evaluationScope - env RideEnvironment + env Environment } func (e *treeEvaluator) evaluate() (RideResult, error) { @@ -434,7 +434,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { } } -func treeVerifierEvaluator(env RideEnvironment, tree *Tree) (*treeEvaluator, error) { +func treeVerifierEvaluator(env Environment, tree *Tree) (*treeEvaluator, error) { s, err := newEvaluationScope(tree.LibVersion, env) if err != nil { return nil, errors.Wrap(err, "failed to create scope") @@ -469,7 +469,7 @@ func treeVerifierEvaluator(env RideEnvironment, tree *Tree) (*treeEvaluator, err }, nil } -func treeFunctionEvaluatorForInvokeDAppFromDApp(env RideEnvironment, tree *Tree, name string, args []rideType) (*treeEvaluator, error) { +func treeFunctionEvaluatorForInvokeDAppFromDApp(env Environment, tree *Tree, name string, args []rideType) (*treeEvaluator, error) { s, err := newEvaluationScope(tree.LibVersion, env) if err != nil { return nil, errors.Wrap(err, "failed to create scope") @@ -503,7 +503,7 @@ func treeFunctionEvaluatorForInvokeDAppFromDApp(env RideEnvironment, tree *Tree, return nil, errors.Errorf("function '%s' not found", name) } -func treeFunctionEvaluator(env RideEnvironment, tree *Tree, name string, args proto.Arguments) (*treeEvaluator, error) { +func treeFunctionEvaluator(env Environment, tree *Tree, name string, args proto.Arguments) (*treeEvaluator, error) { s, err := newEvaluationScope(tree.LibVersion, env) if err != nil { return nil, errors.Wrap(err, "failed to create scope") diff --git a/pkg/ride/tuples.go b/pkg/ride/tuples.go index 5881bdf62..b0da3ad7e 100644 --- a/pkg/ride/tuples.go +++ b/pkg/ride/tuples.go @@ -14,7 +14,7 @@ type tuple2 struct { el2 rideType } -func newTuple2(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple2(_ Environment, args ...rideType) (rideType, error) { if len(args) != 2 { return nil, errors.New("invalid number of arguments") } @@ -63,7 +63,7 @@ type tuple3 struct { el3 rideType } -func newTuple3(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple3(_ Environment, args ...rideType) (rideType, error) { if len(args) != 3 { return nil, errors.New("invalid number of arguments") } @@ -116,7 +116,7 @@ type tuple4 struct { el4 rideType } -func newTuple4(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple4(_ Environment, args ...rideType) (rideType, error) { if len(args) != 4 { return nil, errors.New("invalid number of arguments") } @@ -173,7 +173,7 @@ type tuple5 struct { el5 rideType } -func newTuple5(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple5(_ Environment, args ...rideType) (rideType, error) { if len(args) != 5 { return nil, errors.New("invalid number of arguments") } @@ -234,7 +234,7 @@ type tuple6 struct { el6 rideType } -func newTuple6(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple6(_ Environment, args ...rideType) (rideType, error) { if len(args) != 6 { return nil, errors.New("invalid number of arguments") } @@ -299,7 +299,7 @@ type tuple7 struct { el7 rideType } -func newTuple7(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple7(_ Environment, args ...rideType) (rideType, error) { if len(args) != 7 { return nil, errors.New("invalid number of arguments") } @@ -368,7 +368,7 @@ type tuple8 struct { el8 rideType } -func newTuple8(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple8(_ Environment, args ...rideType) (rideType, error) { if len(args) != 8 { return nil, errors.New("invalid number of arguments") } @@ -441,7 +441,7 @@ type tuple9 struct { el9 rideType } -func newTuple9(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple9(_ Environment, args ...rideType) (rideType, error) { if len(args) != 9 { return nil, errors.New("invalid number of arguments") } @@ -518,7 +518,7 @@ type tuple10 struct { el10 rideType } -func newTuple10(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple10(_ Environment, args ...rideType) (rideType, error) { if len(args) != 10 { return nil, errors.New("invalid number of arguments") } @@ -599,7 +599,7 @@ type tuple11 struct { el11 rideType } -func newTuple11(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple11(_ Environment, args ...rideType) (rideType, error) { if len(args) != 11 { return nil, errors.New("invalid number of arguments") } @@ -684,7 +684,7 @@ type tuple12 struct { el12 rideType } -func newTuple12(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple12(_ Environment, args ...rideType) (rideType, error) { if len(args) != 12 { return nil, errors.New("invalid number of arguments") } @@ -773,7 +773,7 @@ type tuple13 struct { el13 rideType } -func newTuple13(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple13(_ Environment, args ...rideType) (rideType, error) { if len(args) != 13 { return nil, errors.New("invalid number of arguments") } @@ -866,7 +866,7 @@ type tuple14 struct { el14 rideType } -func newTuple14(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple14(_ Environment, args ...rideType) (rideType, error) { if len(args) != 14 { return nil, errors.New("invalid number of arguments") } @@ -963,7 +963,7 @@ type tuple15 struct { el15 rideType } -func newTuple15(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple15(_ Environment, args ...rideType) (rideType, error) { if len(args) != 15 { return nil, errors.New("invalid number of arguments") } @@ -1064,7 +1064,7 @@ type tuple16 struct { el16 rideType } -func newTuple16(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple16(_ Environment, args ...rideType) (rideType, error) { if len(args) != 16 { return nil, errors.New("invalid number of arguments") } @@ -1169,7 +1169,7 @@ type tuple17 struct { el17 rideType } -func newTuple17(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple17(_ Environment, args ...rideType) (rideType, error) { if len(args) != 17 { return nil, errors.New("invalid number of arguments") } @@ -1278,7 +1278,7 @@ type tuple18 struct { el18 rideType } -func newTuple18(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple18(_ Environment, args ...rideType) (rideType, error) { if len(args) != 18 { return nil, errors.New("invalid number of arguments") } @@ -1391,7 +1391,7 @@ type tuple19 struct { el19 rideType } -func newTuple19(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple19(_ Environment, args ...rideType) (rideType, error) { if len(args) != 19 { return nil, errors.New("invalid number of arguments") } @@ -1508,7 +1508,7 @@ type tuple20 struct { el20 rideType } -func newTuple20(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple20(_ Environment, args ...rideType) (rideType, error) { if len(args) != 20 { return nil, errors.New("invalid number of arguments") } @@ -1629,7 +1629,7 @@ type tuple21 struct { el21 rideType } -func newTuple21(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple21(_ Environment, args ...rideType) (rideType, error) { if len(args) != 21 { return nil, errors.New("invalid number of arguments") } @@ -1754,7 +1754,7 @@ type tuple22 struct { el22 rideType } -func newTuple22(_ RideEnvironment, args ...rideType) (rideType, error) { +func newTuple22(_ Environment, args ...rideType) (rideType, error) { if len(args) != 22 { return nil, errors.New("invalid number of arguments") } diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index fd6cde6c5..61fd58a67 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -23,9 +23,6 @@ var _ types.SmartState = &MockSmartState{} // AddingBlockHeightFunc: func() (uint64, error) { // panic("mock out the AddingBlockHeight method") // }, -// ApplyToStateFunc: func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { -// panic("mock out the ApplyToState method") -// }, // BlockVRFFunc: func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { // panic("mock out the BlockVRF method") // }, @@ -38,7 +35,7 @@ var _ types.SmartState = &MockSmartState{} // IsNotFoundFunc: func(err error) bool { // panic("mock out the IsNotFound method") // }, -// NewestAccountBalanceFunc: func(account proto.Recipient, asset []byte) (uint64, error) { +// NewestAccountBalanceFunc: func(account proto.Recipient, assetID []byte) (uint64, error) { // panic("mock out the NewestAccountBalance method") // }, // NewestAddrByAliasFunc: func(alias proto.Alias) (proto.Address, error) { @@ -65,6 +62,9 @@ var _ types.SmartState = &MockSmartState{} // NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { // panic("mock out the NewestRecipientToAddress method") // }, +// NewestScriptByAssetFunc: func(asset proto.OptionalAsset) (proto.Script, error) { +// panic("mock out the NewestScriptByAsset method") +// }, // NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { // panic("mock out the NewestScriptPKByAddr method") // }, @@ -96,9 +96,6 @@ type MockSmartState struct { // AddingBlockHeightFunc mocks the AddingBlockHeight method. AddingBlockHeightFunc func() (uint64, error) - // ApplyToStateFunc mocks the ApplyToState method. - ApplyToStateFunc func(actions []proto.ScriptAction) ([]proto.ScriptAction, error) - // BlockVRFFunc mocks the BlockVRF method. BlockVRFFunc func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) @@ -112,7 +109,7 @@ type MockSmartState struct { IsNotFoundFunc func(err error) bool // NewestAccountBalanceFunc mocks the NewestAccountBalance method. - NewestAccountBalanceFunc func(account proto.Recipient, asset []byte) (uint64, error) + NewestAccountBalanceFunc func(account proto.Recipient, assetID []byte) (uint64, error) // NewestAddrByAliasFunc mocks the NewestAddrByAlias method. NewestAddrByAliasFunc func(alias proto.Alias) (proto.Address, error) @@ -138,6 +135,9 @@ type MockSmartState struct { // NewestRecipientToAddressFunc mocks the NewestRecipientToAddress method. NewestRecipientToAddressFunc func(recipient proto.Recipient) (*proto.Address, error) + // NewestScriptByAssetFunc mocks the NewestScriptByAsset method. + NewestScriptByAssetFunc func(asset proto.OptionalAsset) (proto.Script, error) + // NewestScriptPKByAddrFunc mocks the NewestScriptPKByAddr method. NewestScriptPKByAddrFunc func(addr proto.Address, filter bool) (crypto.PublicKey, error) @@ -164,11 +164,6 @@ type MockSmartState struct { // AddingBlockHeight holds details about calls to the AddingBlockHeight method. AddingBlockHeight []struct { } - // ApplyToState holds details about calls to the ApplyToState method. - ApplyToState []struct { - // Actions is the actions argument value. - Actions []proto.ScriptAction - } // BlockVRF holds details about calls to the BlockVRF method. BlockVRF []struct { // BlockHeader is the blockHeader argument value. @@ -193,8 +188,8 @@ type MockSmartState struct { NewestAccountBalance []struct { // Account is the account argument value. Account proto.Recipient - // Asset is the asset argument value. - Asset []byte + // AssetID is the assetID argument value. + AssetID []byte } // NewestAddrByAlias holds details about calls to the NewestAddrByAlias method. NewestAddrByAlias []struct { @@ -238,6 +233,11 @@ type MockSmartState struct { // Recipient is the recipient argument value. Recipient proto.Recipient } + // NewestScriptByAsset holds details about calls to the NewestScriptByAsset method. + NewestScriptByAsset []struct { + // Asset is the asset argument value. + Asset proto.OptionalAsset + } // NewestScriptPKByAddr holds details about calls to the NewestScriptPKByAddr method. NewestScriptPKByAddr []struct { // Addr is the addr argument value. @@ -285,7 +285,6 @@ type MockSmartState struct { } } lockAddingBlockHeight sync.RWMutex - lockApplyToState sync.RWMutex lockBlockVRF sync.RWMutex lockEstimatorVersion sync.RWMutex lockGetByteTree sync.RWMutex @@ -299,6 +298,7 @@ type MockSmartState struct { lockNewestHeaderByHeight sync.RWMutex lockNewestLeasingInfo sync.RWMutex lockNewestRecipientToAddress sync.RWMutex + lockNewestScriptByAsset sync.RWMutex lockNewestScriptPKByAddr sync.RWMutex lockNewestTransactionByID sync.RWMutex lockNewestTransactionHeightByID sync.RWMutex @@ -334,37 +334,6 @@ func (mock *MockSmartState) AddingBlockHeightCalls() []struct { return calls } -// ApplyToState calls ApplyToStateFunc. -func (mock *MockSmartState) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - if mock.ApplyToStateFunc == nil { - panic("MockSmartState.ApplyToStateFunc: method is nil but SmartState.ApplyToState was just called") - } - callInfo := struct { - Actions []proto.ScriptAction - }{ - Actions: actions, - } - mock.lockApplyToState.Lock() - mock.calls.ApplyToState = append(mock.calls.ApplyToState, callInfo) - mock.lockApplyToState.Unlock() - return mock.ApplyToStateFunc(actions) -} - -// ApplyToStateCalls gets all the calls that were made to ApplyToState. -// Check the length with: -// len(mockedSmartState.ApplyToStateCalls()) -func (mock *MockSmartState) ApplyToStateCalls() []struct { - Actions []proto.ScriptAction -} { - var calls []struct { - Actions []proto.ScriptAction - } - mock.lockApplyToState.RLock() - calls = mock.calls.ApplyToState - mock.lockApplyToState.RUnlock() - return calls -} - // BlockVRF calls BlockVRFFunc. func (mock *MockSmartState) BlockVRF(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { if mock.BlockVRFFunc == nil { @@ -489,21 +458,21 @@ func (mock *MockSmartState) IsNotFoundCalls() []struct { } // NewestAccountBalance calls NewestAccountBalanceFunc. -func (mock *MockSmartState) NewestAccountBalance(account proto.Recipient, asset []byte) (uint64, error) { +func (mock *MockSmartState) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { if mock.NewestAccountBalanceFunc == nil { panic("MockSmartState.NewestAccountBalanceFunc: method is nil but SmartState.NewestAccountBalance was just called") } callInfo := struct { Account proto.Recipient - Asset []byte + AssetID []byte }{ Account: account, - Asset: asset, + AssetID: assetID, } mock.lockNewestAccountBalance.Lock() mock.calls.NewestAccountBalance = append(mock.calls.NewestAccountBalance, callInfo) mock.lockNewestAccountBalance.Unlock() - return mock.NewestAccountBalanceFunc(account, asset) + return mock.NewestAccountBalanceFunc(account, assetID) } // NewestAccountBalanceCalls gets all the calls that were made to NewestAccountBalance. @@ -511,11 +480,11 @@ func (mock *MockSmartState) NewestAccountBalance(account proto.Recipient, asset // len(mockedSmartState.NewestAccountBalanceCalls()) func (mock *MockSmartState) NewestAccountBalanceCalls() []struct { Account proto.Recipient - Asset []byte + AssetID []byte } { var calls []struct { Account proto.Recipient - Asset []byte + AssetID []byte } mock.lockNewestAccountBalance.RLock() calls = mock.calls.NewestAccountBalance @@ -775,6 +744,37 @@ func (mock *MockSmartState) NewestRecipientToAddressCalls() []struct { return calls } +// NewestScriptByAsset calls NewestScriptByAssetFunc. +func (mock *MockSmartState) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) { + if mock.NewestScriptByAssetFunc == nil { + panic("MockSmartState.NewestScriptByAssetFunc: method is nil but SmartState.NewestScriptByAsset was just called") + } + callInfo := struct { + Asset proto.OptionalAsset + }{ + Asset: asset, + } + mock.lockNewestScriptByAsset.Lock() + mock.calls.NewestScriptByAsset = append(mock.calls.NewestScriptByAsset, callInfo) + mock.lockNewestScriptByAsset.Unlock() + return mock.NewestScriptByAssetFunc(asset) +} + +// NewestScriptByAssetCalls gets all the calls that were made to NewestScriptByAsset. +// Check the length with: +// len(mockedSmartState.NewestScriptByAssetCalls()) +func (mock *MockSmartState) NewestScriptByAssetCalls() []struct { + Asset proto.OptionalAsset +} { + var calls []struct { + Asset proto.OptionalAsset + } + mock.lockNewestScriptByAsset.RLock() + calls = mock.calls.NewestScriptByAsset + mock.lockNewestScriptByAsset.RUnlock() + return calls +} + // NewestScriptPKByAddr calls NewestScriptPKByAddrFunc. func (mock *MockSmartState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { if mock.NewestScriptPKByAddrFunc == nil { diff --git a/pkg/ride/vm.go b/pkg/ride/vm.go index 1cf82c282..70bfb81a6 100644 --- a/pkg/ride/vm.go +++ b/pkg/ride/vm.go @@ -27,7 +27,7 @@ func newFunctionFrame(pos int, args []rideType) frame { } type vm struct { - env RideEnvironment + env Environment code []byte ip int constants []rideType diff --git a/pkg/ride/vm_test.go b/pkg/ride/vm_test.go index 8ffd6ba27..fa6ff54ac 100644 --- a/pkg/ride/vm_test.go +++ b/pkg/ride/vm_test.go @@ -34,7 +34,7 @@ func TestExecution(t *testing.T) { for _, test := range []struct { comment string source string - env RideEnvironment + env Environment res bool }{ {`V1: true`, "AQa3b8tH", nil, true}, @@ -218,7 +218,7 @@ func TestFunctions(t *testing.T) { name string text string script string - env RideEnvironment + env Environment result bool error bool }{ diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index bba0be4ff..aa1c53082 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -126,7 +126,7 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, lastBlockIn return nil } -func (a *scriptCaller) callAssetScriptCommon(env *ride.Environment, assetID crypto.Digest, lastBlockInfo *proto.BlockInfo, initialisation bool, acceptFailed bool) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, assetID crypto.Digest, lastBlockInfo *proto.BlockInfo, initialisation bool, acceptFailed bool) (ride.RideResult, error) { tree, err := a.stor.scriptsStorage.newestScriptByAsset(assetID, !initialisation) if err != nil { return nil, err @@ -195,6 +195,7 @@ func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWit } env.SetThisFromAddress(scriptAddress) env.SetLastBlock(lastBlockInfo) + env.SetTimestamp(tx.Timestamp) err = env.SetTransaction(tx) if err != nil { return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) @@ -204,6 +205,15 @@ func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWit return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) } env.ChooseSizeCheck(tree.LibVersion) + + // Since V5 we have to create environment with wrapped state to which we put attached payments + if tree.LibVersion >= 5 { + env, err = ride.NewEnvironmentWithWrappedState(env, tx.Payments, tx.SenderPK) + if err != nil { + return false, nil, errors.Wrapf(err, "failed to create RIDE environment with wrapped state") + } + } + r, err := ride.CallFunction(env, tree, tx.FunctionCall.Name, tx.FunctionCall.Arguments) if err != nil { return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) diff --git a/pkg/state/state.go b/pkg/state/state.go index 67cac215f..1818a4466 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -468,10 +468,6 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc return state, nil } -func (s *stateManager) ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) { - return nil, nil -} - func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, error) { if recipient.Address != nil { key := accountScriptKey{*recipient.Address} @@ -496,6 +492,11 @@ func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, err return nil, errors.Errorf("address and alias from recipient are nil") } +func (s *stateManager) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) { + return s.stor.scriptsStorage.newestScriptBytesByAsset(asset.ID, false) + +} + func (s *stateManager) Mutex() *lock.RwMutex { return lock.NewRwMutex(s.mu) } @@ -859,12 +860,26 @@ func (s *stateManager) NewestFullWavesBalance(account proto.Recipient) (*proto.F }, nil } +func isWaves(assetID []byte) bool { + wavesAsset := crypto.Digest{} + if len(wavesAsset) != len(assetID) { + return false + } + for i := range assetID { + if assetID[i] != wavesAsset[i] { + return false + } + } + return true +} + func (s *stateManager) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { addr, err := s.NewestRecipientToAddress(account) if err != nil { return 0, wrapErr(RetrievalError, err) } - if assetID == nil { + + if assetID == nil || isWaves(assetID) { profile, err := s.newestWavesBalanceProfile(*addr) if err != nil { return 0, wrapErr(RetrievalError, err) diff --git a/pkg/types/types.go b/pkg/types/types.go index ba0d4ed02..52c9f2dba 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -54,11 +54,11 @@ type SmartState interface { NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) + NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) // NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) - ApplyToState(actions []proto.ScriptAction) ([]proto.ScriptAction, error) EstimatorVersion() (int, error) IsNotFound(err error) bool } From 857e94588926ade8ba2fd828910d08d38084643a Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 4 Mar 2021 14:37:45 +0300 Subject: [PATCH 18/52] Merge master to version 0.9 (#432) * Costs of RIDE functions transactionHeightByID and blockInfoByHeight reduced for version 4 of standard library (#406) * Fixed empty senderPublicKey field while asset scritp execution. Fixed an issue then half empty TransferScriptAction produced on invalid asset. (#407) * Fixed calculation of size dependant part of fee of protobuf version of DataTransaction (#409) * RIDE function takeString works with string as UTF-16 string (#418) * Switchable bloom filter. (#424) * Switchable bloom filter. * Fix tests. * Proofs validation added to protobuf and json unmarshaling (#429) Co-authored-by: Frozen --- cmd/node/node.go | 5 + cmd/rollback/main.go | 30 +++-- pkg/keyvalue/bloom_filter.go | 38 ++++-- pkg/keyvalue/bloom_filter_stub.go | 29 +++++ pkg/keyvalue/bloom_filter_test.go | 2 +- pkg/keyvalue/leveldb.go | 4 +- pkg/keyvalue/leveldb_test.go | 2 +- pkg/proto/protobuf_converters.go | 4 + pkg/proto/scripting.go | 12 +- pkg/proto/transactions_with_proofs.go | 12 ++ pkg/proto/types.go | 22 +++- pkg/proto/types_test.go | 26 ++++ pkg/ride/converters.go | 19 +-- pkg/ride/environment.go | 3 - pkg/ride/functions_strings.go | 29 +++-- pkg/ride/functions_strings_test.go | 1 + pkg/ride/generate/main.go | 2 + pkg/ride/tree_evaluation_test.go | 175 +++++++++++++++++++++++--- pkg/state/fee_validation.go | 10 +- pkg/state/invoke_applier.go | 2 +- 20 files changed, 357 insertions(+), 70 deletions(-) create mode 100644 pkg/keyvalue/bloom_filter_stub.go diff --git a/cmd/node/node.go b/cmd/node/node.go index c3e452c0f..7f7e013da 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -65,6 +65,7 @@ var ( bindAddress = flag.String("bind-address", "", "Bind address for incoming connections. If empty, will be same as declared address") disableOutgoingConnections = flag.Bool("no-connections", false, "Disable outgoing network connections to peers. Default value is false.") minerVoteFeatures = flag.String("vote", "", "Miner vote features") + bloomFilter = flag.Bool("bloom", true, "Enable/Disable bloom filter. Less memory usage, but decrease performance. Usage: -bloom=false") reward = flag.String("reward", "", "Miner reward: for example 600000000") outdatePeriod = flag.String("outdate", "4h", "Interval after last block then generation is allowed. Example 1d4h30m") walletPath = flag.String("wallet-path", "", "Path to wallet, or ~/.waves by default.") @@ -118,6 +119,7 @@ func debugCommandLineParameters() { zap.S().Debugf("wallet-password: %s", *walletPassword) zap.S().Debugf("limit-connections: %s", *limitConnectionsS) zap.S().Debugf("profiler: %v", *profiler) + zap.S().Debugf("bloom: %v", *bloomFilter) } func main() { @@ -246,6 +248,9 @@ func main() { params.ProvideExtendedApi = *serveExtendedApi params.BuildStateHashes = *buildStateHashes params.Time = ntptm + if !*bloomFilter { + params.DbParams.BloomFilterParams.Disable = true + } st, err := state.NewState(path, params, cfg) if err != nil { zap.S().Error(err) diff --git a/cmd/rollback/main.go b/cmd/rollback/main.go index f05e8256e..7bafdaf1a 100644 --- a/cmd/rollback/main.go +++ b/cmd/rollback/main.go @@ -10,10 +10,12 @@ import ( ) var ( - logLevel = flag.String("log-level", "INFO", "Logging level. Supported levels: DEBUG, INFO, WARN, ERROR, FATAL. Default logging level INFO.") - statePath = flag.String("state-path", "", "Path to node's state directory") - blockchainType = flag.String("blockchain-type", "mainnet", "Blockchain type: mainnet/testnet/stagenet") - height = flag.Uint64("height", 0, "Height to rollback") + logLevel = flag.String("log-level", "INFO", "Logging level. Supported levels: DEBUG, INFO, WARN, ERROR, FATAL. Default logging level INFO.") + statePath = flag.String("state-path", "", "Path to node's state directory") + blockchainType = flag.String("blockchain-type", "mainnet", "Blockchain type: mainnet/testnet/stagenet") + height = flag.Uint64("height", 0, "Height to rollback") + buildExtendedApi = flag.Bool("build-extended-api", false, "Builds extended API. Note that state must be reimported in case it wasn't imported with similar flag set") + buildStateHashes = flag.Bool("build-state-hashes", false, "Calculate and store state hashes for each block height.") ) func main() { @@ -31,31 +33,39 @@ func main() { return } params := state.DefaultStateParams() - state, err := state.NewState(*statePath, params, cfg) + params.BuildStateHashes = *buildStateHashes + params.StoreExtendedApiData = *buildExtendedApi + s, err := state.NewState(*statePath, params, cfg) if err != nil { zap.S().Error(err) return } + defer func() { + err = s.Close() + if err != nil { + zap.S().Errorf("Failed to close state: %v", err) + } + }() - curHeight, err := state.Height() + curHeight, err := s.Height() if err != nil { zap.S().Error(err) return } - zap.S().Infof("current height: %d", curHeight) + zap.S().Infof("Current height: %d", curHeight) - err = state.RollbackToHeight(*height) + err = s.RollbackToHeight(*height) if err != nil { zap.S().Error(err) return } - curHeight, err = state.Height() + curHeight, err = s.Height() if err != nil { zap.S().Error(err) return } - zap.S().Infof("current height: %d", curHeight) + zap.S().Infof("Current height: %d", curHeight) } diff --git a/pkg/keyvalue/bloom_filter.go b/pkg/keyvalue/bloom_filter.go index 8f905519d..ca5e48cad 100644 --- a/pkg/keyvalue/bloom_filter.go +++ b/pkg/keyvalue/bloom_filter.go @@ -14,6 +14,13 @@ import ( "go.uber.org/zap" ) +type BloomFilter interface { + notInTheSet(data []byte) (bool, error) + add(data []byte) error + Params() BloomFilterParams + io.WriterTo +} + type BloomFilterParams struct { // N is how many items will be added to the filter. N int @@ -21,6 +28,8 @@ type BloomFilterParams struct { FalsePositiveProbability float64 // Bloom store. Store store + // Disable bloom filter. + Disable bool } func NewBloomFilterParams(N int, FalsePositiveProbability float64, store store) BloomFilterParams { @@ -40,11 +49,18 @@ func (bf *bloomFilter) WriteTo(w io.Writer) (n int64, err error) { return bf.filter.WriteTo(w) } +func (bf bloomFilter) Params() BloomFilterParams { + return bf.params +} + func (bf *bloomFilter) ReadFrom(r io.Reader) (n int64, err error) { return bf.filter.ReadFrom(r) } -func newBloomFilter(params BloomFilterParams) (*bloomFilter, error) { +func newBloomFilter(params BloomFilterParams) (BloomFilter, error) { + if params.Disable { + return NewBloomFilterStub(params), nil + } bf, err := bloomfilter.NewOptimal(uint64(params.N), params.FalsePositiveProbability) if err != nil { return nil, err @@ -52,7 +68,10 @@ func newBloomFilter(params BloomFilterParams) (*bloomFilter, error) { return &bloomFilter{filter: bf, params: params}, nil } -func newBloomFilterFromStore(params BloomFilterParams) (*bloomFilter, error) { +func newBloomFilterFromStore(params BloomFilterParams) (BloomFilter, error) { + if params.Disable { + return NewBloomFilterStub(params), nil + } f, err := bloomfilter.NewOptimal(uint64(params.N), params.FalsePositiveProbability) if err != nil { return nil, err @@ -71,9 +90,12 @@ func newBloomFilterFromStore(params BloomFilterParams) (*bloomFilter, error) { return bf, nil } -func storeBloomFilter(a *bloomFilter) error { +func storeBloomFilter(a BloomFilter) error { debug.FreeOSMemory() - return a.params.Store.save(a.filter) + if a.Params().Store != nil { + return a.Params().Store.save(a) + } + return nil } func (bf *bloomFilter) add(data []byte) error { @@ -94,7 +116,7 @@ func (bf *bloomFilter) notInTheSet(data []byte) (bool, error) { } type store interface { - save(*bloomfilter.Filter) error + save(to io.WriterTo) error load() ([]byte, error) WithPath(string) } @@ -104,7 +126,7 @@ type NoOpStore struct { func (NoOpStore) WithPath(string) {} -func (a NoOpStore) save(*bloomfilter.Filter) error { +func (a NoOpStore) save(to io.WriterTo) error { return nil } @@ -124,7 +146,7 @@ func (a *storeImpl) tmpFileName() string { return a.path + "tmp" } -func (a *storeImpl) saveData(f *bloomfilter.Filter) error { +func (a *storeImpl) saveData(f io.WriterTo) error { file, err := os.OpenFile(a.tmpFileName(), os.O_RDWR|os.O_CREATE, 0644) if err != nil { return err @@ -160,7 +182,7 @@ func (a *storeImpl) saveData(f *bloomfilter.Filter) error { return nil } -func (a *storeImpl) save(f *bloomfilter.Filter) error { +func (a *storeImpl) save(f io.WriterTo) error { if err := a.saveData(f); err != nil { return err } diff --git a/pkg/keyvalue/bloom_filter_stub.go b/pkg/keyvalue/bloom_filter_stub.go new file mode 100644 index 000000000..bd349dc95 --- /dev/null +++ b/pkg/keyvalue/bloom_filter_stub.go @@ -0,0 +1,29 @@ +package keyvalue + +import "io" + +type bloomFilterStub struct { + params BloomFilterParams +} + +func NewBloomFilterStub(params BloomFilterParams) bloomFilterStub { + return bloomFilterStub{ + params: params, + } +} + +func (bloomFilterStub) notInTheSet([]byte) (bool, error) { + return false, nil +} + +func (a bloomFilterStub) Params() BloomFilterParams { + return a.params +} + +func (a bloomFilterStub) WriteTo(to io.Writer) (int64, error) { + return 0, nil +} + +func (a bloomFilterStub) add([]byte) error { + return nil +} diff --git a/pkg/keyvalue/bloom_filter_test.go b/pkg/keyvalue/bloom_filter_test.go index f511498bf..05276f076 100644 --- a/pkg/keyvalue/bloom_filter_test.go +++ b/pkg/keyvalue/bloom_filter_test.go @@ -18,7 +18,7 @@ const ( ) func TestBloomFilter(t *testing.T) { - filter, err := newBloomFilter(BloomFilterParams{n, falsePositiveProbability, nil}) + filter, err := newBloomFilter(BloomFilterParams{n, falsePositiveProbability, nil, false}) assert.NoError(t, err, "newBloomFilter() failed") for i := 0; i < n; i++ { data := make([]byte, 100) diff --git a/pkg/keyvalue/leveldb.go b/pkg/keyvalue/leveldb.go index 90506a48a..8348c2818 100644 --- a/pkg/keyvalue/leveldb.go +++ b/pkg/keyvalue/leveldb.go @@ -40,7 +40,7 @@ func (b *batch) Put(key, val []byte) { b.mu.Unlock() } -func (b *batch) addToFilter(filter *bloomFilter) error { +func (b *batch) addToFilter(filter BloomFilter) error { b.mu.Lock() for _, pair := range b.pairs { if !pair.deletion { @@ -90,7 +90,7 @@ func (b *batch) Reset() { type KeyVal struct { db *leveldb.DB - filter *bloomFilter + filter BloomFilter cache *freecache.Cache mu *sync.RWMutex } diff --git a/pkg/keyvalue/leveldb_test.go b/pkg/keyvalue/leveldb_test.go index 97616f8be..9e18fa9d5 100644 --- a/pkg/keyvalue/leveldb_test.go +++ b/pkg/keyvalue/leveldb_test.go @@ -19,7 +19,7 @@ func TestKeyVal(t *testing.T) { dbDir, err := ioutil.TempDir(os.TempDir(), "dbDir0") params := KeyValParams{ CacheParams: CacheParams{cacheSize}, - BloomFilterParams: BloomFilterParams{n, falsePositiveProbability, NoOpStore{}}, + BloomFilterParams: BloomFilterParams{n, falsePositiveProbability, NoOpStore{}, false}, WriteBuffer: writeBuffer, CompactionTableSize: sstableSize, CompactionTotalSize: compactionTotalSize, diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index 4fd7fa568..8df47b91e 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -267,6 +267,10 @@ func (c *ProtobufConverter) proofs(proofs [][]byte) *ProofsV1 { for _, proof := range proofs { r.Proofs = append(r.Proofs, proof) } + if err := r.Valid(); err != nil { + c.err = err + return nil + } return r } diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index c2833a2e0..eae9f1ac1 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -34,11 +34,10 @@ func (a *DataEntryScriptAction) ToProtobuf() *g.DataTransactionData_DataEntry { // TransferScriptAction is an action to emit transfer of asset. type TransferScriptAction struct { - Sender *crypto.PublicKey - Recipient Recipient - Amount int64 - Asset OptionalAsset - InvalidAsset bool + Sender *crypto.PublicKey + Recipient Recipient + Amount int64 + Asset OptionalAsset } func (a TransferScriptAction) scriptAction() {} @@ -463,9 +462,6 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr if ta.Amount < 0 { return errors.New("negative transfer amount") } - if ta.InvalidAsset { - return errors.New("invalid asset") - } if restrictions.DisableSelfTransfers { senderAddress := restrictions.ScriptAddress if ta.SenderPK() != nil { diff --git a/pkg/proto/transactions_with_proofs.go b/pkg/proto/transactions_with_proofs.go index 9dfc7bfd8..ed2d98ff1 100644 --- a/pkg/proto/transactions_with_proofs.go +++ b/pkg/proto/transactions_with_proofs.go @@ -11,6 +11,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/errs" g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "github.com/wavesplatform/gowaves/pkg/libs/serializer" + protobuf "google.golang.org/protobuf/proto" ) const ( @@ -3076,6 +3077,8 @@ func (tx *DataWithProofs) Validate() (Transaction, error) { if !validJVMLong(tx.Fee) { return tx, errors.New("fee is too big") } + //TODO: validate size of transaction by version: + // 1 -> binary size should be less than 150 * 1024; 2 -> proto payload size should be less than 165890 bytes return tx, nil } @@ -3331,6 +3334,15 @@ func (tx *DataWithProofs) ToProtobuf(scheme Scheme) (*g.Transaction, error) { return res, nil } +func (tx *DataWithProofs) ProtoPayload(scheme Scheme) ([]byte, error) { + proto, err := tx.ToProtobuf(scheme) + if err != nil { + return nil, err + } + data := proto.GetDataTransaction() + return protobuf.MarshalOptions{Deterministic: true}.Marshal(data) +} + func (tx *DataWithProofs) ToProtobufSigned(scheme Scheme) (*g.SignedTransaction, error) { unsigned, err := tx.ToProtobuf(scheme) if err != nil { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index a5dff32b4..efb7921c1 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -1552,6 +1552,9 @@ func (p *ProofsV1) UnmarshalJSON(value []byte) error { } p.Version = proofsVersion p.Proofs = tmp + if err := p.Valid(); err != nil { + return errors.Wrap(err, "failed to unmarshal ProofsV1 from JSON") + } return nil } @@ -1675,6 +1678,21 @@ func (p *ProofsV1) BinarySize() int { return proofsMinLen + pl } +func (p *ProofsV1) Valid() error { + if p.Version != proofsVersion { + return errors.Errorf("invalid proofs version %d", p.Version) + } + if c := len(p.Proofs); c > proofsMaxCount { + return errors.Errorf("invalid proofs count %d", c) + } + for i, proof := range p.Proofs { + if s := len(proof); s > proofMaxSize { + return errors.Errorf("proof #%d has invalid size %d", i, s) + } + } + return nil +} + // ValueType is an alias for byte that encodes the value type. type DataValueType byte @@ -3240,16 +3258,18 @@ type FullScriptTransfer struct { Asset OptionalAsset Recipient Recipient Sender Address + SenderPK crypto.PublicKey Timestamp uint64 ID *crypto.Digest } -func NewFullScriptTransfer(action *TransferScriptAction, sender Address, tx *InvokeScriptWithProofs) (*FullScriptTransfer, error) { +func NewFullScriptTransfer(action *TransferScriptAction, sender Address, senderPK crypto.PublicKey, tx *InvokeScriptWithProofs) (*FullScriptTransfer, error) { return &FullScriptTransfer{ Amount: uint64(action.Amount), Asset: action.Asset, Recipient: action.Recipient, Sender: sender, + SenderPK: senderPK, Timestamp: tx.Timestamp, ID: tx.ID, }, nil diff --git a/pkg/proto/types_test.go b/pkg/proto/types_test.go index fc29a3410..273fd287c 100644 --- a/pkg/proto/types_test.go +++ b/pkg/proto/types_test.go @@ -2,6 +2,7 @@ package proto import ( "bytes" + "crypto/rand" "encoding/base64" "encoding/json" "fmt" @@ -1107,6 +1108,31 @@ func TestProofsV1UnmarshalJSON(t *testing.T) { } } +func TestProofsV1_Valid(t *testing.T) { + smallProof := make([]byte, 32) + normProof := make([]byte, 64) + bigProof := make([]byte, 65) + _, err := rand.Read(smallProof) + require.NoError(t, err) + _, err = rand.Read(normProof) + require.NoError(t, err) + _, err = rand.Read(bigProof) + require.NoError(t, err) + p1 := NewProofs() + p1.Proofs = append(p1.Proofs, smallProof) + p1.Proofs = append(p1.Proofs, normProof) + p1.Proofs = append(p1.Proofs, bigProof) + err = p1.Valid() + assert.Error(t, err) + + p2 := NewProofs() + for i := 0; i < 9; i++ { + p2.Proofs = append(p2.Proofs, smallProof) + } + err = p2.Valid() + assert.Error(t, err) +} + func TestIntegerArgumentBinarySize(t *testing.T) { tests := []int64{12345, -9876543210, 1234567890, 0} for _, tc := range tests { diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index 610cb9440..18ebb3dd9 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -956,7 +956,7 @@ func scriptTransferToObject(tr *proto.FullScriptTransfer) rideObject { r["version"] = rideUnit{} r["id"] = rideBytes(tr.ID.Bytes()) r["sender"] = rideAddress(tr.Sender) - r["senderPublicKey"] = rideUnit{} + r["senderPublicKey"] = rideBytes(common.Dup(tr.SenderPK.Bytes())) r["recipient"] = rideRecipient(tr.Recipient) r["assetId"] = optionalAsset(tr.Asset) r["amount"] = rideInt(tr.Amount) @@ -1211,15 +1211,20 @@ func convertToAction(env Environment, obj rideType) (proto.ScriptAction, error) return nil, errors.Wrap(err, "failed to convert ScriptTransfer to ScriptAction") } asset, err := optionalAssetProperty(obj, "asset") - invalidAsset := false + // On asset ID conversion error we return empty action as in Scala + // See example on MainNet: transaction (https://wavesexplorer.com/tx/AUpiEr49Jo43Q9zXKkNN23rstiq87hguvhfQqV8ov9uQ) + // and script (https://wavesexplorer.com/tx/Bp1oieWHWpLz8vBFZui9tY1oDTAKUPTrBAGcwfRe9q5K) if err != nil { - invalidAsset = true + return &proto.TransferScriptAction{ + Recipient: recipient, + Amount: 0, + Asset: proto.OptionalAsset{Present: false}, + }, nil } return &proto.TransferScriptAction{ - Recipient: recipient, - Amount: int64(amount), - Asset: asset, - InvalidAsset: invalidAsset, + Recipient: recipient, + Amount: int64(amount), + Asset: asset, }, nil case "SponsorFee": id, err := digestProperty(obj, "assetId") diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index ca63d2086..55d09cdff 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -457,9 +457,6 @@ func (ws *WrappedState) validateTransferAction(otherActionsCount *int, res *prot if res.Amount < 0 { return errors.New("negative transfer amount") } - if res.InvalidAsset { - return errors.New("invalid asset") - } if restrictions.DisableSelfTransfers { senderAddress := restrictions.ScriptAddress if res.SenderPK() != nil { diff --git a/pkg/ride/functions_strings.go b/pkg/ride/functions_strings.go index c0473e7ea..c38f87220 100644 --- a/pkg/ride/functions_strings.go +++ b/pkg/ride/functions_strings.go @@ -3,6 +3,7 @@ package ride import ( "strconv" "strings" + "unicode/utf16" "unicode/utf8" "github.com/pkg/errors" @@ -307,14 +308,28 @@ func runesDrop(s string, n int) string { return res } -func runesTake(s string, n int) string { - out := make([]rune, n) - copy(out, []rune(s)[:n]) - return string(out) -} +// TODO: This is the correct implementation of takeString function that handles runes in UTF-8 string correct +//func runesTake(s string, n int) string { +// out := make([]rune, n) +// copy(out, []rune(s)[:n]) +// return string(out) +//} +// +//func takeRideString(s string, n int) rideString { +// l := utf8.RuneCountInString(s) +// t := n +// if t > l { +// t = l +// } +// if t < 0 { +// t = 0 +// } +// return rideString(runesTake(s, t)) +//} func takeRideString(s string, n int) rideString { - l := utf8.RuneCountInString(s) + b := utf16.Encode([]rune(s)) + l := len(b) t := n if t > l { t = l @@ -322,7 +337,7 @@ func takeRideString(s string, n int) rideString { if t < 0 { t = 0 } - return rideString(runesTake(s, t)) + return rideString(strings.ReplaceAll(string(utf16.Decode(b[:t])), "�", "?")) } func dropRideString(s string, n int) rideString { diff --git a/pkg/ride/functions_strings_test.go b/pkg/ride/functions_strings_test.go index bd196a045..df75ba07b 100644 --- a/pkg/ride/functions_strings_test.go +++ b/pkg/ride/functions_strings_test.go @@ -53,6 +53,7 @@ func TestTakeString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + {[]rideType{rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶🔶🔶\n\nCeli, child of the first light. One of the main characters of the story, she is the first to see the vision of Cloudscape and its inhabitants from the Earth's dimension after the great destruction.\n\nDragorion - avatars sung into being by Eneria to bring sleep to the people of Cloudscape. They speak in dreams as lullabies, symphonies, hymns, arias and melodies. ~Legendarium\n\n©️Art of Monztre\n"), rideInt(50)}, false, rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶?")}, } { r, err := takeString(nil, test.args...) if test.fail { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index e15cde301..9dad12ab4 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -387,7 +387,9 @@ func catalogueV4() map[string]int { m["800"] = 2700 // BLS12 m["801"] = 1650 // BN256 m["900"] = 70 + m["1001"] = 20 m["1004"] = 15 + m["1005"] = 5 m["1006"] = 60 m["1007"] = 10 m["1008"] = 10 diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 6d8438081..081d354d7 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -1197,9 +1197,9 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 1234, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: proto.OptionalAsset{}}, } expectedLeaseWrites := []*proto.LeaseScriptAction{ @@ -1560,8 +1560,8 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, } expectedDataEntryWrites := []*proto.DataEntryScriptAction{ @@ -1753,10 +1753,10 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 18, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 18, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, } smartState := smartStateDappFromDapp @@ -1941,9 +1941,9 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, } smartState := smartStateDappFromDapp @@ -2127,10 +2127,10 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}, InvalidAsset: false}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, } smartState := smartStateDappFromDapp @@ -2486,7 +2486,7 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Recipient: senderRecipient, Amount: 50000, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Recipient: senderRecipient, Amount: 50000, Asset: proto.OptionalAsset{}}, } smartState := smartStateDappFromDapp @@ -2644,7 +2644,7 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}, InvalidAsset: false}, + {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}}, } smartState := smartStateDappFromDapp @@ -2826,7 +2826,7 @@ func TestInvokeDAppFromDAppSmartAssetValidation(t *testing.T) { } expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: *assetCat, InvalidAsset: false}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 1, Asset: *assetCat}, } smartState := smartStateDappFromDapp @@ -5509,3 +5509,140 @@ func TestRecipientAddressToString(t *testing.T) { require.True(t, ok) assert.True(t, r.Result()) } + +func TestScriptPaymentPublicKey(t *testing.T) { + pk := crypto.MustPublicKeyFromBase58("7gYTeHxHZ2NRQdNpa6DHAxQY4K5LS6bezcsMQcUhYuo1") + addr := proto.MustAddressFromPublicKey(proto.MainNetScheme, pk) + asset, err := proto.NewOptionalAssetFromString("5F4PshPwzE8sQeesDPzjJN45CFVnAnqCUHJcmi7kZq22") + require.NoError(t, err) + rcp := proto.NewRecipientFromAddress(addr) + action := &proto.TransferScriptAction{ + Recipient: rcp, + Amount: 12345, + Asset: *asset, + } + id := crypto.MustDigestFromBase58("9vt45R9y63Xwcseat59BchUjfJGHSuN5LeTK6Pd6cFUM") + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &id, + ChainID: proto.MainNetScheme, + SenderPK: pk, + ScriptRecipient: rcp, + Payments: proto.ScriptPayments{}, + FeeAsset: proto.OptionalAsset{}, + Fee: 1300000, + Timestamp: 1599565088614, + } + + tr, _ := proto.NewFullScriptTransfer(action, addr, pk, tx) + env := &MockRideEnvironment{ + schemeFunc: func() byte { + return proto.MainNetScheme + }, + transactionFunc: func() rideObject { + return scriptTransferToObject(tr) + }, + checkMessageLengthFunc: v3check, + } + + code := "AQQAAAAGc2VuZGVyCQACWAAAAAEICQEAAAAUYWRkcmVzc0Zyb21QdWJsaWNLZXkAAAABCAUAAAACdHgAAAAPc2VuZGVyUHVibGljS2V5AAAABWJ5dGVzCQAAAAAAAAICAAAAIzNQNjFiNnRlMmZ2akw3YWdLSHFOY0NrcHV0Z1lzNjV4dzVSBQAAAAZzZW5kZXJlKXM0" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallVerifier(env, tree) + require.NoError(t, err) + r, ok := res.(ScriptResult) + require.True(t, ok) + require.True(t, r.Result()) +} + +func TestInvalidAssetInTransferScriptAction(t *testing.T) { + txID, err := crypto.NewDigestFromBase58("AUpiEr49Jo43Q9zXKkNN23rstiq87hguvhfQqV8ov9uQ") + require.NoError(t, err) + proofs := proto.NewProofs() + sender, err := crypto.NewPublicKeyFromBase58("Hjd6p3ArqjnQAsejFwu7JcQciVVx9RaQhtMfGBCAi76z") + require.NoError(t, err) + address, err := proto.NewAddressFromString("3P8FF73N7ZvvNJ34vnJ3h9Tfmh7oQCnRz8E") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(address) + arguments := proto.Arguments{} + call := proto.FunctionCall{ + Default: false, + Name: "swapRKMTToWAVES", + Arguments: arguments, + } + asset, err := proto.NewOptionalAssetFromString("2fCdmsn6maErwtLuzxoUrCBkh2vx5SvXtMKAJtN4YBgd") + require.NoError(t, err) + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{Amount: 1000, Asset: *asset}}, + FeeAsset: proto.OptionalAsset{}, + Fee: 500000, + Timestamp: 1609698441420, + } + env := &MockRideEnvironment{ + schemeFunc: func() byte { + return proto.MainNetScheme + }, + thisFunc: func() rideType { + return rideAddress(address) + }, + transactionFunc: func() rideObject { + obj, err := transactionToObject(proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + invocationFunc: func() rideObject { + obj, err := invocationToObject(3, proto.MainNetScheme, tx) + require.NoError(t, err) + return obj + }, + checkMessageLengthFunc: v3check, + } + + code := "AAIDAAAAAAAAABIIARIAEgASABIAEgASABIAEgAAAAAAAAAACAAAAAFpAQAAAA9zd2FwUktNVFRvV0FWRVMAAAAABAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAQAAAAGYXNzZXQxAQAAACAYpOmNLEFVo6RxR5F7mnPqDVa46IRz0pd5kzKLvhp6ygMJAQAAAAIhPQAAAAIIBQAAAANwbXQAAAAHYXNzZXRJZAUAAAAGYXNzZXQxCQAAAgAAAAECAAAAWkluY29ycmVjdCBhc3NldCBhdHRhY2hlZCwgcGxlYXNlIHNlbmQgMmZDZG1zbjZtYUVyd3RMdXp4b1VyQ0JraDJ2eDVTdlh0TUtBSnRONFlCZ2QgKFJLTVQpLgkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEFAAAAA25pbAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAABpAAAAAggFAAAAA3BtdAAAAAZhbW91bnQAAAAAAAAAJxABAAAABBOr2TMFAAAAA25pbAAAAAFpAQAAAAtXQVZFU1RvUktNVAAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50AwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkAAAIAAAABAgAAADFJbmNvcnJlY3QgYXNzZXQgYXR0YWNoZWQsIHBsZWFzZSBzZW5kIFdBVkVTIG9ubHkuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGgAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAnEAEAAAAgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEFAAAAA25pbAAAAAFpAQAAAA5zd2FwUktNVFRvVVNETgAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAIBik6Y0sQVWjpHFHkXuac+oNVrjohHPSl3mTMou+GnrKAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCAyZkNkbXNuNm1hRXJ3dEx1enhvVXJDQmtoMnZ4NVN2WHRNS0FKdE40WUJnZCAoUktNVCkuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGkAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAAgEAAAAgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEFAAAAA25pbAAAAAFpAQAAAA5zd2FwVVNETlRvUktNVAAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAILYmKcME9c5TkaQOS3UkL2SMUbH6369UKb1I0h0qsqrRAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCBERzJ4RmtQZER3S1VvQmt6R0FoUXRMcFNHemZYTGlDWVBFemVLSDJBZDI0cCAoVVNETikuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGgAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAAgEAAAAgGKTpjSxBVaOkcUeRe5pz6g1WuOiEc9KXeZMyi74aesoFAAAAA25pbAAAAAFpAQAAAA5zd2FwUktNVFRvVVNEVAAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAIBik6Y0sQVWjpHFHkXuac+oNVrjohHPSl3mTMou+GnrKAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCAyZkNkbXNuNm1hRXJ3dEx1enhvVXJDQmtoMnZ4NVN2WHRNS0FKdE40WUJnZCAoUktNVCkuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGkAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAAgEAAAAgHpQHE1J2oSWV/chhqIJfEH/fOk8pu/yaRj9a/TZPn5EFAAAAA25pbAAAAAFpAQAAAA5zd2FwVVNEVFRvUktNVAAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAIB6UBxNSdqEllf3IYaiCXxB/3zpPKbv8mkY/Wv02T5+RAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCAzNE45WWNFRVRMV245M3FZUTY0RXNQMXg4OXRTcnVKVTQ0UnJFTVNYWEVQSiAoVVNEVCkuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGgAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAAgEAAAAgGKTpjSxBVaOkcUeRe5pz6g1WuOiEc9KXeZMyi74aesoFAAAAA25pbAAAAAFpAQAAAA5zd2FwUktNVFRvTkdOTgAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAIBik6Y0sQVWjpHFHkXuac+oNVrjohHPSl3mTMou+GnrKAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCAyZkNkbXNuNm1hRXJ3dEx1enhvVXJDQmtoMnZ4NVN2WHRNS0FKdE40WUJnZCAoUktNVCkuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGgAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAyAEAAAAgQQI+NoHe5EsJ7o0J14wNrQAVGs8T/EKxVR7KU382s+sFAAAAA25pbAAAAAFpAQAAAA5zd2FwTkdOTlRvUktNVAAAAAAEAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAAZhc3NldDEBAAAAIEECPjaB3uRLCe6NCdeMDa0AFRrPE/xCsVUeylN/NrPrAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkBQAAAAZhc3NldDEJAAACAAAAAQIAAABaSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLCBwbGVhc2Ugc2VuZCA1Tm1WNVZBaGtxb3JtZHd2YVFqRTU0eVBFa053U1J0Y1h4aExrSmJWUXFrTiAoTkdOTikuCQEAAAAMU2NyaXB0UmVzdWx0AAAAAgkBAAAACFdyaXRlU2V0AAAAAQUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgkAAGkAAAACCAUAAAADcG10AAAABmFtb3VudAAAAAAAAAAAyAEAAAAgGKTpjSxBVaOkcUeRe5pz6g1WuOiEc9KXeZMyi74aesoFAAAAA25pbAAAAAEAAAACdHgBAAAABnZlcmlmeQAAAAAEAAAAByRtYXRjaDAFAAAAAnR4CQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAgFAAAAAnR4AAAAD3NlbmRlclB1YmxpY0tleW6t/SA=" + src, err := base64.StdEncoding.DecodeString(code) + require.NoError(t, err) + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + res, err := CallFunction(env, tree, "swapRKMTToWAVES", arguments) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedTransfers := []*proto.TransferScriptAction{ + { + Recipient: proto.NewRecipientFromAddress(proto.MustAddressFromString("3P8FF73N7ZvvNJ34vnJ3h9Tfmh7oQCnRz8E")), + Amount: 0, + Asset: proto.OptionalAsset{Present: false}, + }, + } + expectedResult := &proto.ScriptResult{ + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: expectedTransfers, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + ErrorMsg: proto.ScriptErrorMessage{}, + } + assert.Equal(t, expectedResult, sr) +} diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index 35f91f18b..f85f57eff 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -103,12 +103,18 @@ func minFeeInUnits(params *feeValidationParams, tx proto.Transaction) (uint64, e } scheme := params.settings.AddressSchemeCharacter var dtxBytes []byte - if smartAccountsActive { + switch { + case proto.IsProtobufTx(tx): + dtxBytes, err = dtx.ProtoPayload(scheme) + if err != nil { + return 0, err + } + case smartAccountsActive: dtxBytes, err = proto.MarshalTxBody(scheme, dtx) if err != nil { return 0, err } - } else { + default: dtxBytes, err = proto.MarshalTx(scheme, dtx) if err != nil { return 0, err diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 74fe294a5..0be60d151 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -347,7 +347,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in } isSmartAsset := ia.stor.scriptsStorage.newestIsSmartAsset(a.Asset.ID, !info.initialisation) if isSmartAsset { - fullTr, err := proto.NewFullScriptTransfer(a, senderAddress, tx) + fullTr, err := proto.NewFullScriptTransfer(a, senderAddress, info.scriptPK, tx) if err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to convert transfer to full script transfer") } From d6ab885f5e5d3f5bbd13ef95c795f40a7fd5bfd1 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 18 Mar 2021 11:01:13 +0300 Subject: [PATCH 19/52] Added fields origin address and PK (#436) * Added fields * Added todo --- pkg/ride/environment.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 55d09cdff..66307160c 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1018,6 +1018,10 @@ func NewEnvironmentWithWrappedState(env *EvaluationEnvironment, payments proto.S } recipient := proto.NewRecipientFromAddress(proto.Address(env.th.(rideAddress))) + env.inv["originalCaller"] = rideAddress(caller) + env.inv["originalCallerPublicKey"] = rideBytes(callerPK.Bytes()) + //TODO add test for these fields + st := newWrappedState(env) for _, payment := range payments { From 2875358174b0d6a7299a8a3b977c36023e711c68 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 22 Mar 2021 20:13:19 +0300 Subject: [PATCH 20/52] Ride tests for original caller (#439) * Added tests for new fields * Finished test, added check if recipient has only alias --- pkg/ride/functions_proto.go | 11 ++ pkg/ride/tree_evaluation_test.go | 233 +++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 7a1278958..ea6e0bb8f 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -34,6 +34,17 @@ func invoke(env Environment, args ...rideType) (rideType, error) { return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[0].instanceOf()) } + if recipient.Address == nil { + if recipient.Alias == nil { + return nil, errors.New("invoke: address and alias are nil") + } + addressFromAlias, err := env.state().NewestAddrByAlias(*recipient.Alias) + if err != nil { + return nil, errors.Errorf("invoke: failed to get address by alias, %v", err) + } + recipient = proto.NewRecipientFromAddress(addressFromAlias) + } + var fnName rideString switch fnN := args[1].(type) { case rideUnit: diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 081d354d7..910937dab 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -855,6 +855,12 @@ func smartStateDappFromDapp() types.SmartState { return nil, nil }, NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { + if recipient.Alias != nil { + if recipient.Alias.Alias == "alias" { + addr, err := proto.NewAddressFromString("3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV") + return &addr, err + } + } return recipient.Address, nil }, AddingBlockHeightFunc: func() (uint64, error) { @@ -868,6 +874,10 @@ func smartStateDappFromDapp() types.SmartState { if address.String() == "3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv" { return crypto.NewPublicKeyFromBase58("pmDSxpnULiroUAerTDFBajffTpqgwVJjtMipQq6DQM5") } + // original caller test + if address.String() == "3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV" { + return crypto.NewPublicKeyFromBase58("AQj4MhySztn4FB3PxXc1ZcHPknLmGFYEKuSBz2vXeJPY") + } // if address == addr { return crypto.NewPublicKeyFromBase58("JBjPD1xkTTcYUVhbLp1bLJLcjDKLT3c32RVk9Rue87ZD") @@ -885,6 +895,12 @@ func smartStateDappFromDapp() types.SmartState { balance := 0 return uint64(balance), nil }, + NewestAddrByAliasFunc: func(alias proto.Alias) (proto.Address, error) { + if alias.Alias == "alias" { + return proto.NewAddressFromString("3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV") + } + return proto.Address{}, errors.New("unexpected alias") + }, NewestFullWavesBalanceFunc: func(account proto.Recipient) (*proto.FullWavesBalance, error) { return &proto.FullWavesBalance{ @@ -2548,6 +2564,223 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { tearDownDappFromDapp() } +func TestInvokeDAppFromDAppOriginalCallerAndAlias(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let b1 = wavesBalance(this) + let ob1 = wavesBalance(Address(base58'$otherAcc')) + if b1 == b1 && ob1 == ob1 && i.caller == i.originalCaller && i.callerPublicKey == i.originalCallerPublicKey + then + let r = Invoke(Alias("alias"), "bar", [this.bytes, i.caller.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + let data = getIntegerValue(Address(base58'3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV'), "bar") + let b2 = wavesBalance(this) + let ob2 = wavesBalance(Address(base58'3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV')) + let ab = assetBalance(this, getBinaryValue(Address(base58'3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV'), "asset")) + if data == 1 + then + if ob1.regular+14 == ob2.regular && b1.regular == b2.regular+14 && ab == 1 + then + let l = Lease(Address(base58'3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV'), 23) + [ + IntegerEntry("key", 1), + Lease(Address(base58'3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV'), 13), + l, + LeaseCancel(l.calculateLeaseId()) + ] + else + throw("Balance check failed") + else + throw("Bad state") + else + throw("Bad returned value") + else + throw("Imposible") + }*/ + + /* script 2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector, o: ByteVector) = { + if i.caller.bytes == a && addressFromPublicKey(i.callerPublicKey).bytes == a && i.originalCaller.bytes == o && addressFromPublicKey(i.originalCallerPublicKey).bytes == o + then + let n = Issue("barAsset", "bar asset", 1, 0, false, unit, 0) + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit), BinaryEntry("asset", n.calculateAssetId()), n, ScriptTransfer(Address(a), 1, n.calculateAssetId())], 17) + else + throw("Bad caller") + } */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV") // new + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + inv["originalCaller"] = rideAddress(senderAddress) + inv["originalCallerPublicKey"] = rideBytes(sender.Bytes()) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQkEaFHOY5/wEUlgg1k/cPu/P+Gr9BUxy4DAwMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcJAAAAAAAAAggFAAAAAWkAAAAGY2FsbGVyCAUAAAABaQAAAA5vcmlnaW5hbENhbGxlcgcJAAAAAAAAAggFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CAUAAAABaQAAABdvcmlnaW5hbENhbGxlclB1YmxpY0tleQcEAAAAAXIJAAP8AAAABAkBAAAABUFsaWFzAAAAAQIAAAAFYWxpYXMCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwkABEwAAAACCAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVCQRoUc5jn/ARSWCDWT9w+78/4av0FTHLgIAAAADYmFyBAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVCQRoUc5jn/ARSWCDWT9w+78/4av0FTHLgQAAAACYWIJAAPwAAAAAgUAAAAEdGhpcwkBAAAAEUBleHRyTmF0aXZlKDEwNTIpAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVCQRoUc5jn/ARSWCDWT9w+78/4av0FTHLgIAAAAFYXNzZXQDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAAA4IBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAADgcJAAAAAAAAAgUAAAACYWIAAAAAAAAAAAEHBAAAAAFsCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQkEaFHOY5/wEUlgg1k/cPu/P+Gr9BUxy4AAAAAAAAAABcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQkABEwAAAACCQAERAAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQkEaFHOY5/wEUlgg1k/cPu/P+Gr9BUxy4AAAAAAAAAAA0JAARMAAAAAgUAAAABbAkABEwAAAACCQEAAAALTGVhc2VDYW5jZWwAAAABCQAEOQAAAAEFAAAAAWwFAAAAA25pbAkAAAIAAAABAgAAABRCYWxhbmNlIGNoZWNrIGZhaWxlZAkAAAIAAAABAgAAAAlCYWQgc3RhdGUJAAACAAAAAQIAAAASQmFkIHJldHVybmVkIHZhbHVlCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAA/J7gE" + secondScript = "AAIFAAAAAAAAAAgIAhIECgICAgAAAAAAAAABAAAAAWkBAAAAA2JhcgAAAAIAAAABYQAAAAFvAwMDAwkAAAAAAAACCAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzBQAAAAFhCQAAAAAAAAIICQEAAAAUYWRkcmVzc0Zyb21QdWJsaWNLZXkAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkAAAAFYnl0ZXMFAAAAAWEHCQAAAAAAAAIICAUAAAABaQAAAA5vcmlnaW5hbENhbGxlcgAAAAVieXRlcwUAAAABbwcJAAAAAAAAAggJAQAAABRhZGRyZXNzRnJvbVB1YmxpY0tleQAAAAEIBQAAAAFpAAAAF29yaWdpbmFsQ2FsbGVyUHVibGljS2V5AAAABWJ5dGVzBQAAAAFvBwQAAAABbgkABEMAAAAHAgAAAAhiYXJBc3NldAIAAAAJYmFyIGFzc2V0AAAAAAAAAAABAAAAAAAAAAAABwUAAAAEdW5pdAAAAAAAAAAAAAkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANiYXIAAAAAAAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAB0FkZHJlc3MAAAABBQAAAAFhAAAAAAAAAAADBQAAAAR1bml0CQAETAAAAAIJAQAAAAtCaW5hcnlFbnRyeQAAAAICAAAABWFzc2V0CQAEOAAAAAEFAAAAAW4JAARMAAAAAgUAAAABbgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEFAAAAAWEAAAAAAAAAAAEJAAQ4AAAAAQUAAAABbgUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACkJhZCBjYWxsZXIAAAAA1Tlvgg==" + + id = bytes.Repeat([]byte{0}, 32) + + smartState := smartStateDappFromDapp + + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + assetIDIssue = sr.Issues[0].ID + firstLeaseID := sr.Leases[0].ID + secondLeaseID := sr.Leases[1].ID + + expectedIssuesWrites := []*proto.IssueScriptAction{ + {Sender: &addressCallablePK, ID: assetIDIssue, Name: "barAsset", Description: "bar asset", Quantity: 1, Decimals: 0, Reissuable: false, Script: nil, Nonce: 0}, + } + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, + {Entry: &proto.BinaryDataEntry{Key: "asset", Value: assetIDIssue.Bytes()}, Sender: &addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + expectedTransferWrites := []*proto.TransferScriptAction{ + {Recipient: recipientCallable, Amount: 17, Asset: proto.NewOptionalAssetWaves(), Sender: &addrPK}, + {Recipient: recipient, Amount: 3, Asset: proto.NewOptionalAssetWaves(), Sender: &addressCallablePK}, + {Recipient: recipient, Amount: 1, Asset: *proto.NewOptionalAssetFromDigest(assetIDIssue), Sender: &addressCallablePK}, + } + + expectedLeasesWrites := []*proto.LeaseScriptAction{ + {Recipient: recipientCallable, Amount: 13, ID: firstLeaseID}, + {Recipient: recipientCallable, Amount: 23, ID: secondLeaseID}, + } + + expectedLeasesCancelWrites := []*proto.LeaseCancelScriptAction{ + {LeaseID: secondLeaseID}, + } + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: expectedIssuesWrites, + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: expectedLeasesWrites, + LeaseCancels: expectedLeasesCancelWrites, + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + + intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry + + binaryEntry := proto.BinaryDataEntry{Key: "asset", Value: assetIDIssue.Bytes()} + expectedDiffResult.dataEntries.diffBinary["asset"+addressCallable.String()] = binaryEntry + + newAsset := diffNewAssetInfo{dAppIssuer: addressCallable, name: "barAsset", description: "bar asset", quantity: 1, decimals: 0, reissuable: false, script: nil, nonce: 0} + expectedDiffResult.newAssetsInfo[assetIDIssue.String()] = newAsset + + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender + + balanceMainWaves := diffBalance{asset: proto.OptionalAsset{}, regular: 9986, effectiveHistory: []int64{10000, 9986}} + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMainWaves + + balanceCallableWaves := diffBalance{asset: proto.OptionalAsset{}, regular: 14, effectiveHistory: []int64{0, 14}} + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallableWaves + + balanceCallableBarAsset := diffBalance{asset: *proto.NewOptionalAssetFromDigest(assetIDIssue), regular: 0} + expectedDiffResult.balances[addressCallable.String()+proto.NewOptionalAssetFromDigest(assetIDIssue).String()] = balanceCallableBarAsset + + balanceMainBarAsset := diffBalance{asset: *proto.NewOptionalAssetFromDigest(assetIDIssue), regular: 1} + expectedDiffResult.balances[addr.String()+proto.NewOptionalAssetFromDigest(assetIDIssue).String()] = balanceMainBarAsset + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + assert.Equal(t, expectedDiffResult.newAssetsInfo, wrappedSt.diff.newAssetsInfo) + + tearDownDappFromDapp() +} + func TestInvokeDAppFromDAppNilResult(t *testing.T) { /* script 1 From 4dacd0263dd526d9e679557a174a4e31a1e13a7e Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 1 Apr 2021 16:14:02 +0300 Subject: [PATCH 21/52] =?UTF-8?q?Addded=20hash=20func=20for=20address'=20s?= =?UTF-8?q?cript=20and=20func=20for=20check=20if=20state=20of=20a=E2=80=A6?= =?UTF-8?q?=20(#441)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Addded hash func for address' script and func for check if state of an address is empty * Fixed methods * Deleted useless methods * Added test for hashFunc * Added test for isStorageUntouched func * Added function names in errors, fixed style --- pkg/ride/environment.go | 5 + pkg/ride/functions.go | 24 +-- pkg/ride/functions_proto.go | 34 ++++ pkg/ride/generate/main.go | 4 + pkg/ride/tree_evaluation_test.go | 269 ++++++++++++++++++++++++++++- pkg/ride/types_moq_test.go | 43 +++++ pkg/state/accounts_data_storage.go | 23 +++ pkg/state/state.go | 12 ++ pkg/types/types.go | 1 + 9 files changed, 402 insertions(+), 13 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 66307160c..e464a77ad 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -72,6 +72,7 @@ func (ws *WrappedState) NewestTransactionByID(id []byte) (proto.Transaction, err func (ws *WrappedState) NewestTransactionHeightByID(id []byte) (uint64, error) { return ws.diff.state.NewestTransactionHeightByID(id) } + func (ws *WrappedState) GetByteTree(recipient proto.Recipient) (proto.Script, error) { return ws.diff.state.GetByteTree(recipient) } @@ -152,6 +153,10 @@ func (ws *WrappedState) NewestFullWavesBalance(account proto.Recipient) (*proto. return balance, nil } +func (ws *WrappedState) IsStateUntouched(account proto.Recipient) (bool, error) { + return ws.diff.state.IsStateUntouched(account) +} + func (ws *WrappedState) RetrieveNewestIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { address, err := ws.diff.state.NewestRecipientToAddress(account) if err != nil { diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 25785b34b..950e2f1a5 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -88,8 +88,8 @@ func init() { _functions_V4 = [226]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} const _names_V4 = "!!=-0110010011004100510061007100810110210201031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" @@ -122,33 +122,33 @@ func costV4(id int) int { return _catalogue_V4[id] } -var _functions_V5 [230]rideFunction +var _functions_V5 [232]rideFunction func init() { - _functions_V5 = [230]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [232]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 100, 15, 100, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1004": 15, "1005": 100, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-0110010011004100510061007100810110210201031041040104110421043105105010511052105310610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-011001001100410051006100710081009101102102010310410401041104210431051050105110521053105410610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 43, 46, 49, 53, 57, 61, 65, 68, 72, 76, 80, 84, 87, 91, 95, 99, 102, 106, 109, 113, 117, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 281, 284, 287, 290, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 601, 618, 635, 652, 669, 686, 703, 720, 737, 765, 785, 806, 827, 847, 854, 859, 868, 883, 894, 906, 910, 913, 920, 935, 946, 950, 955, 963, 971, 977, 989, 1000, 1003, 1008, 1015, 1029, 1033, 1037, 1043, 1049, 1056, 1063, 1070, 1077, 1083, 1089, 1099, 1110, 1114, 1116, 1136, 1153, 1161, 1176, 1185, 1199, 1206, 1215, 1225, 1235, 1244, 1253, 1266, 1275, 1289, 1294, 1299, 1310, 1329} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 95, 99, 103, 107, 110, 114, 117, 121, 125, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 289, 292, 295, 298, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 609, 626, 643, 660, 677, 694, 711, 728, 745, 773, 793, 814, 835, 855, 862, 867, 876, 891, 902, 914, 918, 921, 928, 943, 954, 958, 963, 971, 979, 985, 997, 1008, 1011, 1016, 1023, 1037, 1041, 1045, 1051, 1057, 1064, 1071, 1078, 1085, 1091, 1097, 1107, 1118, 1122, 1124, 1144, 1161, 1169, 1184, 1193, 1207, 1214, 1223, 1233, 1243, 1252, 1261, 1274, 1283, 1297, 1302, 1307, 1318, 1337} func functionNameV5(i int) string { - if i < 0 || i > 229 { + if i < 0 || i > 231 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 229 { + if id < 0 || id > 231 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 229; i++ { + for i := 0; i <= 231; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 229 { + if id < 0 || id > 231 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index ea6e0bb8f..9fe093ad5 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -163,6 +163,40 @@ func invoke(env Environment, args ...rideType) (rideType, error) { return nil, errors.Errorf("result of Invoke is false") } +func hashScriptAtAddress(env Environment, args ...rideType) (rideType, error) { + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Errorf("hashScriptAtAddress func: unexpected argument type '%s'", args[0].instanceOf()) + } + + script, err := env.state().GetByteTree(recipient) + if err != nil { + return nil, errors.Errorf("hashScriptAtAddress func: failed to get script by recipient, %v", err) + } + + if len(script) != 0 { + hash, err := crypto.FastHash(script) + if err != nil { + return nil, errors.Errorf("hashScriptAtAddress func: failed to get hash of script, %v", err) + } + return rideBytes(hash.Bytes()), nil + } + + return rideUnit{}, nil +} + +func isDataStorageUntouched(env Environment, args ...rideType) (rideType, error) { + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Errorf("isDataStorageUntouched func: unexpected argument type '%s'", args[0].instanceOf()) + } + isUntouched, err := env.state().IsStateUntouched(recipient) + if err != nil { + return nil, errors.Wrapf(err, "isDataStorageUntouched func") + } + return rideBoolean(isUntouched), nil +} + func addressFromString(env Environment, args ...rideType) (rideType, error) { s, err := stringArg(args) if err != nil { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 9dad12ab4..6fa06e263 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -471,6 +471,8 @@ func functionsV5() map[string]string { m["1092"] = "simplifiedLease" m["1093"] = "fullLease" m["LeaseCancel"] = "leaseCancel" + m["1054"] = "isDataStorageUntouched" + m["1009"] = "hashScriptAtAddress" return m } @@ -480,6 +482,8 @@ func catalogueV5() map[string]int { m["1092"] = 1 m["1093"] = 1 m["LeaseCancel"] = 1 + m["1054"] = 10 + m["1009"] = 200 return m } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 910937dab..e5bb4c367 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -3120,6 +3120,272 @@ func TestInvokeDAppFromDAppSmartAssetValidation(t *testing.T) { tearDownDappFromDapp() } +func TestHashScriptFunc(t *testing.T) { + /* + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func foo() = { + let h = hashScriptAtAddress(this) + if hashScriptAtAddress(i.caller) == unit + then + [ BinaryEntry("hash", h.value()) ] + else + throw("Unexpected script was found.") + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + senderPK, err := crypto.NewPublicKeyFromBase58("2v89gsAztdyVq8aEVdNrxUZKtf1HfTAn5umC41idvykp") + require.NoError(t, err) + senderAddr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, senderPK) + require.NoError(t, err) + addrPK, err := crypto.NewPublicKeyFromBase58("2zb2orX2g58YZgXAvdn5ojTuPP8vAU2rsqYQ5L6KCXqz") + require.NoError(t, err) + addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, addrPK) + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: senderPK, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + inv, _ := invocationToObject(5, proto.MainNetScheme, tx) + + var script string + var wrappedSt WrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { + var resScript proto.Script + var err error + if recipient.Address.String() == addr.String() { + resScript, err = base64.StdEncoding.DecodeString(script) + } + if recipient.Address.String() == senderAddr.String() { + return proto.Script{}, nil + } + if err != nil { + return proto.Script{}, err + } + + return resScript, nil + }, + } + } + env := &MockRideEnvironment{ + schemeFunc: func() byte { + return proto.MainNetScheme + }, + heightFunc: func() rideInt { + return 368430 + }, + thisFunc: func() rideType { + return rideAddress(addr) + }, + invocationFunc: func() rideObject { + return inv + }, + timestampFunc: func() uint64 { + return 1564703444249 + }, + transactionFunc: func() rideObject { + obj, _ := transactionToObject(proto.MainNetScheme, tx) + return obj + }, + stateFunc: func() types.SmartState { + return &wrappedSt + }, + } + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + script = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABaAkAA/EAAAABBQAAAAR0aGlzAwkAAAAAAAACCQAD8QAAAAEIBQAAAAFpAAAABmNhbGxlcgUAAAAEdW5pdAkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACAgAAAARoYXNoCQEAAAAFdmFsdWUAAAABBQAAAAFoBQAAAANuaWwJAAACAAAAAQIAAAAcVW5leHBlY3RlZCBzY3JpcHQgd2FzIGZvdW5kLgAAAABGhMi8" + src, err := base64.StdEncoding.DecodeString(script) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + decodedScript, err := base64.StdEncoding.DecodeString(script) + require.NoError(t, err) + hash, err := crypto.FastHash(decodedScript) + require.NoError(t, err) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.BinaryDataEntry{Key: "hash", Value: hash.Bytes()}}, + } + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) +} + +func TestDataStorageUntouchedFunc(t *testing.T) { + /* + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + @Callable(i) + func foo() = { + let check = isDataStorageUntouched(this) + [ BooleanEntry("virgin", check) ] + } + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + senderPK, err := crypto.NewPublicKeyFromBase58("2v89gsAztdyVq8aEVdNrxUZKtf1HfTAn5umC41idvykp") + require.NoError(t, err) + + addrPK, err := crypto.NewPublicKeyFromBase58("2zb2orX2g58YZgXAvdn5ojTuPP8vAU2rsqYQ5L6KCXqz") + require.NoError(t, err) + addr, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, addrPK) + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx := &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: senderPK, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + //inv, _ := invocationToObject(5, proto.MainNetScheme, tx) + + var script string + var wrappedSt WrappedState + + smartState := func() types.SmartState { + return &MockSmartState{ + IsStateUntouchedFunc: func(recipient proto.Recipient) (bool, error) { + if recipient.Address.String() == addr.String() { + return false, nil + } else { + return false, errors.New("unexpected address") + } + }, + } + } + env := &MockRideEnvironment{ + schemeFunc: func() byte { + return proto.MainNetScheme + }, + heightFunc: func() rideInt { + return 368430 + }, + thisFunc: func() rideType { + return rideAddress(addr) + }, + timestampFunc: func() uint64 { + return 1564703444249 + }, + transactionFunc: func() rideObject { + obj, _ := transactionToObject(proto.MainNetScheme, tx) + return obj + }, + stateFunc: func() types.SmartState { + return &wrappedSt + }, + } + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + script = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAAFY2hlY2sJAAQeAAAAAQUAAAAEdGhpcwkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgIAAAAGdmlyZ2luBQAAAAVjaGVjawUAAAADbmlsAAAAAA8AdTc=" + src, err := base64.StdEncoding.DecodeString(script) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.BooleanDataEntry{Key: "virgin", Value: false}}, + } + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) +} + func TestMatchOverwrite(t *testing.T) { /* {-# STDLIB_VERSION 1 #-} @@ -3157,7 +3423,7 @@ func TestMatchOverwrite(t *testing.T) { env := &MockRideEnvironment{ schemeFunc: func() byte { - return proto.TestNetScheme + return proto.MainNetScheme }, heightFunc: func() rideInt { return 368430 @@ -3180,6 +3446,7 @@ func TestMatchOverwrite(t *testing.T) { } }, } + code := "AQQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAD0RhdGFUcmFuc2FjdGlvbgQAAAACZHQFAAAAByRtYXRjaDAEAAAAAWEJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACCAUAAAACZHQAAAAGc2VuZGVyAgAAAAFhBAAAAAF4AwkAAAAAAAACBQAAAAFhAAAAAAAAAAAABAAAAAckbWF0Y2gxCQAEGgAAAAIIBQAAAAJkdAAAAAZzZW5kZXICAAAAAXgDCQAAAQAAAAIFAAAAByRtYXRjaDECAAAAA0ludAQAAAABaQUAAAAHJG1hdGNoMQUAAAABaQAAAAAAAAAAAAAAAAAAAAAAAAQAAAACeHgEAAAAByRtYXRjaDEJAAQQAAAAAggFAAAAAmR0AAAABGRhdGECAAAAAXgDCQAAAQAAAAIFAAAAByRtYXRjaDECAAAAA0ludAQAAAABaQUAAAAHJG1hdGNoMQUAAAABaQAAAAAAAAAAAAkAAAAAAAACCQAAZAAAAAIFAAAAAXgFAAAAAnh4AAAAAAAAAAADB2NbtyA=" src, err := base64.StdEncoding.DecodeString(code) require.NoError(t, err) diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index 61fd58a67..80507f886 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -35,6 +35,9 @@ var _ types.SmartState = &MockSmartState{} // IsNotFoundFunc: func(err error) bool { // panic("mock out the IsNotFound method") // }, +// IsStateUntouchedFunc: func(account proto.Recipient) (bool, error) { +// panic("mock out the IsStateUntouched method") +// }, // NewestAccountBalanceFunc: func(account proto.Recipient, assetID []byte) (uint64, error) { // panic("mock out the NewestAccountBalance method") // }, @@ -108,6 +111,9 @@ type MockSmartState struct { // IsNotFoundFunc mocks the IsNotFound method. IsNotFoundFunc func(err error) bool + // IsStateUntouchedFunc mocks the IsStateUntouched method. + IsStateUntouchedFunc func(account proto.Recipient) (bool, error) + // NewestAccountBalanceFunc mocks the NewestAccountBalance method. NewestAccountBalanceFunc func(account proto.Recipient, assetID []byte) (uint64, error) @@ -184,6 +190,11 @@ type MockSmartState struct { // Err is the err argument value. Err error } + // IsStateUntouched holds details about calls to the IsStateUntouched method. + IsStateUntouched []struct { + // Account is the account argument value. + Account proto.Recipient + } // NewestAccountBalance holds details about calls to the NewestAccountBalance method. NewestAccountBalance []struct { // Account is the account argument value. @@ -289,6 +300,7 @@ type MockSmartState struct { lockEstimatorVersion sync.RWMutex lockGetByteTree sync.RWMutex lockIsNotFound sync.RWMutex + lockIsStateUntouched sync.RWMutex lockNewestAccountBalance sync.RWMutex lockNewestAddrByAlias sync.RWMutex lockNewestAssetInfo sync.RWMutex @@ -457,6 +469,37 @@ func (mock *MockSmartState) IsNotFoundCalls() []struct { return calls } +// IsStateUntouched calls IsStateUntouchedFunc. +func (mock *MockSmartState) IsStateUntouched(account proto.Recipient) (bool, error) { + if mock.IsStateUntouchedFunc == nil { + panic("MockSmartState.IsStateUntouchedFunc: method is nil but SmartState.IsStateUntouched was just called") + } + callInfo := struct { + Account proto.Recipient + }{ + Account: account, + } + mock.lockIsStateUntouched.Lock() + mock.calls.IsStateUntouched = append(mock.calls.IsStateUntouched, callInfo) + mock.lockIsStateUntouched.Unlock() + return mock.IsStateUntouchedFunc(account) +} + +// IsStateUntouchedCalls gets all the calls that were made to IsStateUntouched. +// Check the length with: +// len(mockedSmartState.IsStateUntouchedCalls()) +func (mock *MockSmartState) IsStateUntouchedCalls() []struct { + Account proto.Recipient +} { + var calls []struct { + Account proto.Recipient + } + mock.lockIsStateUntouched.RLock() + calls = mock.calls.IsStateUntouched + mock.lockIsStateUntouched.RUnlock() + return calls +} + // NewestAccountBalance calls NewestAccountBalanceFunc. func (mock *MockSmartState) NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) { if mock.NewestAccountBalanceFunc == nil { diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index ef2f97ee9..bbc43e52c 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -269,6 +269,29 @@ func (s *accountsDataStorage) retrieveEntries(addr proto.Address, filter bool) ( return entries, nil } +func (s *accountsDataStorage) isEntryExist(addr proto.Address, filter bool) (bool, error) { + addrNum, err := s.addrToNum(addr) + if err != nil { + return false, err + } + key := accountsDataStorKey{addrNum: addrNum} + iter, err := s.hs.newTopEntryIteratorByPrefix(key.accountPrefix(), filter) + if err != nil { + return false, err + } + defer func() { + iter.Release() + if err := iter.Error(); err != nil { + zap.S().Fatalf("Iterator error: %v", err) + } + }() + + for iter.Next() { + return true, nil + } + return false, nil +} + func (s *accountsDataStorage) retrieveNewestEntry(addr proto.Address, key string, filter bool) (proto.DataEntry, error) { id := entryId{addr, key} if entry, ok := s.uncertainEntries[id]; ok { diff --git a/pkg/state/state.go b/pkg/state/state.go index 1818a4466..229d58e88 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1696,6 +1696,18 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt return entries, nil } +func (s *stateManager) IsStateUntouched(account proto.Recipient) (bool, error) { + addr, err := s.recipientToAddress(account) + if err != nil { + return false, wrapErr(RetrievalError, err) + } + entryExist, err := s.stor.accountsDataStor.isEntryExist(*addr, true) + if err != nil { + return false, wrapErr(RetrievalError, err) + } + return !entryExist, nil +} + func (s *stateManager) RetrieveEntry(account proto.Recipient, key string) (proto.DataEntry, error) { addr, err := s.recipientToAddress(account) if err != nil { diff --git a/pkg/types/types.go b/pkg/types/types.go index 52c9f2dba..9dfa15062 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -43,6 +43,7 @@ type SmartState interface { NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) + IsStateUntouched(account proto.Recipient) (bool, error) // NewestAccountBalance retrieves balance of address in specific currency, asset is asset's ID. // nil asset = Waves. NewestAccountBalance(account proto.Recipient, assetID []byte) (uint64, error) From 28baf43d758ff614201f905546ce68728f1de024 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Fri, 2 Apr 2021 12:38:07 +0300 Subject: [PATCH 22/52] Ride BigInt support (#445) * New Int256 type added * WIP: Functions for BigInt math implemented. No test. * Invoke function moved to V5. Costs of some RIDE functions fixed. Small fixes. * WIP: Tests on BigInt's Pow and Log function added. * Ride's BigInt type converted to structure that holds pointer to Go's big.Int. All tests implemented. * Style fixes * Comments added --- pkg/keyvalue/leveldb_test.go | 1 + pkg/ride/functions.go | 40 +- pkg/ride/functions_bigint.go | 655 +++++++++++++++++++++++++++ pkg/ride/functions_bigint_test.go | 724 ++++++++++++++++++++++++++++++ pkg/ride/functions_int.go | 4 +- pkg/ride/functions_proto.go | 10 +- pkg/ride/functions_test.go | 2 +- pkg/ride/generate/main.go | 52 ++- pkg/ride/math/math.go | 158 +++++-- pkg/ride/runtime.go | 25 ++ pkg/ride/tree_evaluation_test.go | 1 + 11 files changed, 1604 insertions(+), 68 deletions(-) create mode 100644 pkg/ride/functions_bigint.go create mode 100644 pkg/ride/functions_bigint_test.go diff --git a/pkg/keyvalue/leveldb_test.go b/pkg/keyvalue/leveldb_test.go index 9e18fa9d5..7f54baf94 100644 --- a/pkg/keyvalue/leveldb_test.go +++ b/pkg/keyvalue/leveldb_test.go @@ -17,6 +17,7 @@ const ( func TestKeyVal(t *testing.T) { dbDir, err := ioutil.TempDir(os.TempDir(), "dbDir0") + assert.NoError(t, err) params := KeyValParams{ CacheParams: CacheParams{cacheSize}, BloomFilterParams: BloomFilterParams{n, falsePositiveProbability, NoOpStore{}, false}, diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 950e2f1a5..217703bf6 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -82,33 +82,33 @@ func costV3(id int) int { return _catalogue_V3[id] } -var _functions_V4 [226]rideFunction +var _functions_V4 [225]rideFunction func init() { - _functions_V4 = [226]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V4 = [225]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V4 = "!!=-0110010011004100510061007100810110210201031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V4 = "!!=-011001001100410051006100710081011021031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 43, 46, 49, 53, 57, 61, 65, 68, 72, 76, 80, 84, 87, 91, 95, 99, 102, 106, 109, 113, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 269, 272, 275, 278, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 488, 491, 494, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 589, 606, 623, 640, 657, 674, 691, 708, 725, 753, 773, 794, 815, 835, 842, 847, 856, 871, 882, 894, 898, 901, 908, 923, 934, 938, 943, 951, 959, 965, 977, 980, 985, 992, 1006, 1010, 1014, 1020, 1026, 1033, 1040, 1047, 1054, 1060, 1066, 1076, 1087, 1091, 1093, 1113, 1130, 1138, 1153, 1162, 1176, 1183, 1192, 1202, 1212, 1221, 1230, 1243, 1252, 1266, 1271, 1276, 1287, 1306} +var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 265, 268, 271, 274, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 585, 602, 619, 636, 653, 670, 687, 704, 721, 749, 769, 790, 811, 831, 838, 843, 852, 867, 878, 890, 894, 897, 904, 919, 930, 934, 939, 947, 955, 961, 973, 976, 981, 988, 1002, 1006, 1010, 1016, 1022, 1029, 1036, 1043, 1050, 1056, 1062, 1072, 1083, 1087, 1089, 1109, 1126, 1134, 1149, 1158, 1172, 1179, 1188, 1198, 1208, 1217, 1226, 1239, 1248, 1262, 1267, 1272, 1283, 1302} func functionNameV4(i int) string { - if i < 0 || i > 225 { + if i < 0 || i > 224 { return "" } return _names_V4[_index_V4[i]:_index_V4[i+1]] } func functionV4(id int) rideFunction { - if id < 0 || id > 225 { + if id < 0 || id > 224 { return nil } return _functions_V4[id] } func checkFunctionV4(name string) (uint16, bool) { - for i := 0; i <= 225; i++ { + for i := 0; i <= 224; i++ { if _names_V4[_index_V4[i]:_index_V4[i+1]] == name { return uint16(i), true } @@ -116,39 +116,39 @@ func checkFunctionV4(name string) (uint16, bool) { return 0, false } func costV4(id int) int { - if id < 0 || id > 225 { + if id < 0 || id > 224 { return -1 } return _catalogue_V4[id] } -var _functions_V5 [232]rideFunction +var _functions_V5 [255]rideFunction func init() { - _functions_V5 = [232]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [255]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-011001001100410051006100710081009101102102010310410401041104210431051050105110521053105410610601061106210710701081080108110910901091109210931100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-011001001100410051006100710081009101102102010310410401041104210431051050105110521053105410610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 95, 99, 103, 107, 110, 114, 117, 121, 125, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 289, 292, 295, 298, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 609, 626, 643, 660, 677, 694, 711, 728, 745, 773, 793, 814, 835, 855, 862, 867, 876, 891, 902, 914, 918, 921, 928, 943, 954, 958, 963, 971, 979, 985, 997, 1008, 1011, 1016, 1023, 1037, 1041, 1045, 1051, 1057, 1064, 1071, 1078, 1085, 1091, 1097, 1107, 1118, 1122, 1124, 1144, 1161, 1169, 1184, 1193, 1207, 1214, 1223, 1233, 1243, 1252, 1261, 1274, 1283, 1297, 1302, 1307, 1318, 1337} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 95, 99, 103, 107, 110, 114, 117, 121, 125, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 167, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 295, 298, 301, 304, 307, 311, 315, 319, 323, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 595, 598, 601, 604, 607, 610, 613, 616, 619, 622, 625, 628, 631, 634, 637, 640, 643, 646, 649, 652, 655, 658, 661, 678, 695, 712, 729, 746, 763, 780, 797, 814, 842, 862, 883, 904, 924, 931, 936, 945, 960, 971, 983, 987, 990, 997, 1012, 1023, 1027, 1032, 1040, 1048, 1054, 1066, 1077, 1080, 1085, 1092, 1106, 1110, 1114, 1120, 1126, 1133, 1140, 1147, 1154, 1160, 1166, 1176, 1187, 1191, 1193, 1213, 1230, 1238, 1253, 1262, 1276, 1283, 1292, 1302, 1312, 1321, 1330, 1343, 1352, 1366, 1371, 1376, 1387, 1406} func functionNameV5(i int) string { - if i < 0 || i > 231 { + if i < 0 || i > 254 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 231 { + if id < 0 || id > 254 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 231; i++ { + for i := 0; i <= 254; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 231 { + if id < 0 || id > 254 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_bigint.go b/pkg/ride/functions_bigint.go new file mode 100644 index 000000000..0686c0f72 --- /dev/null +++ b/pkg/ride/functions_bigint.go @@ -0,0 +1,655 @@ +package ride + +import ( + "math/big" + "sort" + + "github.com/ericlagergren/decimal" + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/ride/math" +) + +var ( + minBigInt, maxBigInt = initBoundaries() + zeroBigInt = big.NewInt(0) + oneBigInt = big.NewInt(1) +) + +func initBoundaries() (*big.Int, *big.Int) { + max := big.NewInt(0) + max = max.Exp(big.NewInt(2), big.NewInt(511), nil) + max = max.Sub(max, oneBigInt) + + min := big.NewInt(0) + min = min.Neg(max) + min = min.Sub(min, oneBigInt) + return min, max +} + +func bigIntArg(args []rideType) (rideBigInt, error) { + if len(args) != 1 { + return rideBigInt{}, errors.Errorf("%d is invalid number of arguments, expected 1", len(args)) + } + if args[0] == nil { + return rideBigInt{}, errors.Errorf("argument 1 is empty") + } + l, ok := args[0].(rideBigInt) + if !ok { + return rideBigInt{}, errors.Errorf("argument 1 is not of type 'BigInt' but '%s'", args[0].instanceOf()) + } + return l, nil +} + +func twoBigIntArgs(args []rideType) (rideBigInt, rideBigInt, error) { + if len(args) != 2 { + return rideBigInt{}, rideBigInt{}, errors.Errorf("%d is invalid number of arguments, expected 2", len(args)) + } + if args[0] == nil { + return rideBigInt{}, rideBigInt{}, errors.Errorf("argument 1 is empty") + } + if args[1] == nil { + return rideBigInt{}, rideBigInt{}, errors.Errorf("argument 2 is empty") + } + v1, ok := args[0].(rideBigInt) + if !ok { + return rideBigInt{}, rideBigInt{}, errors.Errorf("argument 1 is not of type 'BigInt' but '%s'", args[0].instanceOf()) + } + v2, ok := args[1].(rideBigInt) + if !ok { + return rideBigInt{}, rideBigInt{}, errors.Errorf("argument 2 is not of type 'BigInt' but '%s'", args[1].instanceOf()) + } + return v1, v2, nil +} + +func threeBigIntArgs(args []rideType) (rideBigInt, rideBigInt, rideBigInt, error) { + if len(args) != 3 { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("%d is invalid number of arguments, expected 3", len(args)) + } + if args[0] == nil { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 1 is empty") + } + if args[1] == nil { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 2 is empty") + } + if args[2] == nil { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 3 is empty") + } + v1, ok := args[0].(rideBigInt) + if !ok { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 1 is not of type 'BigInt' but '%s'", args[0].instanceOf()) + } + v2, ok := args[1].(rideBigInt) + if !ok { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 2 is not of type 'BigInt' but '%s'", args[1].instanceOf()) + } + v3, ok := args[2].(rideBigInt) + if !ok { + return rideBigInt{}, rideBigInt{}, rideBigInt{}, errors.Errorf("argument 3 is not of type 'BigInt' but '%s'", args[2].instanceOf()) + } + return v1, v2, v3, nil +} + +func powBigInt(_ Environment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 6); err != nil { + return nil, errors.Wrap(err, "powBigInt") + } + base, ok := args[0].(rideBigInt) + if !ok { + return nil, errors.Errorf("powBigInt: unexpected argument type '%s'", args[0].instanceOf()) + } + bp, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("powBigInt: unexpected argument type '%s'", args[1].instanceOf()) + } + exponent, ok := args[2].(rideBigInt) + if !ok { + return nil, errors.Errorf("powBigInt: unexpected argument type '%s'", args[2].instanceOf()) + } + ep, ok := args[3].(rideInt) + if !ok { + return nil, errors.Errorf("powBigInt: unexpected argument type '%s'", args[3].instanceOf()) + } + rp, ok := args[4].(rideInt) + if !ok { + return nil, errors.Errorf("powBigInt: unexpected argument type '%s'", args[4].instanceOf()) + } + round, err := roundingMode(args[5]) + if err != nil { + return nil, errors.Wrap(err, "powBigInt") + } + b := big.NewInt(0).Set(base.v) + e := big.NewInt(0).Set(exponent.v) + r, err := math.PowBigInt(b, e, int(bp), int(ep), int(rp), round) + if err != nil { + return nil, errors.Wrap(err, "powBigInt") + } + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.New("powBigInt: result is out of range") + } + return rideBigInt{v: r}, nil +} + +func logBigInt(_ Environment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 6); err != nil { + return nil, errors.Wrap(err, "logBigInt") + } + base, ok := args[0].(rideBigInt) + if !ok { + return nil, errors.Errorf("logBigInt: unexpected argument type '%s'", args[0].instanceOf()) + } + bp, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("logBigInt: unexpected argument type '%s'", args[1].instanceOf()) + } + exponent, ok := args[2].(rideBigInt) + if !ok { + return nil, errors.Errorf("logBigInt: unexpected argument type '%s'", args[2].instanceOf()) + } + ep, ok := args[3].(rideInt) + if !ok { + return nil, errors.Errorf("logBigInt: unexpected argument type '%s'", args[3].instanceOf()) + } + rp, ok := args[4].(rideInt) + if !ok { + return nil, errors.Errorf("logBigInt: unexpected argument type '%s'", args[4].instanceOf()) + } + round, err := roundingMode(args[5]) + if err != nil { + return nil, errors.Wrap(err, "logBigInt") + } + b := big.NewInt(0).Set(base.v) + e := big.NewInt(0).Set(exponent.v) + r, err := math.LogBigInt(b, e, int(bp), int(ep), int(rp), round) + if err != nil { + return nil, errors.Wrap(err, "logBigInt") + } + return rideBigInt{v: r}, nil +} + +func toBigInt(_ Environment, args ...rideType) (rideType, error) { + i, err := intArg(args) + if err != nil { + return nil, errors.Wrap(err, "toBigInt") + } + v := big.NewInt(int64(i)) + return rideBigInt{v: v}, nil +} + +func sumBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "sumBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + r := i1.Add(i1, i2) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("sumBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func subtractBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "subtractBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + r := i1.Sub(i1, i2) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("subtractBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func multiplyBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "multiplyBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + r := i1.Mul(i1, i2) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("multiplyBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func divideBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "divideBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + if i2.Cmp(zeroBigInt) == 0 { + return nil, errors.New("divideBigInt: division by zero") + } + r := i1.Div(i1, i2) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("divideBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func moduloBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "moduloBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + if i2.Cmp(zeroBigInt) == 0 { + return nil, errors.New("moduloBigInt: division by zero") + } + //(a % b + b) % b + r0 := i1.Rem(i1, i2) + r1 := r0.Add(r0, i2) + r := r1.Rem(r1, i2) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("moduloBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func fractionBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, c, err := threeBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "fractionBigInt") + } + v := big.NewInt(0).Set(a.v) + n := big.NewInt(0).Set(b.v) + d := big.NewInt(0).Set(c.v) + if d.Cmp(zeroBigInt) == 0 { + return nil, errors.New("fractionBigInt: division by zero") + } + r := v.Mul(v, n) + r = r.Quo(r, d) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("fractionBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func fractionBigIntRounds(_ Environment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 4); err != nil { + return nil, errors.Wrap(err, "fractionBigIntRounds") + } + v1, ok := args[0].(rideBigInt) + if !ok { + return nil, errors.Errorf("fractionBigIntRounds: unexpected argument type '%s'", args[0].instanceOf()) + } + v := big.NewInt(0).Set(v1.v) + v2, ok := args[1].(rideBigInt) + if !ok { + return nil, errors.Errorf("fractionBigIntRounds: unexpected argument type '%s'", args[1].instanceOf()) + } + n := big.NewInt(0).Set(v2.v) + v3, ok := args[2].(rideBigInt) + if !ok { + return nil, errors.Errorf("fractionBigIntRounds: unexpected argument type '%s'", args[2].instanceOf()) + } + d := big.NewInt(0).Set(v3.v) + if d.Cmp(zeroBigInt) == 0 { + return nil, errors.New("fractionBigIntRounds: division by zero") + } + round, err := roundingMode(args[3]) + if err != nil { + return nil, errors.Wrap(err, "fractionBigIntRounds") + } + // This algo is fully taken from Scala implementation + p := v.Mul(v, n) + s := big.NewInt(int64(p.Sign() * d.Sign())) + pa := p.Abs(p) + da := d.Abs(d) + r, m := pa.QuoRem(pa, da, big.NewInt(0)) + ms := big.NewInt(int64(m.Sign())) + switch round { + case decimal.ToZero: // Down + r = r.Mul(r, s) + case decimal.AwayFromZero: // Up + r = r.Add(r, ms) + r = r.Mul(r, s) + case decimal.ToNearestAway: // HalfUp + x := d.Abs(d) + y := m.Mul(m, big.NewInt(2)) + x = x.Sub(x, y) + switch x.Cmp(zeroBigInt) { + case -1: + r = r.Add(r, big.NewInt(1)) + r = r.Mul(r, s) + case 0: + r = r.Add(r, big.NewInt(1)) + r = r.Mul(r, s) + case 1: + r = r.Mul(r, s) + } + case decimal.ToNearestTowardZero: // RoundHalfDown + x := d.Abs(d) + y := m.Mul(m, big.NewInt(2)) + x = x.Sub(x, y) + if x.Cmp(zeroBigInt) < 0 { + r = r.Add(r, big.NewInt(1)) + r = r.Mul(r, s) + } else { + r = r.Mul(r, s) + } + case decimal.ToPositiveInf: // Ceiling + if s.Cmp(zeroBigInt) > 0 { + r = r.Add(r, ms) + } + r = r.Mul(r, s) + case decimal.ToNegativeInf: // Floor + if s.Cmp(zeroBigInt) < 0 { + r = r.Add(r, ms) + } + r = r.Mul(r, s) + case decimal.ToNearestEven: // HalfEven + x := d.Abs(d) + y := m.Mul(m, big.NewInt(2)) + x = x.Sub(x, y) + switch x.Cmp(zeroBigInt) { + case -1: + r = r.Add(r, big.NewInt(1)) + r = r.Mul(r, s) + case 1: + r = r.Mul(r, s) + case 0: + r2 := big.NewInt(2) + r2 = r2.Mod(r, r2) + r = r.Add(r, r2) + r = r.Mul(r, s) + } + default: + return nil, errors.New("fractionBigIntRounds: unsupported rounding mode") + } + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("fractionBigIntRounds: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func unaryMinusBigInt(_ Environment, args ...rideType) (rideType, error) { + v, err := bigIntArg(args) + if err != nil { + return nil, errors.Wrap(err, "unaryMinusBigInt") + } + i := big.NewInt(0).Set(v.v) + if i.Cmp(minBigInt) == 0 { + return nil, errors.New("unaryMinusBigInt: positive BigInt overflow") + } + r := i.Neg(i) + return rideBigInt{v: r}, nil +} + +func gtBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "gtBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + r := i1.Cmp(i2) + return rideBoolean(r > 0), nil +} + +func geBigInt(_ Environment, args ...rideType) (rideType, error) { + a, b, err := twoBigIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "geBigInt") + } + i1 := big.NewInt(0).Set(a.v) + i2 := big.NewInt(0).Set(b.v) + r := i1.Cmp(i2) + return rideBoolean(r >= 0), nil +} + +func maxListBigInt(_ Environment, args ...rideType) (rideType, error) { + list, err := listArg(args) + if err != nil { + return nil, errors.Wrap(err, "maxListBigInt") + } + size := len(list) + if size > maxListSize || size == 0 { + return nil, errors.Errorf("maxListBigInt: invalid list size %d", size) + } + items, err := toBigIntSlice(list) + if err != nil { + return nil, errors.Wrap(err, "maxListBigInt") + } + _, max := minMaxBigInt(items) + return rideBigInt{v: max}, nil +} + +func minListBigInt(_ Environment, args ...rideType) (rideType, error) { + list, err := listArg(args) + if err != nil { + return nil, errors.Wrap(err, "minListBigInt") + } + size := len(list) + if size > maxListSize || size == 0 { + return nil, errors.Errorf("minListBigInt: invalid list size %d", size) + } + items, err := toBigIntSlice(list) + if err != nil { + return nil, errors.Wrap(err, "minListBigInt") + } + min, _ := minMaxBigInt(items) + return rideBigInt{v: min}, nil +} + +func bigIntToBytes(_ Environment, args ...rideType) (rideType, error) { + v, err := bigIntArg(args) + if err != nil { + return nil, errors.Wrap(err, "bigIntToBytes") + } + i := big.NewInt(0).Set(v.v) + return rideBytes(encode2CBigInt(i)), nil +} + +func bytesToBigInt(_ Environment, args ...rideType) (rideType, error) { + bts, err := bytesArg(args) + if err != nil { + return nil, errors.Wrap(err, "bytesToBigInt") + } + if l := len(bts); l > 64 { // No more then 64 bytes can be converted to BigInt, max size of BigInt value is 512 bit. + return nil, errors.Errorf("bytesToBigInt: bytes array is too long (%d) for a BigInt", l) + } + r := decode2CBigInt(bts) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("bytesToBigInt: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func bytesToBigIntLim(_ Environment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 3); err != nil { + return nil, errors.Wrap(err, "bytesToBigIntLim") + } + bts, ok := args[0].(rideBytes) + if !ok { + return nil, errors.Errorf("bytesToBigIntLim: argument 1 is not of type 'ByteVector' but '%s'", args[0].instanceOf()) + } + l := len(bts) + offset, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("bytesToBigIntLim: argument 2 is not of type 'Int' but '%s'", args[1].instanceOf()) + } + if offset < 0 || int(offset) >= l { + return nil, errors.Errorf("bytesToBigIntLim: offset %d is out of range [0; %d]", offset, len(bts)-1) + } + size, ok := args[2].(rideInt) + if !ok { + return nil, errors.Errorf("bytesToBigIntLim: argument 3 is not of type 'Int' but '%s'", args[2].instanceOf()) + } + if size <= 0 || size > 64 { // No more then 64 bytes can be converted to BigInt, max size of BigInt value is 512 bit. + return nil, errors.Errorf("bytesToBigIntLim: size %d is out of ranger [1; 64]", size) + } + end := int(offset + size) + if end > l { + end = l + } + r := decode2CBigInt(bts[offset:end]) + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("bytesToBigIntLim: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +func bigIntToInt(_ Environment, args ...rideType) (rideType, error) { + v, err := bigIntArg(args) + if err != nil { + return nil, errors.Wrap(err, "bigIntToInt") + } + i := big.NewInt(0).Set(v.v) + if !i.IsInt64() { + return nil, errors.Errorf("bigIntToInt: value (%s) is too big for an Int", i.String()) + } + return rideInt(i.Int64()), nil +} + +func bigIntToString(_ Environment, args ...rideType) (rideType, error) { + v, err := bigIntArg(args) + if err != nil { + return nil, errors.Wrap(err, "bigIntToString") + } + i := big.NewInt(0).Set(v.v) + return rideString(i.String()), nil +} + +func stringToBigInt(_ Environment, args ...rideType) (rideType, error) { + s, err := stringArg(args) + if err != nil { + return nil, errors.Wrap(err, "stringToBigInt") + } + if l := len(s); l > 155 { // 155 symbols is the length of minBigInt value is string representation + return nil, errors.Errorf("stringToBigInt: string is too long (%d symbols) for a BigInt", l) + } + r, ok := big.NewInt(0).SetString(string(s), 10) + if !ok { + return nil, errors.Errorf("stringToBigInt: failed to convert string '%s' to BigInt", s) + } + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.New("stringToBigInt: value too big for a BigInt") + } + return rideBigInt{v: r}, nil +} + +func stringToBigIntOpt(env Environment, args ...rideType) (rideType, error) { + v, err := stringToBigInt(env, args...) + if err != nil { + return newUnit(env), nil + } + return v, nil +} + +func medianListBigInt(_ Environment, args ...rideType) (rideType, error) { + list, err := listArg(args) + if err != nil { + return nil, errors.Wrap(err, "medianListBigInt") + } + size := len(list) + if size > maxListSize || size < 2 { + return nil, errors.Errorf("medianListBigInt: invalid list size %d", size) + } + items, err := toBigIntSlice(list) + if err != nil { + return nil, errors.Wrap(err, "medianListBigInt") + } + sort.Sort(items) + half := size / 2 + if size%2 == 1 { + return rideBigInt{v: items[half]}, nil + } + x := items[half-1] + y := items[half] + r := math.FloorDivBigInt(x.Add(x, y), big.NewInt(2)) + return rideBigInt{v: r}, nil +} + +func minMaxBigInt(items []*big.Int) (*big.Int, *big.Int) { + if len(items) == 0 { + panic("empty slice") + } + max, min := items[0], items[0] + for _, i := range items { + if i.Cmp(max) > 0 { + max = i + } + if i.Cmp(min) < 0 { + min = i + } + } + return min, max +} + +type bigIntSlice []*big.Int + +func (x bigIntSlice) Len() int { return len(x) } +func (x bigIntSlice) Less(i, j int) bool { return x[i].Cmp(x[j]) < 0 } +func (x bigIntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func toBigIntSlice(list rideList) (bigIntSlice, error) { + items := make([]*big.Int, len(list)) + for i, el := range list { + item, ok := el.(rideBigInt) + if !ok { + return nil, errors.Errorf("unexpected type of list element '%s'", el.instanceOf()) + } + items[i] = big.NewInt(0).Set(item.v) + } + return items, nil +} + +// decode2CBigInt decodes two's complement representation of BigInt from bytes slice +func decode2CBigInt(bytes []byte) *big.Int { + r := new(big.Int) + if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { // Decode a negative number + notBytes := make([]byte, len(bytes)) + for i := range notBytes { + notBytes[i] = ^bytes[i] + } + r.SetBytes(notBytes) + r.Add(r, oneBigInt) + r.Neg(r) + return r + } + r.SetBytes(bytes) + return r +} + +// encode2CBigInt encodes BigInt into a two's compliment representation +func encode2CBigInt(n *big.Int) []byte { + if n.Sign() < 0 { + // Convert negative number into two's complement form + // Subtract 1 and invert + // If the most-significant-bit isn't set then we'll need to pad the beginning with 0xff in order to keep the number negative + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, oneBigInt) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if l := len(bytes); l == 0 || bytes[0]&0x80 == 0 { + return padBytes(0xff, bytes) + } + return bytes + } else if n.Sign() == 0 { // Zero is written as a single 0 zero rather than no bytes + return []byte{0x00} + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { // We'll have to pad this with 0x00 in order to stop it looking like a negative number + return padBytes(0x00, bytes) + } + return bytes + } +} + +func padBytes(p byte, bytes []byte) []byte { + r := make([]byte, len(bytes)+1) + r[0] = p + copy(r[1:], bytes) + return r +} diff --git a/pkg/ride/functions_bigint_test.go b/pkg/ride/functions_bigint_test.go new file mode 100644 index 000000000..825c8d05a --- /dev/null +++ b/pkg/ride/functions_bigint_test.go @@ -0,0 +1,724 @@ +package ride + +import ( + "encoding/hex" + "fmt" + "math" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPowBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(12), rideInt(1), toRideBigInt(3456), rideInt(3), rideInt(2), newDown(nil)}, false, toRideBigInt(187)}, + {[]rideType{toRideBigInt(12), rideInt(1), toRideBigInt(3456), rideInt(3), rideInt(2), newUp(nil)}, false, toRideBigInt(188)}, + {[]rideType{toRideBigInt(0), rideInt(1), toRideBigInt(3456), rideInt(3), rideInt(2), newUp(nil)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(0), rideInt(1), toRideBigInt(3456), rideInt(3), rideInt(2), newDown(nil)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(20), rideInt(1), toRideBigInt(-1), rideInt(0), rideInt(4), newDown(nil)}, false, toRideBigInt(5000)}, + {[]rideType{toRideBigInt(-20), rideInt(1), toRideBigInt(-1), rideInt(0), rideInt(4), newDown(nil)}, false, toRideBigInt(-5000)}, + {[]rideType{toRideBigInt(0), rideInt(1), toRideBigInt(-1), rideInt(0), rideInt(4), newDown(nil)}, true, nil}, + {[]rideType{toRideBigInt(2), rideInt(0), toRideBigInt(512), rideInt(0), rideInt(0), newDown(nil)}, true, nil}, + {[]rideType{toRideBigInt(12), rideInt(1), toRideBigInt(3456), rideInt(3), rideInt(2), newUp(nil), newDown(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(10), rideInt(0), rideInt(0), newUp(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(1), rideInt(0), rideInt(0), newNoAlg(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(1), rideString("0"), rideInt(0), newUp(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(1), rideInt(0), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(1), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(1)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := powBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestLogBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(16), rideInt(0), toRideBigInt(2), rideInt(0), rideInt(0), newCeiling(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(1), rideInt(4), toRideBigInt(1), rideInt(1), rideInt(0), newHalfEven(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(16), rideInt(0), toRideBigInt(-2), rideInt(0), rideInt(0), newCeiling(nil)}, true, nil}, + {[]rideType{toRideBigInt(-16), rideInt(0), toRideBigInt(2), rideInt(0), rideInt(0), newCeiling(nil)}, true, nil}, + {[]rideType{toRideBigInt(1), rideInt(16), toRideBigInt(10), rideInt(0), rideInt(0), newCeiling(nil)}, false, toRideBigInt(-16)}, + {[]rideType{toRideBigInt(100), rideInt(0), toRideBigInt(10), rideInt(0), rideInt(0), newUp(nil)}, false, toRideBigInt(2)}, + {[]rideType{toRideBigInt(100), rideInt(0), toRideBigInt(10), rideInt(0), rideInt(0), newUp(nil), newDown(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(100), rideInt(0), rideInt(0), newNoAlg(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(100), rideString("0"), rideInt(0), newUp(nil)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(100), rideInt(0), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(100), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0), toRideBigInt(100)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64), rideInt(0)}, true, nil}, + {[]rideType{toRideBigInt(math.MaxInt64)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := logBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestToBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideInt(0)}, false, toRideBigInt(0)}, + {[]rideType{rideInt(-1)}, false, toRideBigInt(-1)}, + {[]rideType{rideInt(1)}, false, toRideBigInt(1)}, + {[]rideType{rideInt(-1234567890)}, false, toRideBigInt(-1234567890)}, + {[]rideType{rideInt(1234567890)}, false, toRideBigInt(1234567890)}, + {[]rideType{rideInt(math.MaxInt64)}, false, toRideBigInt(math.MaxInt64)}, + {[]rideType{rideInt(math.MinInt64)}, false, toRideBigInt(math.MinInt64)}, + {[]rideType{}, true, nil}, + {[]rideType{rideString("12345")}, true, nil}, + {[]rideType{toRideBigInt(12345)}, true, nil}, + {[]rideType{rideInt(12345), rideInt(67890)}, true, nil}, + } { + r, err := toBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestSumBigInt(t *testing.T) { + doubleMaxInt64 := big.NewInt(math.MaxInt64) + doubleMaxInt64 = doubleMaxInt64.Add(doubleMaxInt64, doubleMaxInt64) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(5), toRideBigInt(5)}, false, toRideBigInt(10)}, + {[]rideType{toRideBigInt(-5), toRideBigInt(5)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(0), toRideBigInt(0)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(math.MinInt64)}, false, toRideBigInt(-1)}, + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(math.MaxInt64)}, false, rideBigInt{v: doubleMaxInt64}}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(1)}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(1), toRideBigInt(1)}, true, nil}, + {[]rideType{toRideBigInt(1), rideInt(1)}, true, nil}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := sumBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestSubtractBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(5), toRideBigInt(4)}, false, toRideBigInt(1)}, + {[]rideType{toRideBigInt(5), toRideBigInt(5)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(-5), toRideBigInt(5)}, false, toRideBigInt(-10)}, + {[]rideType{toRideBigInt(0), toRideBigInt(0)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(math.MaxInt64)}, false, toRideBigInt(0)}, + {[]rideType{rideBigInt{v: minBigInt}, toRideBigInt(1)}, true, nil}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := subtractBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestMultiplyBigInt(t *testing.T) { + n := big.NewInt(math.MaxInt64) + n = n.Mul(n, n) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(5), toRideBigInt(4)}, false, toRideBigInt(20)}, + {[]rideType{toRideBigInt(5), toRideBigInt(5)}, false, toRideBigInt(25)}, + {[]rideType{toRideBigInt(-5), toRideBigInt(5)}, false, toRideBigInt(-25)}, + {[]rideType{toRideBigInt(0), toRideBigInt(0)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(math.MaxInt64)}, false, rideBigInt{v: n}}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(2)}, true, nil}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := multiplyBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestDivideBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(10), toRideBigInt(2)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(25), toRideBigInt(5)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(-25), toRideBigInt(5)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(math.MaxInt64)}, false, toRideBigInt(1)}, + {[]rideType{rideBigInt{v: maxBigInt}, rideBigInt{v: maxBigInt}}, false, toRideBigInt(1)}, + {[]rideType{rideBigInt{v: minBigInt}, rideBigInt{v: minBigInt}}, false, toRideBigInt(1)}, + {[]rideType{rideBigInt{v: maxBigInt}, rideBigInt{v: minBigInt}}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(10), toRideBigInt(0)}, true, nil}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := divideBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestModuloBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(10), toRideBigInt(6)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(-10), toRideBigInt(6)}, false, toRideBigInt(2)}, + {[]rideType{toRideBigInt(10), toRideBigInt(-6)}, false, toRideBigInt(-2)}, + {[]rideType{toRideBigInt(-10), toRideBigInt(-6)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(2), toRideBigInt(2)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(10), toRideBigInt(0)}, true, nil}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := moduloBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestFractionBigInt(t *testing.T) { + r1 := big.NewInt(0).Set(maxBigInt) + r1 = r1.Mul(r1, big.NewInt(2)) + r1 = r1.Div(r1, big.NewInt(3)) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(4), toRideBigInt(6)}, false, toRideBigInt(6148914691236517204)}, + {[]rideType{toRideBigInt(8), toRideBigInt(4), toRideBigInt(2)}, false, toRideBigInt(16)}, + {[]rideType{toRideBigInt(8), toRideBigInt(-2), toRideBigInt(-3)}, false, toRideBigInt(5)}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(-2), toRideBigInt(-3)}, false, rideBigInt{v: r1}}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(1)}, true, nil}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(0)}, true, nil}, + {[]rideType{toRideBigInt(2), toRideBigInt(2)}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := fractionBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestFractionBigIntRounds(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(math.MaxInt64), toRideBigInt(4), toRideBigInt(6), newFloor(nil)}, false, toRideBigInt(6148914691236517204)}, + {[]rideType{toRideBigInt(8), toRideBigInt(4), toRideBigInt(2), newFloor(nil)}, false, toRideBigInt(16)}, + {[]rideType{toRideBigInt(8), toRideBigInt(-2), toRideBigInt(-3), newFloor(nil)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(2), newDown(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newDown(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newDown(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newDown(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(2), newCeiling(nil)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newCeiling(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newCeiling(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newCeiling(nil)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(2), newFloor(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newFloor(nil)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newFloor(nil)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newFloor(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(2), newHalfUp(nil)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newHalfUp(nil)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newHalfUp(nil)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newHalfUp(nil)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(2), newHalfEven(nil)}, false, toRideBigInt(4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newHalfEven(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newHalfEven(nil)}, false, toRideBigInt(-4)}, + {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newHalfEven(nil)}, false, toRideBigInt(4)}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(1), newFloor(nil)}, true, nil}, + {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(0), newFloor(nil)}, true, nil}, + {[]rideType{toRideBigInt(2), toRideBigInt(2), toRideBigInt(3)}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := fractionBigIntRounds(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestUnaryMinusBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(math.MaxInt64)}, false, toRideBigInt(-math.MaxInt64)}, + {[]rideType{toRideBigInt(5)}, false, toRideBigInt(-5)}, + {[]rideType{toRideBigInt(0)}, false, toRideBigInt(0)}, + {[]rideType{toRideBigInt(-5)}, false, toRideBigInt(5)}, + {[]rideType{toRideBigInt(math.MinInt64)}, false, rideBigInt{v: big.NewInt(0).Neg(big.NewInt(math.MinInt64))}}, + {[]rideType{rideBigInt{v: minBigInt}}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(5)}, true, nil}, + {[]rideType{rideUnit{}}, true, nil}, + {[]rideType{}, true, nil}, + {[]rideType{rideString("x")}, true, nil}, + } { + r, err := unaryMinusBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestGTBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(5), toRideBigInt(4)}, false, rideBoolean(true)}, + {[]rideType{toRideBigInt(16), toRideBigInt(2)}, false, rideBoolean(true)}, + {[]rideType{toRideBigInt(5), toRideBigInt(5)}, false, rideBoolean(false)}, + {[]rideType{toRideBigInt(1), toRideBigInt(5)}, false, rideBoolean(false)}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), toRideBigInt(3)}, true, nil}, + {[]rideType{toRideBigInt(1), rideInt(2)}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := gtBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestGEBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(15), toRideBigInt(5)}, false, rideBoolean(true)}, + {[]rideType{toRideBigInt(5), toRideBigInt(5)}, false, rideBoolean(true)}, + {[]rideType{toRideBigInt(1), toRideBigInt(5)}, false, rideBoolean(false)}, + {[]rideType{toRideBigInt(1), rideUnit{}}, true, nil}, + {[]rideType{toRideBigInt(1), toRideBigInt(2), toRideBigInt(3)}, true, nil}, + {[]rideType{toRideBigInt(1), rideInt(2)}, true, nil}, + {[]rideType{toRideBigInt(1), rideString("x")}, true, nil}, + {[]rideType{toRideBigInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := geBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestMaxListBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideList(toRideBigInt(1), toRideBigInt(2), toRideBigInt(3))}, false, toRideBigInt(3)}, + {[]rideType{toRideList(toRideBigInt(-1), toRideBigInt(-2), toRideBigInt(-3))}, false, toRideBigInt(-1)}, + {[]rideType{toRideList(toRideBigInt(0), toRideBigInt(0), toRideBigInt(0))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(toRideBigInt(0))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(rideBigInt{v: maxBigInt}, rideBigInt{v: minBigInt}, toRideBigInt(0), toRideBigInt(-10), toRideBigInt(10))}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{toRideList(toRideBigInt(0)), rideInt(1)}, true, nil}, + {[]rideType{toRideList()}, true, nil}, + {[]rideType{toRideBigInt(0)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := maxListBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestMinListBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideList(toRideBigInt(1), toRideBigInt(2), toRideBigInt(3))}, false, toRideBigInt(1)}, + {[]rideType{toRideList(toRideBigInt(-1), toRideBigInt(-2), toRideBigInt(-3))}, false, toRideBigInt(-3)}, + {[]rideType{toRideList(toRideBigInt(0), toRideBigInt(0), toRideBigInt(0))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(toRideBigInt(0))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(rideBigInt{v: maxBigInt}, rideBigInt{v: minBigInt}, toRideBigInt(0), toRideBigInt(-10), toRideBigInt(10))}, false, rideBigInt{v: minBigInt}}, + {[]rideType{toRideList(toRideBigInt(0)), rideInt(1)}, true, nil}, + {[]rideType{toRideList()}, true, nil}, + {[]rideType{toRideBigInt(0)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := minListBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestBigIntToBytes(t *testing.T) { + v, ok := big.NewInt(0).SetString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480", 10) + require.True(t, ok) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(-1)}, false, toRideBytes("ff")}, + {[]rideType{toRideBigInt(0)}, false, toRideBytes("00")}, + {[]rideType{toRideBigInt(1)}, false, toRideBytes("01")}, + {[]rideType{toRideBigInt(1234567890)}, false, toRideBytes("499602d2")}, + {[]rideType{toRideBigInt(-1234567890)}, false, toRideBytes("b669fd2e")}, + {[]rideType{rideBigInt{v: maxBigInt}}, false, toRideBytes("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}, + {[]rideType{rideBigInt{v: minBigInt}}, false, toRideBytes("80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}, + {[]rideType{toRideBigInt(math.MaxInt64)}, false, toRideBytes("7fffffffffffffff")}, + {[]rideType{toRideBigInt(math.MinInt64)}, false, toRideBytes("8000000000000000")}, + {[]rideType{rideBigInt{v: v}}, false, toRideBytes("0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40")}, + {[]rideType{toRideBigInt(0), rideInt(4)}, true, nil}, + {[]rideType{rideString("0")}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := bigIntToBytes(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBytesToBigInt(t *testing.T) { + v, ok := big.NewInt(0).SetString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480", 10) + require.True(t, ok) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBytes("ff")}, false, toRideBigInt(-1)}, + {[]rideType{toRideBytes("00")}, false, toRideBigInt(0)}, + {[]rideType{toRideBytes("01")}, false, toRideBigInt(1)}, + {[]rideType{toRideBytes("499602d2")}, false, toRideBigInt(1234567890)}, + {[]rideType{toRideBytes("b669fd2e")}, false, toRideBigInt(-1234567890)}, + {[]rideType{toRideBytes("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{toRideBytes("80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}, false, rideBigInt{v: minBigInt}}, + {[]rideType{toRideBytes("7fffffffffffffff")}, false, toRideBigInt(math.MaxInt64)}, + {[]rideType{toRideBytes("8000000000000000")}, false, toRideBigInt(math.MinInt64)}, + {[]rideType{toRideBytes("0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40")}, false, rideBigInt{v: v}}, + {[]rideType{toRideBytes("ff"), rideInt(4)}, true, nil}, + {[]rideType{rideString("0")}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := bytesToBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestBytesToBigIntLim(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBytes("cafebebeff"), rideInt(4), rideInt(1)}, false, toRideBigInt(-1)}, + {[]rideType{toRideBytes("cafebebeff"), rideInt(4), rideInt(4)}, false, toRideBigInt(-1)}, + {[]rideType{toRideBytes("00deadbeef"), rideInt(0), rideInt(1)}, false, toRideBigInt(0)}, + {[]rideType{toRideBytes("cafe01bebe"), rideInt(2), rideInt(1)}, false, toRideBigInt(1)}, + {[]rideType{toRideBytes("deadbeef499602d2"), rideInt(4), rideInt(4)}, false, toRideBigInt(1234567890)}, + {[]rideType{toRideBytes("deadbeefb669fd2e"), rideInt(4), rideInt(4)}, false, toRideBigInt(-1234567890)}, + {[]rideType{toRideBytes("cafebebe7fffffffffffffff"), rideInt(4), rideInt(8)}, false, toRideBigInt(math.MaxInt64)}, + {[]rideType{toRideBytes("8000000000000000cafebebe"), rideInt(0), rideInt(8)}, false, toRideBigInt(math.MinInt64)}, + {[]rideType{toRideBytes("deadbeef00"), rideInt(5), rideInt(1)}, true, nil}, + {[]rideType{toRideBytes("deadbeef00"), rideInt(4), rideInt(65)}, true, nil}, + {[]rideType{toRideBytes("deadbeef00"), rideInt(-1), rideInt(5)}, true, nil}, + {[]rideType{toRideBytes("deadbeef00"), rideInt(4), rideInt(0)}, true, nil}, + {[]rideType{toRideBytes("deadbeef00"), rideInt(4), rideInt(-1)}, true, nil}, + {[]rideType{toRideBytes("ff"), rideInt(4)}, true, nil}, + {[]rideType{rideString("0")}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := bytesToBigIntLim(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestBigIntToInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(-1)}, false, rideInt(-1)}, + {[]rideType{toRideBigInt(0)}, false, rideInt(0)}, + {[]rideType{toRideBigInt(1)}, false, rideInt(1)}, + {[]rideType{toRideBigInt(1234567890)}, false, rideInt(1234567890)}, + {[]rideType{toRideBigInt(-1234567890)}, false, rideInt(-1234567890)}, + {[]rideType{toRideBigInt(math.MaxInt64)}, false, rideInt(math.MaxInt64)}, + {[]rideType{toRideBigInt(math.MinInt64)}, false, rideInt(math.MinInt64)}, + {[]rideType{rideBigInt{v: maxBigInt}}, true, nil}, + {[]rideType{rideBigInt{v: minBigInt}}, true, nil}, + {[]rideType{toRideBigInt(0), rideInt(4)}, true, nil}, + {[]rideType{rideString("0")}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := bigIntToInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBigIntToString(t *testing.T) { + v, ok := big.NewInt(0).SetString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480", 10) + require.True(t, ok) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideBigInt(-1)}, false, rideString("-1")}, + {[]rideType{toRideBigInt(0)}, false, rideString("0")}, + {[]rideType{toRideBigInt(1)}, false, rideString("1")}, + {[]rideType{toRideBigInt(1234567890)}, false, rideString("1234567890")}, + {[]rideType{toRideBigInt(-1234567890)}, false, rideString("-1234567890")}, + {[]rideType{rideBigInt{v: maxBigInt}}, false, rideString("6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042047")}, + {[]rideType{rideBigInt{v: minBigInt}}, false, rideString("-6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048")}, + {[]rideType{toRideBigInt(math.MaxInt64)}, false, rideString("9223372036854775807")}, + {[]rideType{toRideBigInt(math.MinInt64)}, false, rideString("-9223372036854775808")}, + {[]rideType{rideBigInt{v: v}}, false, rideString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480")}, + {[]rideType{toRideBigInt(0), rideInt(4)}, true, nil}, + {[]rideType{rideString("0")}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := bigIntToString(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestStringToBigInt(t *testing.T) { + v, ok := big.NewInt(0).SetString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480", 10) + require.True(t, ok) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("-1")}, false, toRideBigInt(-1)}, + {[]rideType{rideString("0")}, false, toRideBigInt(0)}, + {[]rideType{rideString("1")}, false, toRideBigInt(1)}, + {[]rideType{rideString("1234567890")}, false, toRideBigInt(1234567890)}, + {[]rideType{rideString("-1234567890")}, false, toRideBigInt(-1234567890)}, + {[]rideType{rideString("6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042047")}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{rideString("-6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048")}, false, rideBigInt{v: minBigInt}}, + {[]rideType{rideString("9223372036854775807")}, false, toRideBigInt(math.MaxInt64)}, + {[]rideType{rideString("-9223372036854775808")}, false, toRideBigInt(math.MinInt64)}, + {[]rideType{rideString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480")}, false, rideBigInt{v: v}}, + {[]rideType{rideString("0"), rideInt(4)}, true, nil}, + {[]rideType{rideInt(0)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := stringToBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestStringToBigIntOpt(t *testing.T) { + v, ok := big.NewInt(0).SetString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480", 10) + require.True(t, ok) + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("-1")}, false, toRideBigInt(-1)}, + {[]rideType{rideString("0")}, false, toRideBigInt(0)}, + {[]rideType{rideString("1")}, false, toRideBigInt(1)}, + {[]rideType{rideString("1234567890")}, false, toRideBigInt(1234567890)}, + {[]rideType{rideString("-1234567890")}, false, toRideBigInt(-1234567890)}, + {[]rideType{rideString("6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042047")}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{rideString("-6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048")}, false, rideBigInt{v: minBigInt}}, + {[]rideType{rideString("9223372036854775807")}, false, toRideBigInt(math.MaxInt64)}, + {[]rideType{rideString("-9223372036854775808")}, false, toRideBigInt(math.MinInt64)}, + {[]rideType{rideString("52785833603464895924505196455835395749861094195642486808108138863402869537852026544579466671752822414281401856143643660416162921950916138504990605852480")}, false, rideBigInt{v: v}}, + {[]rideType{rideString("0"), rideInt(4)}, false, newUnit(nil)}, + {[]rideType{rideInt(0)}, false, newUnit(nil)}, + {[]rideType{}, false, newUnit(nil)}, + } { + r, err := stringToBigIntOpt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func TestMedianListBigInt(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{toRideList(toRideBigInt(1), toRideBigInt(2), toRideBigInt(3), toRideBigInt(4))}, false, toRideBigInt(3)}, + {[]rideType{toRideList(toRideBigInt(1), toRideBigInt(2), toRideBigInt(3), toRideBigInt(4), toRideBigInt(5))}, false, toRideBigInt(3)}, + {[]rideType{toRideList(toRideBigInt(-1), toRideBigInt(-2), toRideBigInt(-3))}, false, toRideBigInt(-2)}, + {[]rideType{toRideList(toRideBigInt(0), toRideBigInt(0), toRideBigInt(0))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(toRideBigInt(0), toRideBigInt(1), toRideBigInt(1), toRideBigInt(1), toRideBigInt(1), toRideBigInt(2), toRideBigInt(3))}, false, toRideBigInt(1)}, + {[]rideType{toRideList(rideBigInt{v: maxBigInt}, rideBigInt{v: minBigInt}, toRideBigInt(0), toRideBigInt(-10), toRideBigInt(10))}, false, toRideBigInt(0)}, + {[]rideType{toRideList(toRideBigInt(0))}, true, nil}, + {[]rideType{toRideList(toRideBigInt(0)), rideInt(1)}, true, nil}, + {[]rideType{toRideList()}, true, nil}, + {[]rideType{toRideBigInt(0)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := medianListBigInt(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.True(t, test.r.eq(r), fmt.Sprintf("%s != %s", test.r, r)) + } + } +} + +func toRideBigInt(i int) rideBigInt { + v := big.NewInt(int64(i)) + return rideBigInt{v: v} +} + +func toRideBytes(s string) rideBytes { + r, _ := hex.DecodeString(s) + return r +} + +func toRideList(args ...rideType) rideList { + return args +} diff --git a/pkg/ride/functions_int.go b/pkg/ride/functions_int.go index 36c4df4e5..81ba4c515 100644 --- a/pkg/ride/functions_int.go +++ b/pkg/ride/functions_int.go @@ -242,11 +242,11 @@ func roundingMode(v rideType) (decimal.RoundingMode, error) { return decimal.ToNearestEven, nil case "Down": return decimal.ToZero, nil - case "Up": + case "Up": // round-up v2-v4 return decimal.AwayFromZero, nil case "HalfUp": return decimal.ToNearestAway, nil - case "HalfDown": + case "HalfDown": // round-half-down v2-v4 return decimal.ToNearestTowardZero, nil default: return 0, errors.Errorf("unable to get rounding mode from '%s'", v.instanceOf()) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 9fe093ad5..40dd8f52f 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -166,18 +166,18 @@ func invoke(env Environment, args ...rideType) (rideType, error) { func hashScriptAtAddress(env Environment, args ...rideType) (rideType, error) { recipient, err := extractRecipient(args[0]) if err != nil { - return nil, errors.Errorf("hashScriptAtAddress func: unexpected argument type '%s'", args[0].instanceOf()) + return nil, errors.Errorf("hashScriptAtAddress: unexpected argument type '%s'", args[0].instanceOf()) } script, err := env.state().GetByteTree(recipient) if err != nil { - return nil, errors.Errorf("hashScriptAtAddress func: failed to get script by recipient, %v", err) + return nil, errors.Errorf("hashScriptAtAddress: failed to get script by recipient, %v", err) } if len(script) != 0 { hash, err := crypto.FastHash(script) if err != nil { - return nil, errors.Errorf("hashScriptAtAddress func: failed to get hash of script, %v", err) + return nil, errors.Errorf("hashScriptAtAddress: failed to get hash of script, %v", err) } return rideBytes(hash.Bytes()), nil } @@ -188,11 +188,11 @@ func hashScriptAtAddress(env Environment, args ...rideType) (rideType, error) { func isDataStorageUntouched(env Environment, args ...rideType) (rideType, error) { recipient, err := extractRecipient(args[0]) if err != nil { - return nil, errors.Errorf("isDataStorageUntouched func: unexpected argument type '%s'", args[0].instanceOf()) + return nil, errors.Errorf("isDataStorageUntouched: unexpected argument type '%s'", args[0].instanceOf()) } isUntouched, err := env.state().IsStateUntouched(recipient) if err != nil { - return nil, errors.Wrapf(err, "isDataStorageUntouched func") + return nil, errors.Wrapf(err, "isDataStorageUntouched") } return rideBoolean(isUntouched), nil } diff --git a/pkg/ride/functions_test.go b/pkg/ride/functions_test.go index 972d059e5..301ee3374 100644 --- a/pkg/ride/functions_test.go +++ b/pkg/ride/functions_test.go @@ -11,7 +11,7 @@ func TestNames(t *testing.T) { assert.Equal(t, "!", functionNameV2(0)) assert.Equal(t, "!=", functionNameV3(1)) assert.Equal(t, "wavesBalance", functionNameV2(67)) - assert.Equal(t, "DeleteEntry", functionNameV4(182)) + assert.Equal(t, "Down", functionNameV4(182)) } func TestCheckFunction(t *testing.T) { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 6fa06e263..6532d52dd 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -325,7 +325,6 @@ func functionsV4() map[string]string { m["1103"] = "indexOfList" m["1104"] = "lastIndexOfList" m["1209"] = "makeString" - m["1020"] = "invoke" for i, l := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} { m[strconv.Itoa(2400+i)] = fmt.Sprintf("bls12Groth16Verify_%d", l) } @@ -418,7 +417,6 @@ func catalogueV4() map[string]int { m["1207"] = 3 m["1208"] = 3 m["1209"] = 30 - m["1020"] = 1 // TODO write true value for i, c := range []int{1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600} { m[strconv.Itoa(2400+i)] = c } @@ -467,6 +465,30 @@ func catalogueV4() map[string]int { func functionsV5() map[string]string { m := functionsV4() + m["118"] = "powBigInt" + m["119"] = "logBigInt" + m["310"] = "toBigInt" + m["311"] = "sumBigInt" + m["312"] = "subtractBigInt" + m["313"] = "multiplyBigInt" + m["314"] = "divideBigInt" + m["315"] = "moduloBigInt" + m["316"] = "fractionBigInt" + m["317"] = "fractionBigIntRounds" + m["318"] = "unaryMinusBigInt" + m["319"] = "gtBigInt" + m["320"] = "geBigInt" + m["408"] = "maxListBigInt" + m["409"] = "minListBigInt" + m["413"] = "bigIntToBytes" + m["414"] = "bytesToBigInt" + m["415"] = "bytesToBigIntLim" + m["416"] = "bigIntToInt" + m["422"] = "bigIntToString" + m["423"] = "stringToBigInt" + m["424"] = "stringToBigIntOpt" + m["425"] = "medianListBigInt" + m["1020"] = "invoke" m["1081"] = "calculateLeaseID" m["1092"] = "simplifiedLease" m["1093"] = "fullLease" @@ -478,7 +500,31 @@ func functionsV5() map[string]string { func catalogueV5() map[string]int { m := catalogueV4() - m["1081"] = 1 //TODO: put actual value here + m["118"] = 200 + m["119"] = 200 + m["310"] = 1 + m["311"] = 8 + m["312"] = 8 + m["313"] = 64 + m["314"] = 64 + m["315"] = 64 + m["316"] = 128 + m["317"] = 128 + m["318"] = 8 + m["319"] = 8 + m["320"] = 8 + m["408"] = 192 + m["409"] = 192 + m["413"] = 65 + m["414"] = 65 + m["415"] = 65 + m["416"] = 1 + m["422"] = 65 + m["423"] = 65 + m["424"] = 65 + m["425"] = 160 + m["1020"] = 75 + m["1081"] = 1 m["1092"] = 1 m["1093"] = 1 m["LeaseCancel"] = 1 diff --git a/pkg/ride/math/math.go b/pkg/ride/math/math.go index c02d247f7..05db7816c 100644 --- a/pkg/ride/math/math.go +++ b/pkg/ride/math/math.go @@ -1,6 +1,8 @@ package math import ( + "math/big" + "github.com/ericlagergren/decimal" "github.com/ericlagergren/decimal/math" "github.com/pkg/errors" @@ -12,7 +14,17 @@ var ( ten = decimal.New(10, 0) ) -func convertToResult(v *decimal.Big, scale int, mode decimal.RoundingMode) (int64, error) { +func checkScales(baseScale, exponentScale, resultScale int) bool { + // 8 is the maximum scale for RIDE Int values + return baseScale >= 0 && baseScale <= 8 && exponentScale >= 0 && exponentScale <= 8 && resultScale >= 0 && resultScale <= 8 +} + +func checkScalesBigInt(baseScale, exponentScale, resultScale int) bool { + // 18 is the maximum scale for RIDE BigInt values + return baseScale >= 0 && baseScale <= 18 && exponentScale >= 0 && exponentScale <= 18 && resultScale >= 0 && resultScale <= 18 +} + +func convertToIntResult(v *decimal.Big, scale int, mode decimal.RoundingMode) (int64, error) { context := decimal.Context128 context.RoundingMode = mode r := decimal.WithContext(context).Set(v) @@ -27,31 +39,57 @@ func convertToResult(v *decimal.Big, scale int, mode decimal.RoundingMode) (int6 return res, nil } +func convertToBigIntResult(v *decimal.Big, scale int, mode decimal.RoundingMode) (*big.Int, error) { + if v.IsNaN(0) || v.IsInf(0) { + return nil, errors.New("result is NaN or Infinity") + } + context := decimal.Context128 + context.RoundingMode = mode + // r = v * 10^s + r := decimal.WithContext(context).Set(v) + s := decimal.WithContext(decimal.Context128).SetMantScale(int64(scale), 0) + m := decimal.WithContext(decimal.Context128) + math.Pow(m, ten, s) + r.Mul(r, m) + return r.RoundToInt().Int(nil), nil +} + +func pow(base, exponent *decimal.Big) (*decimal.Big, error) { + if base.IsInt() && exponent.Cmp(zero) == 0 { + return one, nil + } + r := decimal.WithContext(decimal.Context128) + r = math.Pow(r, base, exponent) + if r.Context.Err() != nil { + return nil, errors.New(r.Context.Conditions.Error()) + } + return r, nil +} + func Pow(base, exponent int64, baseScale, exponentScale, resultScale int, mode decimal.RoundingMode) (int64, error) { - if baseScale < 0 || baseScale > 8 || - exponentScale < 0 || exponentScale > 8 || - resultScale < 0 || resultScale > 8 { - return 0, errors.New("pow: invalid scale") + if !checkScales(baseScale, exponentScale, resultScale) { + return 0, errors.New("invalid scale") } b := decimal.WithContext(decimal.Context128).SetMantScale(base, baseScale) e := decimal.WithContext(decimal.Context128).SetMantScale(exponent, exponentScale) - if b.IsInt() && e.Cmp(zero) == 0 { - res, err := convertToResult(one, resultScale, mode) - if err != nil { - return 0, errors.Wrap(err, "pow") - } - return res, nil + r, err := pow(b, e) + if err != nil { + return 0, err } - r := decimal.WithContext(decimal.Context128) - r = math.Pow(r, b, e) - if r.Context.Err() != nil { - return 0, errors.Errorf("pow: %s", r.Context.Conditions.Error()) + return convertToIntResult(r, resultScale, mode) +} + +func PowBigInt(base, exponent *big.Int, baseScale, exponentScale, resultScale int, mode decimal.RoundingMode) (*big.Int, error) { + if !checkScalesBigInt(baseScale, exponentScale, resultScale) { + return nil, errors.New("invalid scale") } - res, err := convertToResult(r, resultScale, mode) + b := decimal.WithContext(decimal.Context128).SetBigMantScale(base, baseScale) + e := decimal.WithContext(decimal.Context128).SetBigMantScale(exponent, exponentScale) + r, err := pow(b, e) if err != nil { - return 0, errors.Wrap(err, "pow") + return nil, err } - return res, nil + return convertToBigIntResult(r, resultScale, mode) } func Fraction(value, numerator, denominator int64) (int64, error) { @@ -64,48 +102,63 @@ func Fraction(value, numerator, denominator int64) (int64, error) { if err := v.Context.Err(); err != nil { return 0, errors.Wrap(err, "Fraction") } - res, err := convertToResult(v, 0, decimal.ToZero) + res, err := convertToIntResult(v, 0, decimal.ToZero) if err != nil { return 0, errors.Wrap(err, "Fraction") } return res, nil } -func Log(base, exponent int64, baseScale, exponentScale, resultScale int, mode decimal.RoundingMode) (int64, error) { - if baseScale < 0 || baseScale > 8 || - exponentScale < 0 || exponentScale > 8 || - resultScale < 0 || resultScale > 8 { - return 0, errors.New("log: invalid scale") - } - b := decimal.WithContext(decimal.Context128).SetMantScale(base, baseScale) - e := decimal.WithContext(decimal.Context128).SetMantScale(exponent, exponentScale) +func log(base, exponent *decimal.Big, resultScale int) (*decimal.Big, error) { r := decimal.WithContext(decimal.Context128).SetMantScale(0, resultScale) bl := decimal.WithContext(decimal.Context128) - math.Log(bl, b) + math.Log(bl, base) if bl.Context.Err() != nil { - return 0, errors.New(bl.Context.Conditions.Error()) + return nil, errors.New(bl.Context.Conditions.Error()) } el := decimal.WithContext(decimal.Context128) - math.Log(el, e) + math.Log(el, exponent) if el.Context.Err() != nil { - return 0, errors.New(el.Context.Conditions.Error()) + return nil, errors.New(el.Context.Conditions.Error()) } r.Quo(bl, el) if r.Context.Err() != nil { - return 0, errors.New(r.Context.Conditions.Error()) + return nil, errors.New(r.Context.Conditions.Error()) } - res, err := convertToResult(r, resultScale, mode) + return r, nil +} + +func Log(base, exponent int64, baseScale, exponentScale, resultScale int, mode decimal.RoundingMode) (int64, error) { + if !checkScales(baseScale, exponentScale, resultScale) { + return 0, errors.New("invalid scale") + } + b := decimal.WithContext(decimal.Context128).SetMantScale(base, baseScale) + e := decimal.WithContext(decimal.Context128).SetMantScale(exponent, exponentScale) + r, err := log(b, e, resultScale) if err != nil { - return 0, errors.Wrap(err, "log") + return 0, err } - return res, nil + return convertToIntResult(r, resultScale, mode) +} + +func LogBigInt(base, exponent *big.Int, baseScale, exponentScale, resultScale int, mode decimal.RoundingMode) (*big.Int, error) { + if !checkScalesBigInt(baseScale, exponentScale, resultScale) { + return nil, errors.New("invalid scale") + } + b := decimal.WithContext(decimal.Context128).SetBigMantScale(base, baseScale) + e := decimal.WithContext(decimal.Context128).SetBigMantScale(exponent, exponentScale) + r, err := log(b, e, resultScale) + if err != nil { + return nil, err + } + return convertToBigIntResult(r, resultScale, mode) } -func ModDivision(x int64, y int64) int64 { +func ModDivision(x, y int64) int64 { return x - FloorDiv(x, y)*y } -func FloorDiv(x int64, y int64) int64 { +func FloorDiv(x, y int64) int64 { r := x / y // if the signs are different and modulo not zero, round down if (x^y) < 0 && (r*y != x) { @@ -113,3 +166,34 @@ func FloorDiv(x int64, y int64) int64 { } return r } + +func FloorDivBigInt(x, y *big.Int) *big.Int { + var r *big.Int + if x.Sign() == y.Sign() { + if x.Cmp(y) < 0 { + // abs(y-x)/2 + x + r = y.Sub(y, x) + r = r.Abs(r) + r = r.Div(r, big.NewInt(2)) + r = r.Add(r, x) + return r + } + // abs(x-y)/2 + y + r = x.Sub(x, y) + r = r.Abs(r) + r = r.Div(r, big.NewInt(2)) + r = r.Add(r, y) + return r + } + d := x.Add(x, y) + two := big.NewInt(2) + zero := big.NewInt(0) + d2 := big.NewInt(0).Mod(d, two) + if d.Cmp(zero) >= 0 || d2.Cmp(zero) == 0 { + r = d.Div(d, two) + return r + } + r = d.Sub(d, big.NewInt(1)) + r = r.Div(r, two) + return r +} diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index 8cd4016ec..4806e86e2 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -2,6 +2,7 @@ package ride import ( "bytes" + "math/big" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/proto" @@ -72,6 +73,30 @@ func (l rideInt) get(prop string) (rideType, error) { return nil, errors.Errorf("type '%s' has no property '%s'", l.instanceOf(), prop) } +type rideBigInt struct { + v *big.Int +} + +func (l rideBigInt) instanceOf() string { + return "BigInt" +} + +func (l rideBigInt) eq(other rideType) bool { + if o, ok := other.(rideBigInt); ok { + return l.v.Cmp(o.v) == 0 + } + return false +} + +func (l rideBigInt) get(prop string) (rideType, error) { + //TODO: there is possibility of few properties like 'bytes', 'int' and so on + return nil, errors.Errorf("type '%s' has no property '%s'", l.instanceOf(), prop) +} + +func (l rideBigInt) String() string { + return l.v.String() +} + type rideString string func (s rideString) instanceOf() string { diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index e5bb4c367..34790251a 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -50,6 +50,7 @@ func TestSimpleScriptEvaluation(t *testing.T) { {`V3: let b = base16'0000000000000001'; func add(v: ByteVector) = toInt(b) + 1; add(b) == 2`, "AwQAAAABYgEAAAAIAAAAAAAAAAEKAQAAAANhZGQAAAABAAAAAXYJAABkAAAAAgkABLEAAAABBQAAAAFiAAAAAAAAAAABCQAAAAAAAAIJAQAAAANhZGQAAAABBQAAAAFiAAAAAAAAAAAChRvwnQ==", nil, true}, {`V3: let data = base64'AAAAAAABhqAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWyt9GyysOW84u/u5V5Ah/SzLfef4c28UqXxowxFZS4SLiC6+XBh8D7aJDXyTTjpkPPED06ZPOzUE23V6VYCsLw=='; func getStock(data:ByteVector) = toInt(take(drop(data, 8), 8)); getStock(data) == 1`, `AwQAAAAEZGF0YQEAAABwAAAAAAABhqAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWyt9GyysOW84u/u5V5Ah/SzLfef4c28UqXxowxFZS4SLiC6+XBh8D7aJDXyTTjpkPPED06ZPOzUE23V6VYCsLwoBAAAACGdldFN0b2NrAAAAAQAAAARkYXRhCQAEsQAAAAEJAADJAAAAAgkAAMoAAAACBQAAAARkYXRhAAAAAAAAAAAIAAAAAAAAAAAICQAAAAAAAAIJAQAAAAhnZXRTdG9jawAAAAEFAAAABGRhdGEAAAAAAAAAAAFCtabi`, nil, true}, {`V3: let ref = 999; func g(a: Int) = ref; func f(ref: Int) = g(ref); f(1) == 999`, "AwQAAAADcmVmAAAAAAAAAAPnCgEAAAABZwAAAAEAAAABYQUAAAADcmVmCgEAAAABZgAAAAEAAAADcmVmCQEAAAABZwAAAAEFAAAAA3JlZgkAAAAAAAACCQEAAAABZgAAAAEAAAAAAAAAAAEAAAAAAAAAA+fjknmW", nil, true}, + {`V4: let ref = 999; func f(ref: Int) = {let a = ref; ref }; f(1) == 999`, "BAQAAAADcmVmAAAAAAAAAAPnCgEAAAABZgAAAAEAAAADcmVmBAAAAAFhBQAAAANyZWYFAAAAA3JlZgkAAAAAAAACCQEAAAABZgAAAAEAAAAAAAAAAAEAAAAAAAAAA+eeAF6w", nil, false}, {`let x = 5; 6 > 4`, `AQQAAAABeAAAAAAAAAAABQkAAGYAAAACAAAAAAAAAAAGAAAAAAAAAAAEYSW6XA==`, nil, true}, {`let x = 5; 6 > x`, `AQQAAAABeAAAAAAAAAAABQkAAGYAAAACAAAAAAAAAAAGBQAAAAF4Gh24hw==`, nil, true}, {`let x = 5; 6 >= x`, `AQQAAAABeAAAAAAAAAAABQkAAGcAAAACAAAAAAAAAAAGBQAAAAF4jlxXHA==`, nil, true}, From c480f5530d6c671d208f040429cc4727c4141b63 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 6 Apr 2021 11:07:20 +0300 Subject: [PATCH 23/52] Deleted two ride functions from v5 (#446) * Deleted two ride functions from v5 * Correct case for removed function names Co-authored-by: Alexey Kiselev --- pkg/keyvalue/leveldb_test.go | 3 ++- pkg/ride/constants.go | 12 ++++++------ pkg/ride/generate/main.go | 7 ++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pkg/keyvalue/leveldb_test.go b/pkg/keyvalue/leveldb_test.go index 7f54baf94..4bcab79d5 100644 --- a/pkg/keyvalue/leveldb_test.go +++ b/pkg/keyvalue/leveldb_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -17,7 +18,7 @@ const ( func TestKeyVal(t *testing.T) { dbDir, err := ioutil.TempDir(os.TempDir(), "dbDir0") - assert.NoError(t, err) + require.NoError(t, err) params := KeyValParams{ CacheParams: CacheParams{cacheSize}, BloomFilterParams: BloomFilterParams{n, falsePositiveProbability, NoOpStore{}, false}, diff --git a/pkg/ride/constants.go b/pkg/ride/constants.go index 78321617e..df678c154 100644 --- a/pkg/ride/constants.go +++ b/pkg/ride/constants.go @@ -90,21 +90,21 @@ func checkConstantV4(name string) (uint16, bool) { return 0, false } -var ConstantsV5 = []string{"Buy", "CEILING", "DOWN", "FLOOR", "HALFDOWN", "HALFEVEN", "HALFUP", "MD5", "NOALG", "SHA1", "SHA224", "SHA256", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHA384", "SHA512", "Sell", "UP", "height", "lastBlock", "nil", "this", "tx", "unit"} +var ConstantsV5 = []string{"Buy", "CEILING", "DOWN", "FLOOR", "HALFEVEN", "HALFUP", "MD5", "NOALG", "SHA1", "SHA224", "SHA256", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHA384", "SHA512", "Sell", "height", "lastBlock", "nil", "this", "tx", "unit"} -const _constants_V5 = "BuyCEILINGDOWNFLOORHALFDOWNHALFEVENHALFUPMD5NOALGSHA1SHA224SHA256SHA3224SHA3256SHA3384SHA3512SHA384SHA512SellUPheightlastBlocknilthistxunit" +const _constants_V5 = "BuyCEILINGDOWNFLOORHALFEVENHALFUPMD5NOALGSHA1SHA224SHA256SHA3224SHA3256SHA3384SHA3512SHA384SHA512SellheightlastBlocknilthistxunit" -var _constructors_V5 = [...]rideConstructor{newBuy, newCeiling, newDown, newFloor, newHalfDown, newHalfEven, newHalfUp, newMd5, newNoAlg, newSha1, newSha224, newSha256, newSha3224, newSha3256, newSha3384, newSha3512, newSha384, newSha512, newSell, newUp, newHeight, newLastBlock, newNil, newThis, newTx, newUnit} -var _c_index_V5 = [...]int{0, 3, 10, 14, 19, 27, 35, 41, 44, 49, 53, 59, 65, 72, 79, 86, 93, 99, 105, 109, 111, 117, 126, 129, 133, 135, 139} +var _constructors_V5 = [...]rideConstructor{newBuy, newCeiling, newDown, newFloor, newHalfEven, newHalfUp, newMd5, newNoAlg, newSha1, newSha224, newSha256, newSha3224, newSha3256, newSha3384, newSha3512, newSha384, newSha512, newSell, newHeight, newLastBlock, newNil, newThis, newTx, newUnit} +var _c_index_V5 = [...]int{0, 3, 10, 14, 19, 27, 33, 36, 41, 45, 51, 57, 64, 71, 78, 85, 91, 97, 101, 107, 116, 119, 123, 125, 129} func constantV5(id int) rideConstructor { - if id < 0 || id > 25 { + if id < 0 || id > 23 { return nil } return _constructors_V5[id] } func checkConstantV5(name string) (uint16, bool) { - for i := 0; i <= 25; i++ { + for i := 0; i <= 23; i++ { if _constants_V5[_c_index_V5[i]:_c_index_V5[i+1]] == name { return uint16(i), true } diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 6532d52dd..4ab540d01 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -530,6 +530,8 @@ func catalogueV5() map[string]int { m["LeaseCancel"] = 1 m["1054"] = 10 m["1009"] = 200 + delete(m, "Up") + delete(m, "HalfDown") return m } @@ -587,7 +589,10 @@ func constantsV4() map[string]constantDescription { } func constantsV5() map[string]constantDescription { - return constantsV4() + c := constantsV4() + delete(c, "UP") + delete(c, "HALFDOWN") + return c } func constructorsFromConstants(m map[string]string, c map[string]constantDescription) { From 54d6591767d3ae4070bf952f65ddf3368a064758 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 6 Apr 2021 11:29:57 +0300 Subject: [PATCH 24/52] Added other block complexity in case if RideV5 is activated (#447) * Added other block complexity in case if RideV5 is activated * Fixed style * Variables of limit were wrapped into one * Correct name for the new feature, method renamed. Co-authored-by: Alexey Kiselev --- pkg/miner/constraints.go | 8 ++++++-- pkg/miner/miner.go | 24 +++++++++++++++--------- pkg/settings/features.go | 8 ++++---- pkg/state/appender.go | 10 +++++++--- pkg/state/constraints.go | 17 +++++++++++++++++ pkg/state/invoke_applier_test.go | 4 ++-- pkg/state/state.go | 10 ++++------ pkg/state/transaction_checker.go | 2 +- 8 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 pkg/state/constraints.go diff --git a/pkg/miner/constraints.go b/pkg/miner/constraints.go index 7ad54e94c..2e55f1197 100644 --- a/pkg/miner/constraints.go +++ b/pkg/miner/constraints.go @@ -1,8 +1,12 @@ package miner +import ( + "github.com/wavesplatform/gowaves/pkg/state" +) + type Constraints struct { MaxScriptRunsInBlock int - MaxScriptsComplexityInBlock int + MaxScriptsComplexityInBlock state.MaxScriptsComplexityInBlock ClassicAmountOfTxsInBlock int MaxTxsSizeInBytes int } @@ -10,7 +14,7 @@ type Constraints struct { func DefaultConstraints() Constraints { return Constraints{ MaxScriptRunsInBlock: 100, - MaxScriptsComplexityInBlock: 1000000, + MaxScriptsComplexityInBlock: state.NewMaxScriptsComplexityInBlock(), ClassicAmountOfTxsInBlock: 100, MaxTxsSizeInBytes: 1 * 1024 * 1024, // 1mb } diff --git a/pkg/miner/miner.go b/pkg/miner/miner.go index bf8d9687a..a99de4913 100644 --- a/pkg/miner/miner.go +++ b/pkg/miner/miner.go @@ -2,7 +2,7 @@ package miner import ( "context" - + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/miner/scheduler" "github.com/wavesplatform/gowaves/pkg/node/messages" "github.com/wavesplatform/gowaves/pkg/node/peer_manager" @@ -15,13 +15,12 @@ import ( ) type MicroblockMiner struct { - utx types.UtxPool - state state.State - peer peer_manager.PeerManager - constraints Constraints - services services.Services - features Features - // reward vote 600000000 + utx types.UtxPool + state state.State + peer peer_manager.PeerManager + constraints Constraints + services services.Services + features Features reward int64 maxTransactionTimeForwardOffset proto.Timestamp } @@ -71,12 +70,19 @@ func (a *MicroblockMiner) MineKeyBlock(ctx context.Context, t proto.Timestamp, k return nil, proto.MiningLimits{}, err } b := bi.(*proto.Block) + + activated, err := a.state.IsActivated(int16(settings.RideV5)) + if err != nil { + return nil, proto.MiningLimits{}, errors.Wrapf(err, "failed to check if feature %d is activated", settings.RideV5) + } + rest := proto.MiningLimits{ MaxScriptRunsInBlock: a.constraints.MaxScriptRunsInBlock, - MaxScriptsComplexityInBlock: a.constraints.MaxScriptsComplexityInBlock, + MaxScriptsComplexityInBlock: a.constraints.MaxScriptsComplexityInBlock.GetMaxScriptsComplexityInBlock(activated), ClassicAmountOfTxsInBlock: a.constraints.ClassicAmountOfTxsInBlock, MaxTxsSizeInBytes: a.constraints.MaxTxsSizeInBytes - 4, } + return b, rest, nil } diff --git a/pkg/settings/features.go b/pkg/settings/features.go index a80e872c2..d31ff9702 100644 --- a/pkg/settings/features.go +++ b/pkg/settings/features.go @@ -16,9 +16,9 @@ const ( Ride4DApps // RIDE V3 OrderV3 ReduceNFTFee - BlockReward // 14 - BlockV5 // 15 - ContinuationTransaction // 16 + BlockReward // 14 + BlockV5 // 15 + RideV5 // 16 LeaseExpiration ) @@ -43,6 +43,6 @@ var FeaturesInfo = map[Feature]FeatureInfo{ ReduceNFTFee: {true, "Reduce NFT fee"}, BlockReward: {true, "Block Reward and Community Driven Monetary Policy"}, BlockV5: {true, "Ride V4, VRF, Protobuf, Failed transactions"}, - ContinuationTransaction: {true, "Continuation Transaction"}, + RideV5: {true, "Ride V5, dApp-to-dApp invocations"}, LeaseExpiration: {false, "Lease Expiration"}, } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 9433e1729..99a18462a 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -251,9 +251,13 @@ func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { return err } if ride4DAppsActivated { - // TODO: fix estimator and return error here instead of warning. - if a.sc.getTotalComplexity() > maxScriptsComplexityInBlock { - zap.S().Warn("complexity limit per block is exceeded") + rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return errors.Wrapf(err, "failed to check if feature %d is activated", settings.RideV5) + } + maxBlockComplexity := NewMaxScriptsComplexityInBlock().GetMaxScriptsComplexityInBlock(rideV5Activated) + if a.sc.getTotalComplexity() > uint64(maxBlockComplexity) { + return errors.New("complexity limit per block is exceeded") } return nil } else if smartAccountsActivated { diff --git a/pkg/state/constraints.go b/pkg/state/constraints.go new file mode 100644 index 000000000..15b51b755 --- /dev/null +++ b/pkg/state/constraints.go @@ -0,0 +1,17 @@ +package state + +type MaxScriptsComplexityInBlock struct { + BeforeRideV5 int + AfterRideV5 int +} + +func NewMaxScriptsComplexityInBlock() MaxScriptsComplexityInBlock { + return MaxScriptsComplexityInBlock{BeforeRideV5: 1000000, AfterRideV5: 2500000} +} + +func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRiveV5Activated bool) int { + if isRiveV5Activated { + return a.AfterRideV5 + } + return a.BeforeRideV5 +} diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index ae7cccaca..f800a3083 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -779,7 +779,7 @@ func cancel(id: ByteVector) = ([LeaseCancel(id)], unit) func TestApplyInvokeScriptWithLease(t *testing.T) { to, path := createInvokeApplierTestObjects(t) - to.activateFeature(t, int16(settings.ContinuationTransaction)) + to.activateFeature(t, int16(settings.RideV5)) defer func() { err := to.state.Close() @@ -826,7 +826,7 @@ func TestApplyInvokeScriptWithLease(t *testing.T) { func TestApplyInvokeScriptWithLeaseAndLeaseCancel(t *testing.T) { to, path := createInvokeApplierTestObjects(t) - to.activateFeature(t, int16(settings.ContinuationTransaction)) + to.activateFeature(t, int16(settings.RideV5)) defer func() { err := to.state.Close() diff --git a/pkg/state/state.go b/pkg/state/state.go index 229d58e88..dfbfd48e0 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -24,12 +24,10 @@ import ( ) const ( - rollbackMaxBlocks = 2000 - blocksStorDir = "blocks_storage" - keyvalueDir = "key_value" - - maxScriptsRunsInBlock = 101 - maxScriptsComplexityInBlock = 1000000 + rollbackMaxBlocks = 2000 + blocksStorDir = "blocks_storage" + keyvalueDir = "key_value" + maxScriptsRunsInBlock = 101 ) var empty struct{} diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 0d81f63fa..fed821045 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -68,7 +68,7 @@ func (tc *transactionChecker) scriptActivation(libVersion int, hasBlockV2 bool) if err != nil { return err } - continuationActivated, err := tc.stor.features.newestIsActivated(int16(settings.ContinuationTransaction)) + continuationActivated, err := tc.stor.features.newestIsActivated(int16(settings.RideV5)) if err != nil { return err } From 1a9af47d8be4ce0d8a129103c2f597a2dc7515ed Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 13 Apr 2021 08:53:38 +0300 Subject: [PATCH 25/52] Added new limit of payments after activation RideV5 (#453) --- pkg/state/transaction_checker.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index fed821045..56ccc3b1b 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -1064,12 +1064,18 @@ func (tc *transactionChecker) checkInvokeScriptWithProofs(transaction proto.Tran if err != nil { return nil, err } + rideV5activated, err := tc.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return nil, err + } l := len(tx.Payments) switch { - case l > 1 && !multiPaymentActivated: + case l > 1 && !multiPaymentActivated && !rideV5activated: return nil, errors.New("no more than one payment is allowed") - case l > 2 && multiPaymentActivated: + case l > 2 && multiPaymentActivated && !rideV5activated: return nil, errors.New("no more than two payments is allowed") + case l > 10 && rideV5activated: + return nil, errors.New("no more than ten payments is allowed since RideV5 activation") } var paymentAssets []proto.OptionalAsset for _, payment := range tx.Payments { From 453fd1148e17ac0b8d5f679861a0d8648cb7bc95 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 13 Apr 2021 10:58:26 +0300 Subject: [PATCH 26/52] Changed actions limit and limit of transactions for libVersion V5 (#449) * Changed actions limit and limit of transactions for libVersion V5 * Deleted an useless variable * Fixed style --- pkg/proto/scripting.go | 43 ++++++++++++------- pkg/proto/scripting_test.go | 2 +- pkg/proto/types.go | 58 +++++++++++++++---------- pkg/ride/environment.go | 74 ++++++++++++++++++++++++++------ pkg/state/constraints.go | 14 +++--- pkg/state/invoke_applier.go | 3 +- pkg/state/transaction_checker.go | 4 +- 7 files changed, 137 insertions(+), 61 deletions(-) diff --git a/pkg/proto/scripting.go b/pkg/proto/scripting.go index eae9f1ac1..b93eed2f5 100644 --- a/pkg/proto/scripting.go +++ b/pkg/proto/scripting.go @@ -428,7 +428,12 @@ type ActionsValidationRestrictions struct { Scheme byte } -func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestrictions) error { +func getMaxScriptActions(libVersion int) int { + maxScriptActionInstance := NewMaxScriptActions() + return maxScriptActionInstance.GetMaxScriptsComplexityInBlock(libVersion) +} + +func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestrictions, libVersion int) error { dataEntriesCount := 0 dataEntriesSize := 0 otherActionsCount := 0 @@ -456,8 +461,10 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *TransferScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.Amount < 0 { return errors.New("negative transfer amount") @@ -478,8 +485,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *IssueScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") @@ -496,8 +504,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *ReissueScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") @@ -505,8 +514,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *BurnScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.Quantity < 0 { return errors.New("negative quantity") @@ -514,8 +524,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *SponsorshipScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.MinFee < 0 { return errors.New("negative minimal fee") @@ -523,8 +534,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *LeaseScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } if ta.Amount < 0 { return errors.New("negative leasing amount") @@ -543,8 +555,9 @@ func ValidateActions(actions []ScriptAction, restrictions ActionsValidationRestr case *LeaseCancelScriptAction: otherActionsCount++ - if otherActionsCount > MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", MaxScriptActions) + maxScriptActions := getMaxScriptActions(libVersion) + if otherActionsCount > maxScriptActions { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptActions) } default: diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index 9935a7c85..f3924b0fd 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -231,7 +231,7 @@ func TestActionsValidation(t *testing.T) { &LeaseScriptAction{Recipient: rcp0, Amount: -100}, }, restrictions: ActionsValidationRestrictions{}, valid: false}, } { - err := ValidateActions(test.actions, test.restrictions) + err := ValidateActions(test.actions, test.restrictions, 5) if test.valid { require.NoError(t, err, fmt.Sprintf("#%d", i)) } else { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index efb7921c1..a09b7fee1 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -25,32 +25,46 @@ import ( const ( //WavesAssetName is the default name for basic WAVES asset. - WavesAssetName = "WAVES" - quotedWavesAssetName = "\"" + WavesAssetName + "\"" - orderLen = crypto.PublicKeySize + crypto.PublicKeySize + 1 + 1 + 1 + 8 + 8 + 8 + 8 + 8 - orderV2FixedBodyLen = 1 + orderLen - orderV3FixedBodyLen = 1 + orderLen + 1 - orderV1MinLen = crypto.SignatureSize + orderLen - orderV2MinLen = orderV2FixedBodyLen + proofsMinLen - orderV3MinLen = orderV3FixedBodyLen + proofsMinLen - jsonNull = "null" - integerArgumentLen = 1 + 8 - booleanArgumentLen = 1 - binaryArgumentMinLen = 1 + 4 - stringArgumentMinLen = 1 + 4 - listArgumentMinLen = 1 + 4 - PriceConstant = 100000000 - MaxOrderAmount = 100 * PriceConstant * PriceConstant - MaxOrderTTL = uint64((30 * 24 * time.Hour) / time.Millisecond) - MaxKeySize = 100 - MaxPBKeySize = 400 - maxValueSize = 32767 - - MaxScriptActions = 10 + WavesAssetName = "WAVES" + quotedWavesAssetName = "\"" + WavesAssetName + "\"" + orderLen = crypto.PublicKeySize + crypto.PublicKeySize + 1 + 1 + 1 + 8 + 8 + 8 + 8 + 8 + orderV2FixedBodyLen = 1 + orderLen + orderV3FixedBodyLen = 1 + orderLen + 1 + orderV1MinLen = crypto.SignatureSize + orderLen + orderV2MinLen = orderV2FixedBodyLen + proofsMinLen + orderV3MinLen = orderV3FixedBodyLen + proofsMinLen + jsonNull = "null" + integerArgumentLen = 1 + 8 + booleanArgumentLen = 1 + binaryArgumentMinLen = 1 + 4 + stringArgumentMinLen = 1 + 4 + listArgumentMinLen = 1 + 4 + PriceConstant = 100000000 + MaxOrderAmount = 100 * PriceConstant * PriceConstant + MaxOrderTTL = uint64((30 * 24 * time.Hour) / time.Millisecond) + MaxKeySize = 100 + MaxPBKeySize = 400 + maxValueSize = 32767 MaxDataEntryScriptActions = 100 MaxDataEntryScriptActionsSizeInBytes = 5 * 1024 ) +type MaxScriptActions struct { + BeforeRideScriptV5 int + AfterRideScriptV5 int +} + +func NewMaxScriptActions() MaxScriptActions { + return MaxScriptActions{BeforeRideScriptV5: 10, AfterRideScriptV5: 30} +} + +func (a MaxScriptActions) GetMaxScriptsComplexityInBlock(scriptVersion int) int { + if scriptVersion > 5 { + return a.AfterRideScriptV5 + } + return a.BeforeRideScriptV5 +} + type Timestamp = uint64 type Score = big.Int type Scheme = byte diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index e464a77ad..741d76c89 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -358,6 +358,11 @@ func (ws *WrappedState) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Sc return ws.diff.state.NewestScriptByAsset(asset) } +func (ws *WrappedState) newMaxScriptComplexity(scriptVersion int) int { + maxScriptActions := proto.NewMaxScriptActions() + return maxScriptActions.GetMaxScriptsComplexityInBlock(scriptVersion) +} + func (ws *WrappedState) validateAsset(action proto.ScriptAction, asset proto.OptionalAsset, env Environment) (bool, error) { if !asset.Present { return true, nil @@ -455,9 +460,14 @@ func (ws *WrappedState) validateTransferAction(otherActionsCount *int, res *prot if !assetResult { return errors.New("action is forbidden by smart asset script") } + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.Amount < 0 { return errors.New("negative transfer amount") @@ -514,8 +524,14 @@ func (ws *WrappedState) validateDataEntryAction(dataEntriesCount *int, dataEntri func (ws *WrappedState) validateIssueAction(otherActionsCount *int, res *proto.IssueScriptAction) error { *otherActionsCount++ - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.Quantity < 0 { return errors.New("negative quantity") @@ -544,8 +560,14 @@ func (ws *WrappedState) validateReissueAction(otherActionsCount *int, res *proto return errors.New("action is forbidden by smart asset script") } - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.Quantity < 0 { return errors.New("negative quantity") @@ -575,8 +597,14 @@ func (ws *WrappedState) validateBurnAction(otherActionsCount *int, res *proto.Bu return errors.New("action is forbidden by smart asset script") } - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.Quantity < 0 { return errors.New("negative quantity") @@ -595,8 +623,14 @@ func (ws *WrappedState) validateBurnAction(otherActionsCount *int, res *proto.Bu func (ws *WrappedState) validateSponsorshipAction(otherActionsCount *int, res *proto.SponsorshipScriptAction) error { *otherActionsCount++ - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.MinFee < 0 { return errors.New("negative minimal fee") @@ -607,8 +641,14 @@ func (ws *WrappedState) validateSponsorshipAction(otherActionsCount *int, res *p func (ws *WrappedState) validateLeaseAction(otherActionsCount *int, res *proto.LeaseScriptAction, restrictions proto.ActionsValidationRestrictions) error { *otherActionsCount++ - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } if res.Amount < 0 { return errors.New("negative leasing amount") @@ -637,8 +677,14 @@ func (ws *WrappedState) validateLeaseAction(otherActionsCount *int, res *proto.L func (ws *WrappedState) validateLeaseCancelAction(otherActionsCount *int) error { *otherActionsCount++ - if *otherActionsCount > proto.MaxScriptActions { - return errors.Errorf("number of actions produced by script is more than allowed %d", proto.MaxScriptActions) + scriptVersion, err := ws.getLibVersion() + if err != nil { + return err + } + maxScriptAction := ws.newMaxScriptComplexity(scriptVersion) + + if *otherActionsCount > maxScriptAction { + return errors.Errorf("number of actions produced by script is more than allowed %d", maxScriptAction) } return nil } diff --git a/pkg/state/constraints.go b/pkg/state/constraints.go index 15b51b755..edbaf2d7c 100644 --- a/pkg/state/constraints.go +++ b/pkg/state/constraints.go @@ -1,17 +1,17 @@ package state type MaxScriptsComplexityInBlock struct { - BeforeRideV5 int - AfterRideV5 int + BeforeActivationRideV5Feature int + AfterActivationRideV5Feature int } func NewMaxScriptsComplexityInBlock() MaxScriptsComplexityInBlock { - return MaxScriptsComplexityInBlock{BeforeRideV5: 1000000, AfterRideV5: 2500000} + return MaxScriptsComplexityInBlock{BeforeActivationRideV5Feature: 1000000, AfterActivationRideV5Feature: 2500000} } -func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRiveV5Activated bool) int { - if isRiveV5Activated { - return a.AfterRideV5 +func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRideV5Activated bool) int { + if isRideV5Activated { + return a.AfterActivationRideV5Feature } - return a.BeforeRideV5 + return a.BeforeActivationRideV5Feature } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 0be60d151..15860a705 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -301,7 +301,8 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in DisableSelfTransfers: info.disableSelfTransfers, KeySizeValidationVersion: keySizeValidationVersion, } - if err := proto.ValidateActions(info.actions, restrictions); err != nil { + + if err := proto.ValidateActions(info.actions, restrictions, int(info.libVersion)); err != nil { return proto.DAppError, info.failedChanges, err } // Check full transaction fee (with actions and payments scripts). diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 56ccc3b1b..fe496c521 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -92,8 +92,10 @@ func (tc *transactionChecker) checkScriptComplexity(tree *ride.Tree, estimation switch tree.LibVersion { case 1, 2: maxComplexity = 2000 - case 3, 4, 5: + case 3, 4: maxComplexity = 4000 + case 5: + maxComplexity = 26000 } complexity := estimation.Verifier if tree.IsDApp() { From 41d9c3db94bf5db6e08f1f0cc964feb272689144 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 15 Apr 2021 11:20:30 +0300 Subject: [PATCH 27/52] Seed peers on all networks were moved to port 6868. Stype fixed. Typo fixed. (#454) --- cmd/node/node.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 7f7e013da..d7145bd48 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -59,7 +59,7 @@ var ( apiKey = flag.String("api-key", "", "Api key") grpcAddr = flag.String("grpc-address", "127.0.0.1:7475", "Address for gRPC API") enableGrpcApi = flag.Bool("enable-grpc-api", true, "Enables/disables gRPC API") - buildExtendedApi = flag.Bool("build-extended-api", false, "Builds extended API. Note that state must be reimported in case it wasn't imported with similar flag set") + buildExtendedApi = flag.Bool("build-extended-api", false, "Builds extended API. Note that state must be re-imported in case it wasn't imported with similar flag set") serveExtendedApi = flag.Bool("serve-extended-api", false, "Serves extended API requests since the very beginning. The default behavior is to import until first block close to current time, and start serving at this point") buildStateHashes = flag.Bool("build-state-hashes", false, "Calculate and store state hashes for each block height.") bindAddress = flag.String("bind-address", "", "Bind address for incoming connections. If empty, will be same as declared address") @@ -87,8 +87,8 @@ var ( var defaultPeers = map[string]string{ "mainnet": "34.253.153.4:6868,168.119.116.189:6868,135.181.87.72:6868,35.158.218.156:6868,52.48.34.89:6868", - "testnet": "159.69.126.149:6863,94.130.105.239:6863,159.69.126.153:6863,94.130.172.201:6863", - "stagenet": "88.99.185.128:6862,49.12.15.166:6862,95.216.205.3:6862,88.198.179.16:6862", + "testnet": "159.69.126.149:6868,94.130.105.239:6868,159.69.126.153:6868,94.130.172.201:6868", + "stagenet": "88.99.185.128:6868,49.12.15.166:6868,95.216.205.3:6868,88.198.179.16:6868", } type Scheduler interface { @@ -367,8 +367,8 @@ func main() { if *prometheus != "" { h := http.NewServeMux() h.Handle("/metrics", promhttp.Handler()) - server := &http.Server{Addr: *prometheus, Handler: h} - _ = server.ListenAndServe() + s := &http.Server{Addr: *prometheus, Handler: h} + _ = s.ListenAndServe() } }() From ec1dafaf04e0fef5aaf23a92214c22eba4e33d2e Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Fri, 16 Apr 2021 10:53:37 +0300 Subject: [PATCH 28/52] Added free verifier (#450) * Added free verifier * fixed tests * Get complexity from store instead of double estimation * Moved save of complexity * Deleted extra fee for smart asset script since RideV5 (#452) * Deleted extra fee for smart asset script since RideV5 * Fixed style * Changed fee to zero for smart asset script since rideV5 * Moved check fee * Fixed style --- pkg/state/constraints.go | 2 + pkg/state/fee_validation.go | 42 ++++++++++++++----- pkg/state/fee_validation_test.go | 72 ++++++++++++++++---------------- pkg/state/transaction_checker.go | 17 +++++++- 4 files changed, 85 insertions(+), 48 deletions(-) diff --git a/pkg/state/constraints.go b/pkg/state/constraints.go index edbaf2d7c..1403845fe 100644 --- a/pkg/state/constraints.go +++ b/pkg/state/constraints.go @@ -15,3 +15,5 @@ func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRideV5Acti } return a.BeforeActivationRideV5Feature } + +const FreeVerifierComplexity = 200 diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index f85f57eff..be6f4f122 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -2,7 +2,6 @@ package state import ( "fmt" - "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -141,9 +140,17 @@ type txCosts struct { total uint64 } -func newTxCosts(smartAssets, smartAccounts uint64) *txCosts { +func newTxCosts(smartAssets, smartAccounts uint64, isRideV5Activated bool, complexity int, isAccountScripted bool) *txCosts { smartAssetsFee := smartAssets * scriptExtraFee smartAccountsFee := smartAccounts * scriptExtraFee + + if isRideV5Activated { + smartAssetsFee = 0 // since RideV5 we have to erase extra fee for smart asset scripts + } + + if isAccountScripted && isRideV5Activated && complexity <= FreeVerifierComplexity { + smartAccountsFee = 0 + } return &txCosts{ smartAssets: smartAssets, smartAssetsFee: smartAssetsFee, @@ -168,7 +175,7 @@ func (tc *txCosts) toString() string { return str } -func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, error) { +func scriptsCost(tx proto.Transaction, params *feeValidationParams, isRideV5Activated bool, estimatorVersion int) (*txCosts, error) { smartAssets := uint64(len(params.txAssets.smartAssets)) senderAddr, err := proto.NewAddressFromPublicKey(params.settings.AddressSchemeCharacter, tx.GetSenderPK()) if err != nil { @@ -178,6 +185,21 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, e if err != nil { return nil, err } + + // check complexity of script for free verifier if complexity <= 200 + complexity := 0 + if accountScripted && isRideV5Activated { + + treeEstimation, err := params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, estimatorVersion, !params.initialisation) + if err != nil { + return nil, errors.Errorf("failed to get complexity by addr from store, %v", err) + } + if treeEstimation == nil { + return nil, errors.Errorf("failed to get complexity by addr from store: estimation tree is empty") + } + complexity = treeEstimation.Verifier + } + smartAccounts := uint64(0) if accountScripted { smartAccounts = 1 @@ -193,16 +215,16 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, e smartAssets += 1 } } - return newTxCosts(smartAssets, smartAccounts), nil + return newTxCosts(smartAssets, smartAccounts, isRideV5Activated, complexity, accountScripted), nil } -func minFeeInWaves(tx proto.Transaction, params *feeValidationParams) (*txCosts, error) { +func minFeeInWaves(tx proto.Transaction, params *feeValidationParams, isRideV5Activated bool, estimatorVersion int) (*txCosts, error) { feeInUnits, err := minFeeInUnits(params, tx) if err != nil { return nil, err } minFee := feeInUnits * FeeUnit - cost, err := scriptsCost(tx, params) + cost, err := scriptsCost(tx, params, isRideV5Activated, estimatorVersion) if err != nil { return nil, err } @@ -210,8 +232,8 @@ func minFeeInWaves(tx proto.Transaction, params *feeValidationParams) (*txCosts, return cost, nil } -func checkMinFeeWaves(tx proto.Transaction, params *feeValidationParams) error { - minWaves, err := minFeeInWaves(tx, params) +func checkMinFeeWaves(tx proto.Transaction, params *feeValidationParams, isRideV5Activated bool, estimatorVersion int) error { + minWaves, err := minFeeInWaves(tx, params, isRideV5Activated, estimatorVersion) if err != nil { return errors.Errorf("failed to calculate min fee in Waves: %v\n", err) } @@ -223,7 +245,7 @@ func checkMinFeeWaves(tx proto.Transaction, params *feeValidationParams) error { return nil } -func checkMinFeeAsset(tx proto.Transaction, feeAssetID crypto.Digest, params *feeValidationParams) error { +func checkMinFeeAsset(tx proto.Transaction, feeAssetID crypto.Digest, params *feeValidationParams, isRideV5Activated bool, estimatorVersion int) error { isSponsored, err := params.stor.sponsoredAssets.newestIsSponsored(feeAssetID, !params.initialisation) if err != nil { return errors.Errorf("newestIsSponsored: %v", err) @@ -231,7 +253,7 @@ func checkMinFeeAsset(tx proto.Transaction, feeAssetID crypto.Digest, params *fe if !isSponsored { return errs.NewTxValidationError(fmt.Sprintf("Asset %s is not sponsored, cannot be used to pay fees", feeAssetID.String())) } - minWaves, err := minFeeInWaves(tx, params) + minWaves, err := minFeeInWaves(tx, params, isRideV5Activated, estimatorVersion) if err != nil { return errors.Errorf("failed to calculate min fee in Waves: %v\n", err) } diff --git a/pkg/state/fee_validation_test.go b/pkg/state/fee_validation_test.go index f8d0c1dc7..7039bc722 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -41,11 +41,11 @@ func TestAssetScriptExtraFee(t *testing.T) { initialisation: false, txAssets: &txAssets{feeAsset: proto.OptionalAsset{Present: false}, smartAssets: []crypto.Digest{tx.AssetID}}, } - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) // it doesn't matter for these tests what version estimator is assert.Error(t, err, "checkMinFeeWaves() did not fail with invalid Burn fee") // One more extra fee for asset script must be added. tx.Fee += scriptExtraFee - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeWaves() failed with valid Burn fee") } @@ -75,10 +75,10 @@ func TestAccountScriptExtraFee(t *testing.T) { initialisation: false, txAssets: &txAssets{feeAsset: proto.OptionalAsset{Present: false}}, } - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) assert.Error(t, err, "checkMinFeeWaves() did not fail with invalid Burn fee") tx.Fee += scriptExtraFee - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeWaves() failed with valid Burn fee") } @@ -101,11 +101,11 @@ func TestCheckMinFeeWaves(t *testing.T) { initialisation: false, txAssets: &txAssets{feeAsset: proto.OptionalAsset{Present: false}}, } - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeWaves() failed with valid Burn fee") tx.Fee = 1 - err = checkMinFeeWaves(tx, params) + err = checkMinFeeWaves(tx, params, false, maxEstimatorVersion) assert.Error(t, err, "checkMinFeeWaves() did not fail with invalid Burn fee") // MassTransfer special case. @@ -113,21 +113,21 @@ func TestCheckMinFeeWaves(t *testing.T) { entries := generateMassTransferEntries(t, entriesNum) tx1 := createMassTransferWithProofs(t, entries) tx1.Fee = FeeUnit * 34 - err = checkMinFeeWaves(tx1, params) + err = checkMinFeeWaves(tx1, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeWaves() failed with valid MassTransfer fee") tx1.Fee -= 1 - err = checkMinFeeWaves(tx1, params) + err = checkMinFeeWaves(tx1, params, false, maxEstimatorVersion) assert.Error(t, err, "checkMinFeeWaves did not fail with invalid MassTransfer fee") // Data transaction special case. tx2 := createDataWithProofs(t, 100) tx2.Fee = FeeUnit * 2 - err = checkMinFeeWaves(tx2, params) + err = checkMinFeeWaves(tx2, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeWaves() failed with valid Data transaction fee") tx2.Fee -= 1 - err = checkMinFeeWaves(tx2, params) + err = checkMinFeeWaves(tx2, params, false, maxEstimatorVersion) assert.Error(t, err, "checkMinFeeWaves() did not fail with invalid Data transaction fee") } @@ -157,11 +157,11 @@ func TestCheckMinFeeAsset(t *testing.T) { to.stor.flush(t) tx.Fee = 1 * assetCost - err = checkMinFeeAsset(tx, tx.FeeAsset.ID, params) + err = checkMinFeeAsset(tx, tx.FeeAsset.ID, params, false, maxEstimatorVersion) assert.NoError(t, err, "checkMinFeeAsset() failed with valid Transfer transaction fee in asset") tx.Fee -= 1 - err = checkMinFeeAsset(tx, tx.FeeAsset.ID, params) + err = checkMinFeeAsset(tx, tx.FeeAsset.ID, params, false, maxEstimatorVersion) assert.Error(t, err, "checkMinFeeAsset() did not fail with invalid Transfer transaction fee in asset") } @@ -189,23 +189,23 @@ func TestNFTMinFee(t *testing.T) { nftA1 := createNFTIssueWithSig(t) nftA2 := createNFTIssueWithProofs(t) - require.Error(t, checkMinFeeWaves(issueA1, params)) - require.Error(t, checkMinFeeWaves(issueA2, params)) - require.NoError(t, checkMinFeeWaves(issueB1, params)) - require.NoError(t, checkMinFeeWaves(issueB2, params)) + require.Error(t, checkMinFeeWaves(issueA1, params, false, maxEstimatorVersion)) + require.Error(t, checkMinFeeWaves(issueA2, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(issueB1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(issueB2, params, false, maxEstimatorVersion)) - require.Error(t, checkMinFeeWaves(nftA1, params)) - require.Error(t, checkMinFeeWaves(nftA2, params)) + require.Error(t, checkMinFeeWaves(nftA1, params, false, maxEstimatorVersion)) + require.Error(t, checkMinFeeWaves(nftA2, params, false, maxEstimatorVersion)) storage.activateFeature(t, int16(settings.ReduceNFTFee)) - require.Error(t, checkMinFeeWaves(issueA1, params)) - require.Error(t, checkMinFeeWaves(issueA2, params)) - require.NoError(t, checkMinFeeWaves(issueB1, params)) - require.NoError(t, checkMinFeeWaves(issueB2, params)) + require.Error(t, checkMinFeeWaves(issueA1, params, false, maxEstimatorVersion)) + require.Error(t, checkMinFeeWaves(issueA2, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(issueB1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(issueB2, params, false, maxEstimatorVersion)) - require.NoError(t, checkMinFeeWaves(nftA1, params)) - require.NoError(t, checkMinFeeWaves(nftA2, params)) + require.NoError(t, checkMinFeeWaves(nftA1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(nftA2, params, false, maxEstimatorVersion)) } func TestReissueFeeReduction(t *testing.T) { @@ -230,17 +230,17 @@ func TestReissueFeeReduction(t *testing.T) { reissueB1 := createReissueWithSig(t, 1000) reissueB2 := createReissueWithProofs(t, 1000) - require.Error(t, checkMinFeeWaves(reissueA1, params)) - require.Error(t, checkMinFeeWaves(reissueA2, params)) - require.NoError(t, checkMinFeeWaves(reissueB1, params)) - require.NoError(t, checkMinFeeWaves(reissueB2, params)) + require.Error(t, checkMinFeeWaves(reissueA1, params, false, maxEstimatorVersion)) + require.Error(t, checkMinFeeWaves(reissueA2, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(reissueB1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(reissueB2, params, false, maxEstimatorVersion)) storage.activateFeature(t, int16(settings.BlockV5)) - require.NoError(t, checkMinFeeWaves(reissueA1, params)) - require.NoError(t, checkMinFeeWaves(reissueA2, params)) - require.NoError(t, checkMinFeeWaves(reissueB1, params)) - require.NoError(t, checkMinFeeWaves(reissueB2, params)) + require.NoError(t, checkMinFeeWaves(reissueA1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(reissueA2, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(reissueB1, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(reissueB2, params, false, maxEstimatorVersion)) } func TestSponsorshipFeeReduction(t *testing.T) { @@ -263,11 +263,11 @@ func TestSponsorshipFeeReduction(t *testing.T) { sponsorshipA := createSponsorshipWithProofs(t, 1) sponsorshipB := createSponsorshipWithProofs(t, 1000) - require.Error(t, checkMinFeeWaves(sponsorshipA, params)) - require.NoError(t, checkMinFeeWaves(sponsorshipB, params)) + require.Error(t, checkMinFeeWaves(sponsorshipA, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(sponsorshipB, params, false, maxEstimatorVersion)) storage.activateFeature(t, int16(settings.BlockV5)) - require.NoError(t, checkMinFeeWaves(sponsorshipA, params)) - require.NoError(t, checkMinFeeWaves(sponsorshipB, params)) + require.NoError(t, checkMinFeeWaves(sponsorshipA, params, false, maxEstimatorVersion)) + require.NoError(t, checkMinFeeWaves(sponsorshipB, params, false, maxEstimatorVersion)) } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index fe496c521..04a04383e 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -161,11 +161,16 @@ func (tc *transactionChecker) checkFee( initialisation: info.initialisation, txAssets: assets, } + + isRideV5Activated, err := tc.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return errors.Errorf("failed to check if feature is was activated, %v", err) + } if !assets.feeAsset.Present { // Waves. - return checkMinFeeWaves(tx, params) + return checkMinFeeWaves(tx, params, isRideV5Activated, info.estimatorVersion()) } - return checkMinFeeAsset(tx, assets.feeAsset.ID, params) + return checkMinFeeAsset(tx, assets.feeAsset.ID, params, isRideV5Activated, info.estimatorVersion()) } func (tc *transactionChecker) checkFromFuture(timestamp uint64) bool { @@ -394,6 +399,7 @@ func (tc *transactionChecker) checkIssueWithProofs(transaction proto.Transaction if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, estimations, info.blockID); err != nil { return nil, err } + return nil, nil } @@ -527,6 +533,7 @@ func (tc *transactionChecker) checkBurnWithProofs(transaction proto.Transaction, if err != nil { return nil, err } + assets := &txAssets{feeAsset: proto.OptionalAsset{Present: false}, smartAssets: smartAssets} if err := tc.checkFee(transaction, assets, info); err != nil { return nil, err @@ -980,9 +987,11 @@ func (tc *transactionChecker) checkSetScriptWithProofs(transaction proto.Transac return nil, errs.Extend(err, "invalid timestamp") } assets := &txAssets{feeAsset: proto.OptionalAsset{Present: false}} + if err := tc.checkFee(transaction, assets, info); err != nil { return nil, err } + addr, err := proto.NewAddressFromPublicKey(tc.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -1002,6 +1011,7 @@ func (tc *transactionChecker) checkSetScriptWithProofs(transaction proto.Transac if err := tc.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, info.blockID); err != nil { return nil, err } + return nil, nil } @@ -1023,9 +1033,11 @@ func (tc *transactionChecker) checkSetAssetScriptWithProofs(transaction proto.Tr if err := tc.checkFee(transaction, assets, info); err != nil { return nil, errs.Extend(err, "check fee") } + if !bytes.Equal(assetInfo.issuer[:], tx.SenderPK[:]) { return nil, errs.NewAssetIssuedByOtherAddress("asset was issued by other address") } + isSmartAsset := tc.stor.scriptsStorage.newestIsSmartAsset(tx.AssetID, !info.initialisation) if len(tx.Script) == 0 { return nil, errs.NewTxValidationError("Cannot set empty script") @@ -1041,6 +1053,7 @@ func (tc *transactionChecker) checkSetAssetScriptWithProofs(transaction proto.Tr if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimations, info.blockID); err != nil { return nil, errs.Extend(err, "saveComplexityForAsset") } + return smartAssets, nil } From 5cf6e74193c7cc22e539f157263f19d0595938ba Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Wed, 21 Apr 2021 10:35:32 +0300 Subject: [PATCH 29/52] Filter parameter of state functions is always set to true then called from RIDE scripts (#456) --- pkg/mock/grpc.go | 16 +++++------ pkg/ride/diff_state.go | 2 +- pkg/ride/environment.go | 36 ++++++++++++------------ pkg/ride/functions_proto.go | 2 +- pkg/ride/tree_evaluation_test.go | 42 ++++++++++++++-------------- pkg/ride/types_moq_test.go | 47 ++++++++++++-------------------- pkg/state/state.go | 43 +++++++++++++++++++++++------ pkg/types/types.go | 5 ++-- 8 files changed, 104 insertions(+), 89 deletions(-) diff --git a/pkg/mock/grpc.go b/pkg/mock/grpc.go index a6b002add..90bcbd523 100644 --- a/pkg/mock/grpc.go +++ b/pkg/mock/grpc.go @@ -7,10 +7,10 @@ package mock import ( context "context" gomock "github.com/golang/mock/gomock" - empty "github.com/golang/protobuf/ptypes/empty" - wrappers "github.com/golang/protobuf/ptypes/wrappers" waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" grpc "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/node/grpc" + emptypb "google.golang.org/protobuf/types/known/emptypb" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" ) @@ -95,10 +95,10 @@ func (mr *MockGrpcHandlersMockRecorder) GetDataEntries(arg0, arg1 interface{}) * } // ResolveAlias mocks base method -func (m *MockGrpcHandlers) ResolveAlias(arg0 context.Context, arg1 *wrappers.StringValue) (*wrappers.BytesValue, error) { +func (m *MockGrpcHandlers) ResolveAlias(arg0 context.Context, arg1 *wrapperspb.StringValue) (*wrapperspb.BytesValue, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ResolveAlias", arg0, arg1) - ret0, _ := ret[0].(*wrappers.BytesValue) + ret0, _ := ret[0].(*wrapperspb.BytesValue) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -154,7 +154,7 @@ func (mr *MockGrpcHandlersMockRecorder) GetActivationStatus(arg0, arg1 interface } // GetBaseTarget mocks base method -func (m *MockGrpcHandlers) GetBaseTarget(arg0 context.Context, arg1 *empty.Empty) (*grpc.BaseTargetResponse, error) { +func (m *MockGrpcHandlers) GetBaseTarget(arg0 context.Context, arg1 *emptypb.Empty) (*grpc.BaseTargetResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetBaseTarget", arg0, arg1) ret0, _ := ret[0].(*grpc.BaseTargetResponse) @@ -169,7 +169,7 @@ func (mr *MockGrpcHandlersMockRecorder) GetBaseTarget(arg0, arg1 interface{}) *g } // GetCumulativeScore mocks base method -func (m *MockGrpcHandlers) GetCumulativeScore(arg0 context.Context, arg1 *empty.Empty) (*grpc.ScoreResponse, error) { +func (m *MockGrpcHandlers) GetCumulativeScore(arg0 context.Context, arg1 *emptypb.Empty) (*grpc.ScoreResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetCumulativeScore", arg0, arg1) ret0, _ := ret[0].(*grpc.ScoreResponse) @@ -213,10 +213,10 @@ func (mr *MockGrpcHandlersMockRecorder) GetBlockRange(arg0, arg1 interface{}) *g } // GetCurrentHeight mocks base method -func (m *MockGrpcHandlers) GetCurrentHeight(arg0 context.Context, arg1 *empty.Empty) (*wrappers.UInt32Value, error) { +func (m *MockGrpcHandlers) GetCurrentHeight(arg0 context.Context, arg1 *emptypb.Empty) (*wrapperspb.UInt32Value, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetCurrentHeight", arg0, arg1) - ret0, _ := ret[0].(*wrappers.UInt32Value) + ret0, _ := ret[0].(*wrapperspb.UInt32Value) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/pkg/ride/diff_state.go b/pkg/ride/diff_state.go index 887fda3db..0d8831132 100644 --- a/pkg/ride/diff_state.go +++ b/pkg/ride/diff_state.go @@ -196,7 +196,7 @@ func (diffSt *diffState) findLeaseByIDForCancel(leaseID crypto.Digest) (*lease, if lease, ok := diffSt.leases[leaseID.String()]; ok { return &lease, nil } - leaseFromStore, err := diffSt.state.NewestLeasingInfo(leaseID, false) + leaseFromStore, err := diffSt.state.NewestLeasingInfo(leaseID) if err != nil { return nil, err } diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 741d76c89..521ba774b 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -59,12 +59,12 @@ func (ws *WrappedState) AddingBlockHeight() (uint64, error) { return ws.diff.state.AddingBlockHeight() } -func (ws *WrappedState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { - return ws.diff.state.NewestLeasingInfo(id, filter) +func (ws *WrappedState) NewestLeasingInfo(id crypto.Digest) (*proto.LeaseInfo, error) { + return ws.diff.state.NewestLeasingInfo(id) } -func (ws *WrappedState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return ws.diff.state.NewestScriptPKByAddr(addr, filter) +func (ws *WrappedState) NewestScriptPKByAddr(addr proto.Address) (crypto.PublicKey, error) { + return ws.diff.state.NewestScriptPKByAddr(addr) } func (ws *WrappedState) NewestTransactionByID(id []byte) (proto.Transaction, error) { return ws.diff.state.NewestTransactionByID(id) @@ -247,7 +247,7 @@ func (ws *WrappedState) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo return assetFromStore, nil } - issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer) if err != nil { return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") } @@ -297,7 +297,7 @@ func (ws *WrappedState) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullA return assetFromStore, nil } - issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer, false) + issuerPK, err := ws.NewestScriptPKByAddr(searchNewAsset.dAppIssuer) if err != nil { return nil, errors.Wrap(err, "failed to get issuerPK from address in NewestAssetInfo") } @@ -741,7 +741,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.IntegerDataEntry: addr := ws.callee() - senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -753,7 +753,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.StringDataEntry: addr := ws.callee() - senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -765,7 +765,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.BooleanDataEntry: addr := ws.callee() - senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -777,7 +777,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.BinaryDataEntry: addr := ws.callee() - senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -789,7 +789,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.DeleteDataEntry: addr := ws.callee() - senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr, false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(addr) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -813,7 +813,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme return nil, errors.Wrap(err, "failed to get address by public key") } } else { - pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -849,7 +849,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme } case *proto.SponsorshipScriptAction: - senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -883,7 +883,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme ws.diff.newAssetsInfo[res.ID.String()] = assetInfo - senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -901,7 +901,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme } case *proto.ReissueScriptAction: - senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -928,7 +928,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme ws.diff.reissueNewAsset(res.AssetID, res.Quantity, res.Reissuable) case *proto.BurnScriptAction: - senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + senderPK, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -956,7 +956,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme case *proto.LeaseScriptAction: senderAddress := ws.callee() - pk, err := ws.diff.state.NewestScriptPKByAddr(senderAddress, false) + pk, err := ws.diff.state.NewestScriptPKByAddr(senderAddress) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } @@ -991,7 +991,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme ws.diff.addNewLease(res.Recipient, senderAccount, res.Amount, res.ID) case *proto.LeaseCancelScriptAction: - pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee(), false) + pk, err := ws.diff.state.NewestScriptPKByAddr(ws.callee()) if err != nil { return nil, errors.Wrap(err, "failed to get public key by address") } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 40dd8f52f..72520197c 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -75,7 +75,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { } invocationParam["caller"] = callerAddress - callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(callerAddress), false) + callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(callerAddress)) if err != nil { return nil, errors.Wrapf(err, "failed to get caller public key by address") } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 34790251a..46ce0dc61 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -826,7 +826,7 @@ var addressCallablePK crypto.PublicKey func smartStateDappFromDapp() types.SmartState { return &MockSmartState{ - NewestLeasingInfoFunc: func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { + NewestLeasingInfoFunc: func(id crypto.Digest) (*proto.LeaseInfo, error) { return nil, nil }, GetByteTreeFunc: func(recipient proto.Recipient) (proto.Script, error) { @@ -867,7 +867,7 @@ func smartStateDappFromDapp() types.SmartState { AddingBlockHeightFunc: func() (uint64, error) { return 10, nil }, - NewestScriptPKByAddrFunc: func(address proto.Address, filter bool) (crypto.PublicKey, error) { + NewestScriptPKByAddrFunc: func(address proto.Address) (crypto.PublicKey, error) { // payments test if address.String() == "3P8eZVKS7a4troGckytxaefLAi9w7P5aMna" { return crypto.NewPublicKeyFromBase58("FztxsodUc9V7iVzodkGumnZFtHnNTxYSETZfxBFAw9R3") @@ -1153,13 +1153,13 @@ func TestInvokeDAppFromDAppAllActions(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -1388,7 +1388,7 @@ func TestInvokeDAppFromDAppScript1(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) arguments := proto.Arguments{} @@ -1534,13 +1534,13 @@ func TestInvokeDAppFromDAppScript2(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -1721,13 +1721,13 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -1910,13 +1910,13 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -2097,13 +2097,13 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -2458,12 +2458,12 @@ func TestInvokeDAppFromDAppPayments(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -2635,12 +2635,12 @@ func TestInvokeDAppFromDAppOriginalCallerAndAlias(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3MsCoDnBbgzjQ7BgGk9xcruM6JVZ5jF8YCV") // new require.NoError(t, err) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) @@ -2831,13 +2831,13 @@ func TestInvokeDAppFromDAppNilResult(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) recipientCallable := proto.NewRecipientFromAddress(addressCallable) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} @@ -3015,12 +3015,12 @@ func TestInvokeDAppFromDAppSmartAssetValidation(t *testing.T) { addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) - addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) require.NoError(t, err) addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index 80507f886..f139bee20 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -4,10 +4,11 @@ package ride import ( + "sync" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/types" - "sync" ) // Ensure, that MockSmartState does implement types.SmartState. @@ -59,7 +60,7 @@ var _ types.SmartState = &MockSmartState{} // NewestHeaderByHeightFunc: func(height uint64) (*proto.BlockHeader, error) { // panic("mock out the NewestHeaderByHeight method") // }, -// NewestLeasingInfoFunc: func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { +// NewestLeasingInfoFunc: func(id crypto.Digest) (*proto.LeaseInfo, error) { // panic("mock out the NewestLeasingInfo method") // }, // NewestRecipientToAddressFunc: func(recipient proto.Recipient) (*proto.Address, error) { @@ -68,7 +69,7 @@ var _ types.SmartState = &MockSmartState{} // NewestScriptByAssetFunc: func(asset proto.OptionalAsset) (proto.Script, error) { // panic("mock out the NewestScriptByAsset method") // }, -// NewestScriptPKByAddrFunc: func(addr proto.Address, filter bool) (crypto.PublicKey, error) { +// NewestScriptPKByAddrFunc: func(addr proto.Address) (crypto.PublicKey, error) { // panic("mock out the NewestScriptPKByAddr method") // }, // NewestTransactionByIDFunc: func(in1 []byte) (proto.Transaction, error) { @@ -136,7 +137,7 @@ type MockSmartState struct { NewestHeaderByHeightFunc func(height uint64) (*proto.BlockHeader, error) // NewestLeasingInfoFunc mocks the NewestLeasingInfo method. - NewestLeasingInfoFunc func(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) + NewestLeasingInfoFunc func(id crypto.Digest) (*proto.LeaseInfo, error) // NewestRecipientToAddressFunc mocks the NewestRecipientToAddress method. NewestRecipientToAddressFunc func(recipient proto.Recipient) (*proto.Address, error) @@ -145,7 +146,7 @@ type MockSmartState struct { NewestScriptByAssetFunc func(asset proto.OptionalAsset) (proto.Script, error) // NewestScriptPKByAddrFunc mocks the NewestScriptPKByAddr method. - NewestScriptPKByAddrFunc func(addr proto.Address, filter bool) (crypto.PublicKey, error) + NewestScriptPKByAddrFunc func(addr proto.Address) (crypto.PublicKey, error) // NewestTransactionByIDFunc mocks the NewestTransactionByID method. NewestTransactionByIDFunc func(in1 []byte) (proto.Transaction, error) @@ -236,8 +237,6 @@ type MockSmartState struct { NewestLeasingInfo []struct { // ID is the id argument value. ID crypto.Digest - // Filter is the filter argument value. - Filter bool } // NewestRecipientToAddress holds details about calls to the NewestRecipientToAddress method. NewestRecipientToAddress []struct { @@ -253,8 +252,6 @@ type MockSmartState struct { NewestScriptPKByAddr []struct { // Addr is the addr argument value. Addr proto.Address - // Filter is the filter argument value. - Filter bool } // NewestTransactionByID holds details about calls to the NewestTransactionByID method. NewestTransactionByID []struct { @@ -722,33 +719,29 @@ func (mock *MockSmartState) NewestHeaderByHeightCalls() []struct { } // NewestLeasingInfo calls NewestLeasingInfoFunc. -func (mock *MockSmartState) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { +func (mock *MockSmartState) NewestLeasingInfo(id crypto.Digest) (*proto.LeaseInfo, error) { if mock.NewestLeasingInfoFunc == nil { panic("MockSmartState.NewestLeasingInfoFunc: method is nil but SmartState.NewestLeasingInfo was just called") } callInfo := struct { - ID crypto.Digest - Filter bool + ID crypto.Digest }{ - ID: id, - Filter: filter, + ID: id, } mock.lockNewestLeasingInfo.Lock() mock.calls.NewestLeasingInfo = append(mock.calls.NewestLeasingInfo, callInfo) mock.lockNewestLeasingInfo.Unlock() - return mock.NewestLeasingInfoFunc(id, filter) + return mock.NewestLeasingInfoFunc(id) } // NewestLeasingInfoCalls gets all the calls that were made to NewestLeasingInfo. // Check the length with: // len(mockedSmartState.NewestLeasingInfoCalls()) func (mock *MockSmartState) NewestLeasingInfoCalls() []struct { - ID crypto.Digest - Filter bool + ID crypto.Digest } { var calls []struct { - ID crypto.Digest - Filter bool + ID crypto.Digest } mock.lockNewestLeasingInfo.RLock() calls = mock.calls.NewestLeasingInfo @@ -819,33 +812,29 @@ func (mock *MockSmartState) NewestScriptByAssetCalls() []struct { } // NewestScriptPKByAddr calls NewestScriptPKByAddrFunc. -func (mock *MockSmartState) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { +func (mock *MockSmartState) NewestScriptPKByAddr(addr proto.Address) (crypto.PublicKey, error) { if mock.NewestScriptPKByAddrFunc == nil { panic("MockSmartState.NewestScriptPKByAddrFunc: method is nil but SmartState.NewestScriptPKByAddr was just called") } callInfo := struct { - Addr proto.Address - Filter bool + Addr proto.Address }{ - Addr: addr, - Filter: filter, + Addr: addr, } mock.lockNewestScriptPKByAddr.Lock() mock.calls.NewestScriptPKByAddr = append(mock.calls.NewestScriptPKByAddr, callInfo) mock.lockNewestScriptPKByAddr.Unlock() - return mock.NewestScriptPKByAddrFunc(addr, filter) + return mock.NewestScriptPKByAddrFunc(addr) } // NewestScriptPKByAddrCalls gets all the calls that were made to NewestScriptPKByAddr. // Check the length with: // len(mockedSmartState.NewestScriptPKByAddrCalls()) func (mock *MockSmartState) NewestScriptPKByAddrCalls() []struct { - Addr proto.Address - Filter bool + Addr proto.Address } { var calls []struct { - Addr proto.Address - Filter bool + Addr proto.Address } mock.lockNewestScriptPKByAddr.RLock() calls = mock.calls.NewestScriptPKByAddr diff --git a/pkg/state/state.go b/pkg/state/state.go index dfbfd48e0..4edca50b5 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -467,9 +467,11 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc } func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment if recipient.Address != nil { key := accountScriptKey{*recipient.Address} - script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), false) + script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), true) if err != nil { return nil, errors.Wrapf(err, "failed to get script by address") } @@ -481,7 +483,7 @@ func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, err return nil, errors.Wrapf(err, "failed to get address by alias") } key := accountScriptKey{address} - script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), false) + script, err := s.stor.scriptsStorage.newestScriptBytesByKey(key.bytes(), true) if err != nil { return nil, errors.Wrapf(err, "failed to get script by address") } @@ -491,8 +493,9 @@ func (s *stateManager) GetByteTree(recipient proto.Recipient) (proto.Script, err } func (s *stateManager) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) { - return s.stor.scriptsStorage.newestScriptBytesByAsset(asset.ID, false) - + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment + return s.stor.scriptsStorage.newestScriptBytesByAsset(asset.ID, true) } func (s *stateManager) Mutex() *lock.RwMutex { @@ -681,8 +684,10 @@ func (s *stateManager) BlockByHeight(height uint64) (*proto.Block, error) { return s.Block(blockID) } -func (s *stateManager) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) { - leaseFromStore, err := s.stor.leases.newestLeasingInfo(id, filter) +func (s *stateManager) NewestLeasingInfo(id crypto.Digest) (*proto.LeaseInfo, error) { + // This function is used only from RIDE for now do not pass filter as an optimization + // TODO: Pass real filter value then supported in environment + leaseFromStore, err := s.stor.leases.newestLeasingInfo(id, true) if err != nil { return nil, err } @@ -695,8 +700,10 @@ func (s *stateManager) NewestLeasingInfo(id crypto.Digest, filter bool) (*proto. return &leaseInfo, nil } -func (s *stateManager) NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) { - return s.stor.scriptsStorage.NewestScriptPKByAddr(addr, filter) +func (s *stateManager) NewestScriptPKByAddr(addr proto.Address) (crypto.PublicKey, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment + return s.stor.scriptsStorage.NewestScriptPKByAddr(addr, true) } func (s *stateManager) AddingBlockHeight() (uint64, error) { @@ -1497,6 +1504,8 @@ func (s *stateManager) CurrentScore() (*big.Int, error) { } func (s *stateManager) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment if recipient.Address == nil { return s.stor.aliases.newestAddrByAlias(recipient.Alias.Alias, true) } @@ -1560,6 +1569,8 @@ func (s *stateManager) ValidateNextTx(tx proto.Transaction, currentTimestamp, pa } func (s *stateManager) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment addr, err := s.stor.aliases.newestAddrByAlias(alias.Alias, true) if err != nil { return proto.Address{}, wrapErr(RetrievalError, err) @@ -1695,6 +1706,8 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt } func (s *stateManager) IsStateUntouched(account proto.Recipient) (bool, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment addr, err := s.recipientToAddress(account) if err != nil { return false, wrapErr(RetrievalError, err) @@ -1723,6 +1736,8 @@ func (s *stateManager) RetrieveNewestIntegerEntry(account proto.Recipient, key s if err != nil { return nil, wrapErr(RetrievalError, err) } + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment entry, err := s.stor.accountsDataStor.retrieveNewestIntegerEntry(*addr, key, true) if err != nil { return nil, wrapErr(RetrievalError, err) @@ -1747,6 +1762,8 @@ func (s *stateManager) RetrieveNewestBooleanEntry(account proto.Recipient, key s if err != nil { return nil, wrapErr(RetrievalError, err) } + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment entry, err := s.stor.accountsDataStor.retrieveNewestBooleanEntry(*addr, key, true) if err != nil { return nil, wrapErr(RetrievalError, err) @@ -1771,6 +1788,8 @@ func (s *stateManager) RetrieveNewestStringEntry(account proto.Recipient, key st if err != nil { return nil, wrapErr(RetrievalError, err) } + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment entry, err := s.stor.accountsDataStor.retrieveNewestStringEntry(*addr, key, true) if err != nil { return nil, wrapErr(RetrievalError, err) @@ -1795,6 +1814,8 @@ func (s *stateManager) RetrieveNewestBinaryEntry(account proto.Recipient, key st if err != nil { return nil, wrapErr(RetrievalError, err) } + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment entry, err := s.stor.accountsDataStor.retrieveNewestBinaryEntry(*addr, key, true) if err != nil { return nil, wrapErr(RetrievalError, err) @@ -1870,6 +1891,8 @@ func (s *stateManager) NewAddrTransactionsIterator(addr proto.Address) (Transact } func (s *stateManager) NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment sponsored, err := s.stor.sponsoredAssets.newestIsSponsored(assetID, true) if err != nil { return false, wrapErr(RetrievalError, err) @@ -1886,6 +1909,8 @@ func (s *stateManager) AssetIsSponsored(assetID crypto.Digest) (bool, error) { } func (s *stateManager) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment info, err := s.stor.assets.newestAssetInfo(assetID, true) if err != nil { return nil, wrapErr(RetrievalError, err) @@ -1921,6 +1946,8 @@ func (s *stateManager) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAs if err != nil { return nil, wrapErr(RetrievalError, err) } + // This function is used only from SmartState interface, so for now we set filter to true. + // TODO: Pass actual filter value after support in RIDE environment info, err := s.stor.assets.newestAssetInfo(assetID, true) if err != nil { return nil, wrapErr(RetrievalError, err) diff --git a/pkg/types/types.go b/pkg/types/types.go index 9dfa15062..f4b559da0 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -35,14 +35,14 @@ type TransactionWithBytes struct { // state for smart contracts type SmartState interface { - NewestScriptPKByAddr(addr proto.Address, filter bool) (crypto.PublicKey, error) + NewestScriptPKByAddr(addr proto.Address) (crypto.PublicKey, error) AddingBlockHeight() (uint64, error) NewestTransactionByID([]byte) (proto.Transaction, error) NewestTransactionHeightByID([]byte) (uint64, error) GetByteTree(recipient proto.Recipient) (proto.Script, error) NewestRecipientToAddress(recipient proto.Recipient) (*proto.Address, error) NewestAddrByAlias(alias proto.Alias) (proto.Address, error) - NewestLeasingInfo(id crypto.Digest, filter bool) (*proto.LeaseInfo, error) + NewestLeasingInfo(id crypto.Digest) (*proto.LeaseInfo, error) IsStateUntouched(account proto.Recipient) (bool, error) // NewestAccountBalance retrieves balance of address in specific currency, asset is asset's ID. // nil asset = Waves. @@ -56,7 +56,6 @@ type SmartState interface { NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) NewestFullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) NewestScriptByAsset(asset proto.OptionalAsset) (proto.Script, error) - // NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) From 50b6c2f7fdcf6e03c97590abeb638e17e69d6918 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Fri, 23 Apr 2021 15:39:40 +0300 Subject: [PATCH 30/52] Additional RIDE functions to retriev data entries on this account implemented and tested (#459) --- pkg/ride/functions.go | 20 +- pkg/ride/functions_proto.go | 111 +++++ pkg/ride/functions_proto_test.go | 695 ++++++++++++++++++++++++++++++- pkg/ride/generate/main.go | 24 +- 4 files changed, 825 insertions(+), 25 deletions(-) diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 217703bf6..9a1c6a28c 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -122,33 +122,33 @@ func costV4(id int) int { return _catalogue_V4[id] } -var _functions_V5 [255]rideFunction +var _functions_V5 [263]rideFunction func init() { - _functions_V5 = [255]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [263]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-011001001100410051006100710081009101102102010310410401041104210431051050105110521053105410610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-0110010011004100510061007100810091011021020103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 95, 99, 103, 107, 110, 114, 117, 121, 125, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 167, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 295, 298, 301, 304, 307, 311, 315, 319, 323, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 595, 598, 601, 604, 607, 610, 613, 616, 619, 622, 625, 628, 631, 634, 637, 640, 643, 646, 649, 652, 655, 658, 661, 678, 695, 712, 729, 746, 763, 780, 797, 814, 842, 862, 883, 904, 924, 931, 936, 945, 960, 971, 983, 987, 990, 997, 1012, 1023, 1027, 1032, 1040, 1048, 1054, 1066, 1077, 1080, 1085, 1092, 1106, 1110, 1114, 1120, 1126, 1133, 1140, 1147, 1154, 1160, 1166, 1176, 1187, 1191, 1193, 1213, 1230, 1238, 1253, 1262, 1276, 1283, 1292, 1302, 1312, 1321, 1330, 1343, 1352, 1366, 1371, 1376, 1387, 1406} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 111, 115, 119, 123, 126, 130, 133, 137, 141, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 183, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 311, 314, 317, 320, 323, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 587, 590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623, 626, 629, 632, 635, 638, 641, 644, 647, 650, 653, 656, 659, 662, 665, 668, 671, 674, 677, 694, 711, 728, 745, 762, 779, 796, 813, 830, 847, 864, 881, 898, 926, 946, 967, 988, 1008, 1015, 1020, 1029, 1044, 1055, 1067, 1071, 1074, 1081, 1096, 1107, 1111, 1116, 1124, 1132, 1138, 1150, 1161, 1164, 1169, 1176, 1190, 1194, 1198, 1204, 1210, 1217, 1224, 1231, 1238, 1244, 1250, 1260, 1271, 1275, 1277, 1297, 1314, 1322, 1337, 1346, 1360, 1367, 1376, 1386, 1396, 1405, 1414, 1427, 1436, 1450, 1455, 1460, 1471, 1490} func functionNameV5(i int) string { - if i < 0 || i > 254 { + if i < 0 || i > 262 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 254 { + if id < 0 || id > 262 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 254; i++ { + for i := 0; i <= 262; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 254 { + if id < 0 || id > 262 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 72520197c..13eaf3142 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -310,6 +310,23 @@ func intFromState(env Environment, args ...rideType) (rideType, error) { return rideInt(entry.Value), nil } +func intFromSelfState(env Environment, args ...rideType) (rideType, error) { + k, err := extractKey(args) + if err != nil { + return rideUnit{}, nil + } + a, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, nil + } + r := proto.NewRecipientFromAddress(proto.Address(a)) + entry, err := env.state().RetrieveNewestIntegerEntry(r, k) + if err != nil { + return rideUnit{}, nil + } + return rideInt(entry.Value), nil +} + func bytesFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { @@ -322,6 +339,23 @@ func bytesFromState(env Environment, args ...rideType) (rideType, error) { return rideBytes(entry.Value), nil } +func bytesFromSelfState(env Environment, args ...rideType) (rideType, error) { + k, err := extractKey(args) + if err != nil { + return rideUnit{}, nil + } + a, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, nil + } + r := proto.NewRecipientFromAddress(proto.Address(a)) + entry, err := env.state().RetrieveNewestBinaryEntry(r, k) + if err != nil { + return rideUnit{}, nil + } + return rideBytes(entry.Value), nil +} + func stringFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { @@ -334,6 +368,23 @@ func stringFromState(env Environment, args ...rideType) (rideType, error) { return rideString(entry.Value), nil } +func stringFromSelfState(env Environment, args ...rideType) (rideType, error) { + k, err := extractKey(args) + if err != nil { + return rideUnit{}, nil + } + a, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, nil + } + r := proto.NewRecipientFromAddress(proto.Address(a)) + entry, err := env.state().RetrieveNewestStringEntry(r, k) + if err != nil { + return rideUnit{}, nil + } + return rideString(entry.Value), nil +} + func booleanFromState(env Environment, args ...rideType) (rideType, error) { r, k, err := extractRecipientAndKey(args) if err != nil { @@ -346,6 +397,23 @@ func booleanFromState(env Environment, args ...rideType) (rideType, error) { return rideBoolean(entry.Value), nil } +func booleanFromSelfState(env Environment, args ...rideType) (rideType, error) { + k, err := extractKey(args) + if err != nil { + return rideUnit{}, nil + } + a, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, nil + } + r := proto.NewRecipientFromAddress(proto.Address(a)) + entry, err := env.state().RetrieveNewestBooleanEntry(r, k) + if err != nil { + return rideUnit{}, nil + } + return rideBoolean(entry.Value), nil +} + func addressFromRecipient(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 1); err != nil { return nil, errors.Wrap(err, "addressFromRecipient") @@ -650,6 +718,14 @@ func intValueFromState(env Environment, args ...rideType) (rideType, error) { return extractValue(v) } +func intValueFromSelfState(env Environment, args ...rideType) (rideType, error) { + v, err := intFromSelfState(env, args...) + if err != nil { + return nil, err + } + return extractValue(v) +} + func booleanValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := booleanFromState(env, args...) if err != nil { @@ -658,6 +734,14 @@ func booleanValueFromState(env Environment, args ...rideType) (rideType, error) return extractValue(v) } +func booleanValueFromSelfState(env Environment, args ...rideType) (rideType, error) { + v, err := booleanFromSelfState(env, args...) + if err != nil { + return nil, err + } + return extractValue(v) +} + func bytesValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := bytesFromState(env, args...) if err != nil { @@ -666,6 +750,14 @@ func bytesValueFromState(env Environment, args ...rideType) (rideType, error) { return extractValue(v) } +func bytesValueFromSelfState(env Environment, args ...rideType) (rideType, error) { + v, err := bytesFromSelfState(env, args...) + if err != nil { + return nil, err + } + return extractValue(v) +} + func stringValueFromState(env Environment, args ...rideType) (rideType, error) { v, err := stringFromState(env, args...) if err != nil { @@ -674,6 +766,14 @@ func stringValueFromState(env Environment, args ...rideType) (rideType, error) { return extractValue(v) } +func stringValueFromSelfState(env Environment, args ...rideType) (rideType, error) { + v, err := stringFromSelfState(env, args...) + if err != nil { + return nil, err + } + return extractValue(v) +} + func transferFromProtobuf(env Environment, args ...rideType) (rideType, error) { b, err := bytesArg(args) if err != nil { @@ -1319,6 +1419,17 @@ func extractRecipientAndKey(args []rideType) (proto.Recipient, string, error) { return r, string(key), nil } +func extractKey(args []rideType) (string, error) { + if err := checkArgs(args, 1); err != nil { + return "", err + } + key, ok := args[0].(rideString) + if !ok { + return "", errors.Errorf("unexpected argument '%s'", args[0].instanceOf()) + } + return string(key), nil +} + func bytesOrStringArg(args []rideType) (rideBytes, error) { if len(args) != 1 { return nil, errors.Errorf("%d is invalid number of arguments, expected 1", len(args)) diff --git a/pkg/ride/functions_proto_test.go b/pkg/ride/functions_proto_test.go index 9c452cdc4..1044b1a47 100644 --- a/pkg/ride/functions_proto_test.go +++ b/pkg/ride/functions_proto_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/base64" "encoding/hex" + "errors" "testing" "time" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/types" ) var ( @@ -98,19 +100,355 @@ func TestAssetBalanceV4(t *testing.T) { } func TestIntFromState(t *testing.T) { - t.SkipNow() + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.IntegerDataEntry{Key: "key", Value: 100500}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := intFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestBytesFromState(t *testing.T) { - t.SkipNow() + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.BinaryDataEntry{Key: "key", Value: []byte("value")}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := bytesFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestStringFromState(t *testing.T) { - t.SkipNow() + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.StringDataEntry{Key: "key", Value: "value"}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideString("value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideString("value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := stringFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestBooleanFromState(t *testing.T) { - t.SkipNow() + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.BooleanDataEntry{Key: "key", Value: true}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideUnit{}}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := booleanFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestIntFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.IntegerDataEntry{Key: "key", Value: 100500}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideString("xxx")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := intFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBytesFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.BinaryDataEntry{Key: "key", Value: []byte("value")}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideString("xxx")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := bytesFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestStringFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.StringDataEntry{Key: "key", Value: "value"}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideString("value")}, + {[]rideType{rideString("xxx")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := stringFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBooleanFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.BooleanDataEntry{Key: "key", Value: true}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideString("xxx")}, false, rideUnit{}}, + {[]rideType{}, false, rideUnit{}}, + {[]rideType{rideUnit{}}, false, rideUnit{}}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideUnit{}}, + } { + r, err := booleanFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestAddressFromRecipient(t *testing.T) { @@ -388,20 +726,355 @@ func TestCheckMerkleProof(t *testing.T) { } } -func TestInvValueFromState(t *testing.T) { - t.SkipNow() +func TestIntValueFromState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.IntegerDataEntry{Key: "key", Value: 100500}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := intValueFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBytesValueFromState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.BinaryDataEntry{Key: "key", Value: []byte("value")}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := bytesValueFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestStringValueFromState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.StringDataEntry{Key: "key", Value: "value"}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideString("value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideString("value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := stringValueFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestBooleanValueFromState(t *testing.T) { - t.SkipNow() + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + correctAlias := proto.NewAlias('T', "good") + incorrectAddress := proto.MustAddressFromString("3N3isZTp6tchjYox99bpxFkqxxySKY6FQsi") + incorrectAlias := proto.NewAlias('T', "bad") + correctAddressRecipient := proto.NewRecipientFromAddress(correctAddress) + correctAliasRecipient := proto.NewRecipientFromAlias(*correctAlias) + incorrectAddressRecipient := proto.NewRecipientFromAddress(incorrectAddress) + incorrectAliasRecipient := proto.NewRecipientFromAlias(*incorrectAlias) + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + if (account == correctAddressRecipient || account == correctAliasRecipient) && key == "key" { + return &proto.BooleanDataEntry{Key: "key", Value: true}, nil + } + return nil, errors.New("not found") + }, + } + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideRecipient(correctAddressRecipient), rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideRecipient(correctAddressRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAddressRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(incorrectAliasRecipient), rideString("key")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAddressRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideRecipient(correctAliasRecipient), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := booleanValueFromState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} +func TestIntValueFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.IntegerDataEntry{Key: "key", Value: 100500}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideInt(100500)}, + {[]rideType{rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := intValueFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } -func TestBytesValueFromState(t *testing.T) { - t.SkipNow() +func TestBytesValueFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.BinaryDataEntry{Key: "key", Value: []byte("value")}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideBytes("value")}, + {[]rideType{rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := bytesValueFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } -func TestStringValueFromState(t *testing.T) { - t.SkipNow() +func TestStringValueFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestStringEntryFunc: func(account proto.Recipient, key string) (*proto.StringDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.StringDataEntry{Key: "key", Value: "value"}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideString("value")}, + {[]rideType{rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := stringValueFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + +func TestBooleanValueFromSelfState(t *testing.T) { + correctAddress := proto.MustAddressFromString("3Myqjf1D44wR8Vko4Tr5CwSzRNo2Vg9S7u7") + env := &MockRideEnvironment{ + stateFunc: func() types.SmartState { + return &MockSmartState{ + RetrieveNewestBooleanEntryFunc: func(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + if *account.Address == correctAddress && key == "key" { + return &proto.BooleanDataEntry{Key: "key", Value: true}, nil + } + return nil, errors.New("not found") + }, + } + }, + thisFunc: func() rideType { + return rideAddress(correctAddress) + }, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("key")}, false, rideBoolean(true)}, + {[]rideType{rideString("xxx")}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideUnit{}}, false, rideThrow("failed to extract from Unit value")}, + {[]rideType{rideString("xxx"), rideInt(12345)}, false, rideThrow("failed to extract from Unit value")}, + } { + r, err := booleanValueFromSelfState(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } } func TestTransferFromProtobuf(t *testing.T) { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 4ab540d01..84f4b5869 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -488,13 +488,21 @@ func functionsV5() map[string]string { m["423"] = "stringToBigInt" m["424"] = "stringToBigIntOpt" m["425"] = "medianListBigInt" + m["1009"] = "hashScriptAtAddress" m["1020"] = "invoke" + m["1054"] = "isDataStorageUntouched" + m["1055"] = "intFromSelfState" + m["1056"] = "booleanFromSelfState" + m["1057"] = "bytesFromSelfState" + m["1058"] = "stringFromSelfState" m["1081"] = "calculateLeaseID" m["1092"] = "simplifiedLease" m["1093"] = "fullLease" m["LeaseCancel"] = "leaseCancel" - m["1054"] = "isDataStorageUntouched" - m["1009"] = "hashScriptAtAddress" + m["@extrNative(1055)"] = "intValueFromSelfState" + m["@extrNative(1056)"] = "booleanValueFromSelfState" + m["@extrNative(1057)"] = "bytesValueFromSelfState" + m["@extrNative(1058)"] = "stringValueFromSelfState" return m } @@ -523,13 +531,21 @@ func catalogueV5() map[string]int { m["423"] = 65 m["424"] = 65 m["425"] = 160 + m["1009"] = 200 m["1020"] = 75 + m["1054"] = 10 + m["1055"] = 10 + m["1056"] = 10 + m["1057"] = 10 + m["1058"] = 10 m["1081"] = 1 m["1092"] = 1 m["1093"] = 1 m["LeaseCancel"] = 1 - m["1054"] = 10 - m["1009"] = 200 + m["@extrNative(1055)"] = 10 + m["@extrNative(1056)"] = 10 + m["@extrNative(1057)"] = 10 + m["@extrNative(1058)"] = 10 delete(m, "Up") delete(m, "HalfDown") return m From a1e37b0ade70226389be6737dce9503b591c769f Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 26 Apr 2021 14:05:47 +0300 Subject: [PATCH 31/52] Ride reentrancy (#457) * Added safe invoke * Added reentranceInvoke * Changed addresses comparison in blacklist * Added combined Invoke and ReentrantInvoke test, added negative test for Invoke with limits * Added recursive test for reentrant invoke * Deleted useless variables --- pkg/ride/environment.go | 1 + pkg/ride/functions.go | 20 +- pkg/ride/functions_proto.go | 179 ++++++- pkg/ride/generate/main.go | 2 + pkg/ride/tree_evaluation_test.go | 823 ++++++++++++++++++++++------- pkg/ride/types_moq_test.go | 3 +- pkg/state/accounts_data_storage.go | 2 +- pkg/state/state.go | 2 +- 8 files changed, 821 insertions(+), 211 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 521ba774b..55fa6e998 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -16,6 +16,7 @@ type WrappedState struct { scheme proto.Scheme invokeCount uint64 act []proto.ScriptAction + blackList []proto.Address } func newWrappedState(env *EvaluationEnvironment) *WrappedState { diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 9a1c6a28c..942292662 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -122,33 +122,33 @@ func costV4(id int) int { return _catalogue_V4[id] } -var _functions_V5 [263]rideFunction +var _functions_V5 [264]rideFunction func init() { - _functions_V5 = [263]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [264]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-0110010011004100510061007100810091011021020103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-01100100110041005100610071008100910110210201021103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 50, 53, 57, 61, 65, 69, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 111, 115, 119, 123, 126, 130, 133, 137, 141, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 183, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 311, 314, 317, 320, 323, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 587, 590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623, 626, 629, 632, 635, 638, 641, 644, 647, 650, 653, 656, 659, 662, 665, 668, 671, 674, 677, 694, 711, 728, 745, 762, 779, 796, 813, 830, 847, 864, 881, 898, 926, 946, 967, 988, 1008, 1015, 1020, 1029, 1044, 1055, 1067, 1071, 1074, 1081, 1096, 1107, 1111, 1116, 1124, 1132, 1138, 1150, 1161, 1164, 1169, 1176, 1190, 1194, 1198, 1204, 1210, 1217, 1224, 1231, 1238, 1244, 1250, 1260, 1271, 1275, 1277, 1297, 1314, 1322, 1337, 1346, 1360, 1367, 1376, 1386, 1396, 1405, 1414, 1427, 1436, 1450, 1455, 1460, 1471, 1490} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 187, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 315, 318, 321, 324, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 534, 537, 540, 543, 546, 549, 552, 555, 558, 561, 564, 567, 570, 573, 576, 579, 582, 585, 588, 591, 594, 597, 600, 603, 606, 609, 612, 615, 618, 621, 624, 627, 630, 633, 636, 639, 642, 645, 648, 651, 654, 657, 660, 663, 666, 669, 672, 675, 678, 681, 698, 715, 732, 749, 766, 783, 800, 817, 834, 851, 868, 885, 902, 930, 950, 971, 992, 1012, 1019, 1024, 1033, 1048, 1059, 1071, 1075, 1078, 1085, 1100, 1111, 1115, 1120, 1128, 1136, 1142, 1154, 1165, 1168, 1173, 1180, 1194, 1198, 1202, 1208, 1214, 1221, 1228, 1235, 1242, 1248, 1254, 1264, 1275, 1279, 1281, 1301, 1318, 1326, 1341, 1350, 1364, 1371, 1380, 1390, 1400, 1409, 1418, 1431, 1440, 1454, 1459, 1464, 1475, 1494} func functionNameV5(i int) string { - if i < 0 || i > 262 { + if i < 0 || i > 263 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 262 { + if id < 0 || id > 263 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 262; i++ { + for i := 0; i <= 263; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 262 { + if id < 0 || id > 263 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 13eaf3142..5bc0d2906 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -6,14 +6,179 @@ import ( "crypto/rsa" sh256 "crypto/sha256" "crypto/x509" + "github.com/wavesplatform/gowaves/pkg/util/common" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" c2 "github.com/wavesplatform/gowaves/pkg/ride/crypto" - "github.com/wavesplatform/gowaves/pkg/util/common" ) +func isAddressInBL(dAppAddress proto.Address, blackList []proto.Address) bool { + for _, v := range blackList { + if v == dAppAddress { + return true + } + } + return false +} + +func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { + ws, ok := env.state().(*WrappedState) + if !ok { + return nil, errors.Wrapf(errors.New("wrong state"), "invoke") + } + ws.incrementInvCount() + if ws.invCount() > 100 { + return rideUnit{}, nil + } + + callerAddress, ok := env.this().(rideAddress) + if !ok { + return rideUnit{}, errors.Errorf("invoke: this has an unexpected type '%s'", env.this().instanceOf()) + } + + recipient, err := extractRecipient(args[0]) + if err != nil { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[0].instanceOf()) + } + + if recipient.Address == nil { + if recipient.Alias == nil { + return nil, errors.New("invoke: address and alias are nil") + } + addressFromAlias, err := env.state().NewestAddrByAlias(*recipient.Alias) + if err != nil { + return nil, errors.Errorf("invoke: failed to get address by alias, %v", err) + } + recipient = proto.NewRecipientFromAddress(addressFromAlias) + } + + var fnName rideString + switch fnN := args[1].(type) { + case rideUnit: + fnName = "default" + case rideString: + if fnN == "" { + fnName = "default" + break + } + fnName = fnN + default: + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[1].instanceOf()) + } + + listArg, ok := args[2].(rideList) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", args[2].instanceOf()) + } + + var attachedPayments proto.ScriptPayments + payments := args[3].(rideList) + + oldInvocationParam := env.invocation() + + invocationParam := make(rideObject) + for key, value := range oldInvocationParam { + invocationParam[key] = value + } + + invocationParam["caller"] = callerAddress + callerPublicKey, err := env.state().NewestScriptPKByAddr(proto.Address(callerAddress)) + if err != nil { + return nil, errors.Wrapf(err, "failed to get caller public key by address") + } + invocationParam["callerPublicKey"] = rideBytes(common.Dup(callerPublicKey.Bytes())) + invocationParam["payments"] = payments + env.SetInvocation(invocationParam) + + for _, value := range payments { + payment, ok := value.(rideObject) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", payment.instanceOf()) + } + + assetID, err := payment.get("assetId") + if err != nil { + return nil, errors.Wrap(err, "invoke") + } + amount, err := payment.get("amount") + if err != nil { + return nil, errors.Wrap(err, "invoke") + } + + intAmount, ok := amount.(rideInt) + if !ok { + return nil, errors.Errorf("invoke: unexpected argument type '%s'", amount.instanceOf()) + } + var asset *proto.OptionalAsset + + switch asID := assetID.(type) { + case rideBytes: + asset, err = proto.NewOptionalAssetFromBytes(asID) + if err != nil { + return nil, errors.Errorf("invoke: failed to get optional asset from ride bytes") + } + case rideUnit: + waves := proto.NewOptionalAssetWaves() + asset = &waves + default: + return nil, errors.Errorf("attachedPayment: unexpected argument type '%s'", args[0].instanceOf()) + } + + attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: *asset, Amount: uint64(intAmount)}) + } + + var paymentActions []proto.ScriptAction + for _, payment := range attachedPayments { + action := &proto.TransferScriptAction{Sender: &callerPublicKey, Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} + paymentActions = append(paymentActions, action) + } + + address, err := env.state().NewestRecipientToAddress(recipient) + if err != nil { + return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") + } + env.setNewDAppAddress(*address) + err = ws.smartAppendActions(paymentActions, env) + if err != nil { + return nil, errors.Wrapf(err, "failed to apply attachedPayments") + } + + if ws.invCount() > 1 { + if isAddressInBL(*recipient.Address, ws.blackList) && proto.Address(callerAddress) != *recipient.Address { + return rideUnit{}, errors.Errorf("function call of %s with dApp address %s is forbiden because it had already been called once by 'invoke'", fnName, recipient.Address) + } + } + + res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) + + if err != nil { + return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + } + + if res.Result() { + if res.UserError() != "" { + return nil, errors.Errorf(res.UserError()) + } + + err = ws.smartAppendActions(res.ScriptActions(), env) + if err != nil { + return nil, err + } + + env.setNewDAppAddress(proto.Address(callerAddress)) + env.SetInvocation(oldInvocationParam) + + if res.UserResult() == nil { + return rideUnit{}, nil + } + return res.UserResult(), nil + } + + return nil, errors.Errorf("result of Invoke is false") +} + func invoke(env Environment, args ...rideType) (rideType, error) { ws, ok := env.state().(*WrappedState) if !ok { @@ -136,7 +301,19 @@ func invoke(env Environment, args ...rideType) (rideType, error) { return nil, errors.Wrapf(err, "failed to apply attachedPayments") } + // append a call to the stack to protect a user from the reentrancy attack + ws.blackList = append(ws.blackList, proto.Address(callerAddress)) // push + + if ws.invCount() > 1 { + if isAddressInBL(*recipient.Address, ws.blackList) && proto.Address(callerAddress) != *recipient.Address { + return rideUnit{}, errors.Errorf("failed to call ") + } + } + res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) + + ws.blackList = ws.blackList[:len(ws.blackList)-1] // pop + if err != nil { return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") } diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 84f4b5869..65f8ae783 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -490,6 +490,7 @@ func functionsV5() map[string]string { m["425"] = "medianListBigInt" m["1009"] = "hashScriptAtAddress" m["1020"] = "invoke" + m["1021"] = "reentrantInvoke" m["1054"] = "isDataStorageUntouched" m["1055"] = "intFromSelfState" m["1056"] = "booleanFromSelfState" @@ -533,6 +534,7 @@ func catalogueV5() map[string]int { m["425"] = 160 m["1009"] = 200 m["1020"] = 75 + m["1021"] = 75 m["1054"] = 10 m["1055"] = 10 m["1056"] = 10 diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 46ce0dc61..b67442bc9 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -1836,7 +1836,197 @@ func TestInvokeDAppFromDAppScript3(t *testing.T) { tearDownDappFromDapp() } -func TestInvokeDAppFromDAppScript4(t *testing.T) { +//TODO change this test from Invoke to ReentrantInvoke +//func TestInvokeDAppFromDAppScript4(t *testing.T) { +// +// /* script 1 +// {-# STDLIB_VERSION 5 #-} +// {-# CONTENT_TYPE DAPP #-} +// {-#SCRIPT_TYPE ACCOUNT#-} +// +// @Callable(i) +// func back() = { +// [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] +// } +// +// @Callable(i) +// func foo() = { +// let b1 = wavesBalance(this) +// let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) +// if b1 == b1 && ob1 == ob1 +// then +// let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) +// if r == 17 +// then +// let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") +// let tdata = getIntegerValue(this, "key") +// let b2 = wavesBalance(this) +// let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) +// if data == 1 && tdata == 0 +// then +// if ob1.regular+16 == ob2.regular && b1.regular == b2.regular+16 +// then +// [ +// IntegerEntry("key", 1) +// ] +// else +// throw("Balance check failed") +// else +// throw("Bad state") +// else +// throw("Bad returned value") +// else +// throw("Imposible") +// } +// */ +// +// /* +// script2 +// {-# STDLIB_VERSION 5 #-} +// {-# CONTENT_TYPE DAPP #-} +// {-#SCRIPT_TYPE ACCOUNT#-} +// +// @Callable(i) +// func bar(a: ByteVector) = { +// let r = Invoke(Address(a), "back", [], []) +// if r == r +// then +// ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) +// else +// throw("Imposible") +// } +// +// */ +// txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") +// require.NoError(t, err) +// proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") +// require.NoError(t, err) +// proofs := proto.NewProofs() +// proofs.Proofs = []proto.B58Bytes{proof[:]} +// sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") +// require.NoError(t, err) +// senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) +// require.NoError(t, err) +// +// addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") +// require.NoError(t, err) +// recipient := proto.NewRecipientFromAddress(addr) +// addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) +// require.NoError(t, err) +// +// addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") +// require.NoError(t, err) +// recipientCallable := proto.NewRecipientFromAddress(addressCallable) +// addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) +// require.NoError(t, err) +// +// arguments := proto.Arguments{} +// arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) +// +// call := proto.FunctionCall{ +// Default: false, +// Name: "cancel", +// Arguments: arguments, +// } +// tx = &proto.InvokeScriptWithProofs{ +// Type: proto.InvokeScriptTransaction, +// Version: 1, +// ID: &txID, +// Proofs: proofs, +// ChainID: proto.MainNetScheme, +// SenderPK: sender, +// ScriptRecipient: recipient, +// FunctionCall: call, +// Payments: proto.ScriptPayments{proto.ScriptPayment{ +// Amount: 10000, +// Asset: proto.OptionalAsset{}, +// }}, +// FeeAsset: proto.OptionalAsset{}, +// Fee: 900000, +// Timestamp: 1564703444249, +// } +// inv, _ = invocationToObject(4, proto.MainNetScheme, tx) +// +// firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssAAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAJiMQkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjEJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywMDCQAAAAAAAAIFAAAAAmIxBQAAAAJiMQkAAAAAAAACBQAAAANvYjEFAAAAA29iMQcEAAAAAXIJAAP8AAAABAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAADYmFyCQAETAAAAAIIBQAAAAR0aGlzAAAABWJ5dGVzBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAABHVuaXQAAAAAAAAAABEFAAAAA25pbAMJAAAAAAAAAgUAAAABcgAAAAAAAAAAEQQAAAAEZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywIAAAADYmFyBAAAAAV0ZGF0YQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwIAAAADa2V5BAAAAAJiMgkAA+8AAAABBQAAAAR0aGlzBAAAAANvYjIJAAPvAAAAAQkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywMDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEJAAAAAAAAAgUAAAAFdGRhdGEAAAAAAAAAAAAHAwMJAAAAAAAAAgkAAGQAAAACCAUAAAADb2IxAAAAB3JlZ3VsYXIAAAAAAAAAABAIBQAAAANvYjIAAAAHcmVndWxhcgkAAAAAAAACCAUAAAACYjEAAAAHcmVndWxhcgkAAGQAAAACCAUAAAACYjIAAAAHcmVndWxhcgAAAAAAAAAAEAcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAAFEJhbGFuY2UgY2hlY2sgZmFpbGVkCQAAAgAAAAECAAAACUJhZCBzdGF0ZQkAAAIAAAABAgAAABJCYWQgcmV0dXJuZWQgdmFsdWUJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAOgXYAY=" +// secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" +// +// id = bytes.Repeat([]byte{0}, 32) +// +// expectedDataEntryWrites := []*proto.DataEntryScriptAction{ +// {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: &addrPK}, +// {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, +// {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, +// } +// +// expectedTransferWrites := []*proto.TransferScriptAction{ +// {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, +// {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, +// {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, +// } +// +// smartState := smartStateDappFromDapp +// +// thisAddress = addr +// +// env := envDappFromDapp +// +// NewWrappedSt := initWrappedState(smartState(), env) +// wrappedSt = *NewWrappedSt +// +// err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) +// require.NoError(t, err) +// err = AddExternalPayments(tx.Payments, tx.SenderPK) +// require.NoError(t, err) +// +// src, err := base64.StdEncoding.DecodeString(firstScript) +// require.NoError(t, err) +// +// tree, err := Parse(src) +// require.NoError(t, err) +// assert.NotNil(t, tree) +// +// res, err := CallFunction(env, tree, "foo", proto.Arguments{}) +// +// require.NoError(t, err) +// r, ok := res.(DAppResult) +// require.True(t, ok) +// require.True(t, r.res) +// +// sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) +// require.NoError(t, err) +// +// expectedActionsResult := &proto.ScriptResult{ +// DataEntries: expectedDataEntryWrites, +// Transfers: expectedTransferWrites, +// Issues: make([]*proto.IssueScriptAction, 0), +// Reissues: make([]*proto.ReissueScriptAction, 0), +// Burns: make([]*proto.BurnScriptAction, 0), +// Sponsorships: make([]*proto.SponsorshipScriptAction, 0), +// Leases: make([]*proto.LeaseScriptAction, 0), +// LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), +// } +// assert.Equal(t, expectedActionsResult, sr) +// +// expectedDiffResult := initWrappedState(smartState(), env).diff +// +// balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9984, effectiveHistory: []int64{10000, 9984}} +// balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} +// balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 16, effectiveHistory: []int64{0, 16}} +// intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} +// intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} +// expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 +// expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 +// expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain +// expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender +// expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable +// +// assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) +// assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) +// +// tearDownDappFromDapp() +//} + +func TestNegativeCycleNewInvokeDAppFromDAppScript4(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} @@ -1895,6 +2085,7 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { throw("Imposible") } + */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) @@ -1915,7 +2106,6 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) @@ -1951,18 +2141,6 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: &addrPK}, - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, - } - - expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, - } - smartState := smartStateDappFromDapp thisAddress = addr @@ -1986,102 +2164,219 @@ func TestInvokeDAppFromDAppScript4(t *testing.T) { res, err := CallFunction(env, tree, "foo", proto.Arguments{}) - require.NoError(t, err) + require.Error(t, err) r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: expectedTransferWrites, - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - } - assert.Equal(t, expectedActionsResult, sr) - - expectedDiffResult := initWrappedState(smartState(), env).diff - - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9984, effectiveHistory: []int64{10000, 9984}} - balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} - balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 16, effectiveHistory: []int64{0, 16}} - intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} - intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} - expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 - expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 - expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain - expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender - expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable - - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + require.False(t, ok) + require.False(t, r.res) tearDownDappFromDapp() } -func TestInvokeDAppFromDAppScript5(t *testing.T) { +//TODO change this test from Invoke to ReentrantInvoke +//func TestInvokeDAppFromDAppScript5(t *testing.T) { +// +// /* script 1 +// {-# STDLIB_VERSION 5 #-} +// {-# CONTENT_TYPE DAPP #-} +// {-#SCRIPT_TYPE ACCOUNT#-} +// +// @Callable(i) +// func back() = { +// [ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] +// } +// +// @Callable(i) +// func foo() = { +// let b1 = wavesBalance(this) +// let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) +// if b1 == b1 && ob1 == ob1 +// then +// let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) +// if r == 17 +// then +// let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") +// let b2 = wavesBalance(this) +// let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) +// if data == 1 +// then +// if ob1.regular+13 == ob2.regular && b1.regular == b2.regular+13 +// then +// [ +// IntegerEntry("key", 1) +// ] +// else +// throw("Balance check failed") +// else +// throw("Bad state") +// else +// throw("Bad returned value") +// else +// throw("Imposible") +// } +// */ +// +// /* +// script2 +// {-# STDLIB_VERSION 5 #-} +// {-# CONTENT_TYPE DAPP #-} +// {-#SCRIPT_TYPE ACCOUNT#-} +// +// @Callable(i) +// func bar(a: ByteVector) = { +// let r = Invoke(Address(a), "back", [], [AttachedPayment(unit, 3)]) +// if r == r +// then +// ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) +// else +// throw("Imposible") +// } + +// */ +// txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") +// require.NoError(t, err) +// proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") +// require.NoError(t, err) +// proofs := proto.NewProofs() +// proofs.Proofs = []proto.B58Bytes{proof[:]} +// sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") +// require.NoError(t, err) +// senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) +// require.NoError(t, err) +// +// addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") +// require.NoError(t, err) +// recipient := proto.NewRecipientFromAddress(addr) +// addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr, false) +// require.NoError(t, err) +// +// addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") +// require.NoError(t, err) +// recipientCallable := proto.NewRecipientFromAddress(addressCallable) +// addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable, false) +// require.NoError(t, err) +// +// arguments := proto.Arguments{} +// arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) +// +// call := proto.FunctionCall{ +// Default: false, +// Name: "cancel", +// Arguments: arguments, +// } +// tx = &proto.InvokeScriptWithProofs{ +// Type: proto.InvokeScriptTransaction, +// Version: 1, +// ID: &txID, +// Proofs: proofs, +// ChainID: proto.MainNetScheme, +// SenderPK: sender, +// ScriptRecipient: recipient, +// FunctionCall: call, +// Payments: proto.ScriptPayments{proto.ScriptPayment{ +// Amount: 10000, +// Asset: proto.OptionalAsset{}, +// }}, +// FeeAsset: proto.OptionalAsset{}, +// Fee: 900000, +// Timestamp: 1564703444249, +// } +// inv, _ = invocationToObject(4, proto.MainNetScheme, tx) +// +// firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXSbIqC+dSm+dDCCL8KamODy9oLyPQygrLAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAA0WFyhQ==" +// secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAADBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACzZnMp" +// +// id = bytes.Repeat([]byte{0}, 32) +// +// expectedDataEntryWrites := []*proto.DataEntryScriptAction{ +// {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, +// {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, +// } +// +// expectedTransferWrites := []*proto.TransferScriptAction{ +// {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, +// {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, +// {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, +// {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, +// } +// +// smartState := smartStateDappFromDapp +// +// thisAddress = addr +// env := envDappFromDapp +// +// NewWrappedSt := initWrappedState(smartState(), env) +// wrappedSt = *NewWrappedSt +// +// err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) +// require.NoError(t, err) +// err = AddExternalPayments(tx.Payments, tx.SenderPK) +// require.NoError(t, err) +// +// src, err := base64.StdEncoding.DecodeString(firstScript) +// require.NoError(t, err) +// +// tree, err := Parse(src) +// require.NoError(t, err) +// assert.NotNil(t, tree) +// +// res, err := CallFunction(env, tree, "foo", proto.Arguments{}) +// +// require.NoError(t, err) +// r, ok := res.(DAppResult) +// require.True(t, ok) +// require.True(t, r.res) +// +// sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) +// require.NoError(t, err) +// +// expectedActionsResult := &proto.ScriptResult{ +// DataEntries: expectedDataEntryWrites, +// Transfers: expectedTransferWrites, +// Issues: make([]*proto.IssueScriptAction, 0), +// Reissues: make([]*proto.ReissueScriptAction, 0), +// Burns: make([]*proto.BurnScriptAction, 0), +// Sponsorships: make([]*proto.SponsorshipScriptAction, 0), +// Leases: make([]*proto.LeaseScriptAction, 0), +// LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), +// } +// assert.Equal(t, expectedActionsResult, sr) +// +// expectedDiffResult := initWrappedState(smartState(), env).diff +// +// balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9987, effectiveHistory: []int64{10000, 9987}} +// balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} +// balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 13, effectiveHistory: []int64{0, 13}} +// intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} +// expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry +// expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain +// expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender +// expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable +// +// assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) +// assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) +// +// tearDownDappFromDapp() +// +//} + +func TestInvokeDAppFromDAppScript6(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} {-# CONTENT_TYPE DAPP #-} {-#SCRIPT_TYPE ACCOUNT#-} - @Callable(i) - func back() = { - [ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] - } - @Callable(i) func foo() = { - let b1 = wavesBalance(this) - let ob1 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) - if b1 == b1 && ob1 == ob1 + let r = Invoke(this, "foo", [], []) + if r == r then - let r = Invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) - if r == 17 - then - let data = getIntegerValue(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar") - let b2 = wavesBalance(this) - let ob2 = wavesBalance(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna')) - if data == 1 - then - if ob1.regular+13 == ob2.regular && b1.regular == b2.regular+13 - then - [ - IntegerEntry("key", 1) - ] - else - throw("Balance check failed") - else - throw("Bad state") - else - throw("Bad returned value") + [ + ] else throw("Imposible") } - */ - /* - script2 - {-# STDLIB_VERSION 5 #-} - {-# CONTENT_TYPE DAPP #-} - {-#SCRIPT_TYPE ACCOUNT#-} - - @Callable(i) - func bar(a: ByteVector) = { - let r = Invoke(Address(a), "back", [], [AttachedPayment(unit, 3)]) - if r == r - then - ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) - else - throw("Imposible") - } */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") require.NoError(t, err) @@ -2091,9 +2386,6 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") require.NoError(t, err) - senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) - require.NoError(t, err) - addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) @@ -2102,13 +2394,11 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) arguments := proto.Arguments{} arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) - call := proto.FunctionCall{ Default: false, Name: "cancel", @@ -2123,46 +2413,26 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { SenderPK: sender, ScriptRecipient: recipient, FunctionCall: call, - Payments: proto.ScriptPayments{proto.ScriptPayment{ - Amount: 10000, - Asset: proto.OptionalAsset{}, - }}, - FeeAsset: proto.OptionalAsset{}, - Fee: 900000, - Timestamp: 1564703444249, + Payments: nil, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXSbIqC+dSm+dDCCL8KamODy9oLyPQygrLAAAAAAAAAAACBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAADZm9vAAAAAAQAAAACYjEJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IxCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDAwkAAAAAAAACBQAAAAJiMQUAAAACYjEJAAAAAAAAAgUAAAADb2IxBQAAAANvYjEHBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEEAAAABGRhdGEJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgQAAAACYjIJAAPvAAAAAQUAAAAEdGhpcwQAAAADb2IyCQAD7wAAAAEJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssDCQAAAAAAAAIFAAAABGRhdGEAAAAAAAAAAAEDAwkAAAAAAAACCQAAZAAAAAIIBQAAAANvYjEAAAAHcmVndWxhcgAAAAAAAAAADQgFAAAAA29iMgAAAAdyZWd1bGFyCQAAAAAAAAIIBQAAAAJiMQAAAAdyZWd1bGFyCQAAZAAAAAIIBQAAAAJiMgAAAAdyZWd1bGFyAAAAAAAAAAANBwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAABBQAAAANuaWwJAAACAAAAAQIAAAAUQmFsYW5jZSBjaGVjayBmYWlsZWQJAAACAAAAAQIAAAAJQmFkIHN0YXRlCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQkAAAIAAAABAgAAAAlJbXBvc2libGUAAAAA0WFyhQ==" - secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAADBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACzZnMp" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" id = bytes.Repeat([]byte{0}, 32) - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, - {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, - } - - expectedTransferWrites := []*proto.TransferScriptAction{ - {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, - {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, - {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, - } - smartState := smartStateDappFromDapp thisAddress = addr + env := envDappFromDapp NewWrappedSt := initWrappedState(smartState(), env) wrappedSt = *NewWrappedSt - err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) - require.NoError(t, err) - err = AddExternalPayments(tx.Payments, tx.SenderPK) - require.NoError(t, err) - src, err := base64.StdEncoding.DecodeString(firstScript) require.NoError(t, err) @@ -2181,8 +2451,8 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { require.NoError(t, err) expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: expectedTransferWrites, + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: make([]*proto.TransferScriptAction, 0), Issues: make([]*proto.IssueScriptAction, 0), Reissues: make([]*proto.ReissueScriptAction, 0), Burns: make([]*proto.BurnScriptAction, 0), @@ -2194,23 +2464,12 @@ func TestInvokeDAppFromDAppScript5(t *testing.T) { expectedDiffResult := initWrappedState(smartState(), env).diff - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9987, effectiveHistory: []int64{10000, 9987}} - balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} - balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 13, effectiveHistory: []int64{0, 13}} - intEntry := proto.IntegerDataEntry{Key: "bar", Value: 1} - expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry - expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain - expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender - expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) tearDownDappFromDapp() - } -func TestInvokeDAppFromDAppScript6(t *testing.T) { +func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { /* script 1 {-# STDLIB_VERSION 5 #-} @@ -2230,15 +2489,23 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") - require.NoError(t, err) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") - require.NoError(t, err) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } proofs := proto.NewProofs() proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") - require.NoError(t, err) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") - require.NoError(t, err) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } recipient := proto.NewRecipientFromAddress(addr) arguments := proto.Arguments{} @@ -2278,42 +2545,26 @@ func TestInvokeDAppFromDAppScript6(t *testing.T) { wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) - require.NoError(t, err) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } tree, err := Parse(src) - require.NoError(t, err) - assert.NotNil(t, tree) - - res, err := CallFunction(env, tree, "foo", proto.Arguments{}) - - require.NoError(t, err) - r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: make([]*proto.DataEntryScriptAction, 0), - Transfers: make([]*proto.TransferScriptAction, 0), - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + if err != nil { + b.Fatal("Expected no errors, got error ", err) } - assert.Equal(t, expectedActionsResult, sr) - - expectedDiffResult := initWrappedState(smartState(), env).diff - - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := CallFunction(env, tree, "foo", proto.Arguments{}) + if err != nil { + b.Fatal("Expected no errors, got error ", err) + } + } tearDownDappFromDapp() } -func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { +func TestReentrantInvokeDAppFromDAppScript6(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} @@ -2322,7 +2573,7 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { @Callable(i) func foo() = { - let r = Invoke(this, "foo", [], []) + let r = reentrantInvoke(this, "foo", [], []) if r == r then [ @@ -2333,23 +2584,15 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { */ txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) proofs := proto.NewProofs() proofs.Proofs = []proto.B58Bytes{proof[:]} sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) recipient := proto.NewRecipientFromAddress(addr) arguments := proto.Arguments{} @@ -2375,7 +2618,7 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { } inv, _ = invocationToObject(4, proto.MainNetScheme, tx) - firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/wAAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAAAWzLtA=" + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAADZm9vAAAAAAQAAAABcgkAA/0AAAAEBQAAAAR0aGlzAgAAAANmb28FAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFyBQAAAAFyBQAAAANuaWwJAAACAAAAAQIAAAAJSW1wb3NpYmxlAAAAALQe43c=\n" id = bytes.Repeat([]byte{0}, 32) @@ -2389,22 +2632,38 @@ func BenchmarkInvokeDAppFromDAppScript6(b *testing.B) { wrappedSt = *NewWrappedSt src, err := base64.StdEncoding.DecodeString(firstScript) - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) tree, err := Parse(src) - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + require.NoError(t, err) + assert.NotNil(t, tree) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := CallFunction(env, tree, "foo", proto.Arguments{}) - if err != nil { - b.Fatal("Expected no errors, got error ", err) - } + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: make([]*proto.DataEntryScriptAction, 0), + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + tearDownDappFromDapp() } @@ -3121,6 +3380,178 @@ func TestInvokeDAppFromDAppSmartAssetValidation(t *testing.T) { tearDownDappFromDapp() } +func TestMixedReentrantInvokeAndInvoke(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func back() = { + [IntegerEntry("key", 0), ScriptTransfer(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), 2, unit)] + } + + @Callable(i) + func foo() = { + let r = reentrantInvoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "bar", [this.bytes], [AttachedPayment(unit, 17)]) + if r == 17 + then + [ + IntegerEntry("key", 1) + ] + else + throw("Imposible") + } + */ + + /* + script2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-#SCRIPT_TYPE ACCOUNT#-} + + @Callable(i) + func bar(a: ByteVector) = { + let r = Invoke(Address(a), "back", [], []) + if r == r + then + ([IntegerEntry("bar", 1), ScriptTransfer(Address(a), 3, unit)], 17) + else + throw("Imposible") + } + + + */ + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAYIAhIAEgAAAAAAAAAAAgAAAAFpAQAAAARiYWNrAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADa2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssAAAAAAAAAAAIFAAAABHVuaXQFAAAAA25pbAAAAAFpAQAAAANmb28AAAAABAAAAAFyCQAD/QAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAA2JhcgkABEwAAAACCAUAAAAEdGhpcwAAAAVieXRlcwUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAR1bml0AAAAAAAAAAARBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIAAAAAAAAAABEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2tleQAAAAAAAAAAAQUAAAADbmlsCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAAB70C6c" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgECAAAAAAAAAAEAAAABaQEAAAADYmFyAAAAAQAAAAFhBAAAAAFyCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQIAAAAEYmFjawUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAAXIFAAAAAXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAADYmFyAAAAAAAAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAAAdBZGRyZXNzAAAAAQUAAAABYQAAAAAAAAAAAwUAAAAEdW5pdAUAAAADbmlsAAAAAAAAAAARCQAAAgAAAAECAAAACUltcG9zaWJsZQAAAACf+Ofn" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 0}, Sender: &addrPK}, + {Entry: &proto.IntegerDataEntry{Key: "bar", Value: 1}, Sender: &addressCallablePK}, + {Entry: &proto.IntegerDataEntry{Key: "key", Value: 1}}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Sender: &addrPK, Recipient: recipientCallable, Amount: 17, Asset: proto.OptionalAsset{}}, + {Sender: &addrPK, Recipient: recipientCallable, Amount: 2, Asset: proto.OptionalAsset{}}, + {Sender: &addressCallablePK, Recipient: recipient, Amount: 3, Asset: proto.OptionalAsset{}}, + } + + smartState := smartStateDappFromDapp + + thisAddress = addr + + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "foo", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9984} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 16} + intEntry1 := proto.IntegerDataEntry{Key: "key", Value: 0} + intEntry2 := proto.IntegerDataEntry{Key: "bar", Value: 1} + expectedDiffResult.dataEntries.diffInteger["key"+addr.String()] = intEntry1 + expectedDiffResult.dataEntries.diffInteger["bar"+addressCallable.String()] = intEntry2 + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + + tearDownDappFromDapp() +} + func TestHashScriptFunc(t *testing.T) { /* {-# STDLIB_VERSION 5 #-} diff --git a/pkg/ride/types_moq_test.go b/pkg/ride/types_moq_test.go index f139bee20..988e7932f 100644 --- a/pkg/ride/types_moq_test.go +++ b/pkg/ride/types_moq_test.go @@ -4,11 +4,10 @@ package ride import ( - "sync" - "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/types" + "sync" ) // Ensure, that MockSmartState does implement types.SmartState. diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index bbc43e52c..7d09fb962 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -269,7 +269,7 @@ func (s *accountsDataStorage) retrieveEntries(addr proto.Address, filter bool) ( return entries, nil } -func (s *accountsDataStorage) isEntryExist(addr proto.Address, filter bool) (bool, error) { +func (s *accountsDataStorage) entryExists(addr proto.Address, filter bool) (bool, error) { addrNum, err := s.addrToNum(addr) if err != nil { return false, err diff --git a/pkg/state/state.go b/pkg/state/state.go index 4edca50b5..c50f15e8e 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1712,7 +1712,7 @@ func (s *stateManager) IsStateUntouched(account proto.Recipient) (bool, error) { if err != nil { return false, wrapErr(RetrievalError, err) } - entryExist, err := s.stor.accountsDataStor.isEntryExist(*addr, true) + entryExist, err := s.stor.accountsDataStor.entryExists(*addr, true) if err != nil { return false, wrapErr(RetrievalError, err) } From fd8cec340a8e124ac51f2262b6c158b1bb31d7e0 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 27 Apr 2021 12:49:21 +0300 Subject: [PATCH 32/52] Added new RIDE function fraction for Int arguments with support of rounding mode. Tests added. Usual Int fraction function cost changed. (#460) --- pkg/ride/functions.go | 20 +++++------ pkg/ride/functions_bigint.go | 28 +++++++++------ pkg/ride/functions_bigint_test.go | 4 +++ pkg/ride/functions_int.go | 35 +++++++++++++++++++ pkg/ride/functions_int_test.go | 57 +++++++++++++++++++++++++++++++ pkg/ride/generate/main.go | 3 ++ 6 files changed, 127 insertions(+), 20 deletions(-) diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 942292662..7175b3223 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -122,33 +122,33 @@ func costV4(id int) int { return _catalogue_V4[id] } -var _functions_V5 [264]rideFunction +var _functions_V5 [265]rideFunction func init() { - _functions_V5 = [264]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [265]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, fractionIntRounds, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 14, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 17, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 14, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "fraction": 17, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-01100100110041005100610071008100910110210201021103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-01100100110041005100610071008100910110210201021103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractfractiongetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 187, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 315, 318, 321, 324, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 534, 537, 540, 543, 546, 549, 552, 555, 558, 561, 564, 567, 570, 573, 576, 579, 582, 585, 588, 591, 594, 597, 600, 603, 606, 609, 612, 615, 618, 621, 624, 627, 630, 633, 636, 639, 642, 645, 648, 651, 654, 657, 660, 663, 666, 669, 672, 675, 678, 681, 698, 715, 732, 749, 766, 783, 800, 817, 834, 851, 868, 885, 902, 930, 950, 971, 992, 1012, 1019, 1024, 1033, 1048, 1059, 1071, 1075, 1078, 1085, 1100, 1111, 1115, 1120, 1128, 1136, 1142, 1154, 1165, 1168, 1173, 1180, 1194, 1198, 1202, 1208, 1214, 1221, 1228, 1235, 1242, 1248, 1254, 1264, 1275, 1279, 1281, 1301, 1318, 1326, 1341, 1350, 1364, 1371, 1380, 1390, 1400, 1409, 1418, 1431, 1440, 1454, 1459, 1464, 1475, 1494} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 187, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 315, 318, 321, 324, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 534, 537, 540, 543, 546, 549, 552, 555, 558, 561, 564, 567, 570, 573, 576, 579, 582, 585, 588, 591, 594, 597, 600, 603, 606, 609, 612, 615, 618, 621, 624, 627, 630, 633, 636, 639, 642, 645, 648, 651, 654, 657, 660, 663, 666, 669, 672, 675, 678, 681, 698, 715, 732, 749, 766, 783, 800, 817, 834, 851, 868, 885, 902, 930, 950, 971, 992, 1012, 1019, 1024, 1033, 1048, 1059, 1071, 1075, 1078, 1085, 1100, 1111, 1115, 1120, 1128, 1136, 1142, 1154, 1165, 1168, 1173, 1180, 1194, 1198, 1202, 1208, 1214, 1221, 1228, 1235, 1242, 1248, 1254, 1264, 1275, 1279, 1281, 1301, 1318, 1326, 1341, 1350, 1364, 1371, 1379, 1388, 1398, 1408, 1417, 1426, 1439, 1448, 1462, 1467, 1472, 1483, 1502} func functionNameV5(i int) string { - if i < 0 || i > 263 { + if i < 0 || i > 264 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 263 { + if id < 0 || id > 264 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 263; i++ { + for i := 0; i <= 264; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 263 { + if id < 0 || id > 264 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_bigint.go b/pkg/ride/functions_bigint.go index 0686c0f72..46ed0add6 100644 --- a/pkg/ride/functions_bigint.go +++ b/pkg/ride/functions_bigint.go @@ -292,21 +292,32 @@ func fractionBigIntRounds(_ Environment, args ...rideType) (rideType, error) { return nil, errors.Errorf("fractionBigIntRounds: unexpected argument type '%s'", args[2].instanceOf()) } d := big.NewInt(0).Set(v3.v) - if d.Cmp(zeroBigInt) == 0 { - return nil, errors.New("fractionBigIntRounds: division by zero") - } round, err := roundingMode(args[3]) if err != nil { return nil, errors.Wrap(err, "fractionBigIntRounds") } - // This algo is fully taken from Scala implementation + r, err := fractionBigIntLikeInScala(v, n, d, round) + if err != nil { + return nil, errors.Wrap(err, "fractionBigIntRounds") + } + if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { + return nil, errors.Errorf("fractionBigIntRounds: %s result is out of range", r.String()) + } + return rideBigInt{v: r}, nil +} + +// fractionBigIntLikeInScala the algo is fully taken from Scala implementation. +func fractionBigIntLikeInScala(v, n, d *big.Int, roundingMode decimal.RoundingMode) (*big.Int, error) { + if d.Cmp(zeroBigInt) == 0 { + return nil, errors.New("division by zero") + } p := v.Mul(v, n) s := big.NewInt(int64(p.Sign() * d.Sign())) pa := p.Abs(p) da := d.Abs(d) r, m := pa.QuoRem(pa, da, big.NewInt(0)) ms := big.NewInt(int64(m.Sign())) - switch round { + switch roundingMode { case decimal.ToZero: // Down r = r.Mul(r, s) case decimal.AwayFromZero: // Up @@ -363,12 +374,9 @@ func fractionBigIntRounds(_ Environment, args ...rideType) (rideType, error) { r = r.Mul(r, s) } default: - return nil, errors.New("fractionBigIntRounds: unsupported rounding mode") + return nil, errors.New("unsupported rounding mode") } - if r.Cmp(minBigInt) < 0 || r.Cmp(maxBigInt) > 0 { - return nil, errors.Errorf("fractionBigIntRounds: %s result is out of range", r.String()) - } - return rideBigInt{v: r}, nil + return r, nil } func unaryMinusBigInt(_ Environment, args ...rideType) (rideType, error) { diff --git a/pkg/ride/functions_bigint_test.go b/pkg/ride/functions_bigint_test.go index 825c8d05a..42867c1a6 100644 --- a/pkg/ride/functions_bigint_test.go +++ b/pkg/ride/functions_bigint_test.go @@ -262,6 +262,8 @@ func TestFractionBigInt(t *testing.T) { {[]rideType{toRideBigInt(8), toRideBigInt(4), toRideBigInt(2)}, false, toRideBigInt(16)}, {[]rideType{toRideBigInt(8), toRideBigInt(-2), toRideBigInt(-3)}, false, toRideBigInt(5)}, {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(-2), toRideBigInt(-3)}, false, rideBigInt{v: r1}}, + {[]rideType{rideBigInt{v: maxBigInt}, rideBigInt{v: maxBigInt}, rideBigInt{v: maxBigInt}}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{rideBigInt{v: minBigInt}, rideBigInt{v: minBigInt}, rideBigInt{v: minBigInt}}, false, rideBigInt{v: minBigInt}}, {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(1)}, true, nil}, {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(0)}, true, nil}, {[]rideType{toRideBigInt(2), toRideBigInt(2)}, true, nil}, @@ -309,6 +311,8 @@ func TestFractionBigIntRounds(t *testing.T) { {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(2), newHalfEven(nil)}, false, toRideBigInt(-4)}, {[]rideType{toRideBigInt(9), toRideBigInt(1), toRideBigInt(-2), newHalfEven(nil)}, false, toRideBigInt(-4)}, {[]rideType{toRideBigInt(-9), toRideBigInt(1), toRideBigInt(-2), newHalfEven(nil)}, false, toRideBigInt(4)}, + {[]rideType{rideBigInt{v: maxBigInt}, rideBigInt{v: maxBigInt}, rideBigInt{v: maxBigInt}, newCeiling(nil)}, false, rideBigInt{v: maxBigInt}}, + {[]rideType{rideBigInt{v: minBigInt}, rideBigInt{v: minBigInt}, rideBigInt{v: minBigInt}, newCeiling(nil)}, false, rideBigInt{v: minBigInt}}, {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(1), newFloor(nil)}, true, nil}, {[]rideType{rideBigInt{v: maxBigInt}, toRideBigInt(4), toRideBigInt(0), newFloor(nil)}, true, nil}, {[]rideType{toRideBigInt(2), toRideBigInt(2), toRideBigInt(3)}, true, nil}, diff --git a/pkg/ride/functions_int.go b/pkg/ride/functions_int.go index 81ba4c515..c7e887207 100644 --- a/pkg/ride/functions_int.go +++ b/pkg/ride/functions_int.go @@ -2,6 +2,7 @@ package ride import ( "encoding/binary" + "math/big" "strconv" "github.com/ericlagergren/decimal" @@ -152,11 +153,45 @@ func fraction(_ Environment, args ...rideType) (rideType, error) { return rideInt(res), nil } +func fractionIntRounds(_ Environment, args ...rideType) (rideType, error) { + if err := checkArgs(args, 4); err != nil { + return nil, errors.Wrap(err, "fraction") + } + value, ok := args[0].(rideInt) + if !ok { + return nil, errors.Errorf("fraction: unexpected argument type '%s'", args[0].instanceOf()) + } + v := big.NewInt(int64(value)) + numerator, ok := args[1].(rideInt) + if !ok { + return nil, errors.Errorf("fraction: unexpected argument type '%s'", args[1].instanceOf()) + } + n := big.NewInt(int64(numerator)) + denominator, ok := args[2].(rideInt) + if !ok { + return nil, errors.Errorf("fraction: unexpected argument type '%s'", args[2].instanceOf()) + } + d := big.NewInt(int64(denominator)) + round, err := roundingMode(args[3]) + if err != nil { + return nil, errors.Wrap(err, "fraction") + } + r, err := fractionBigIntLikeInScala(v, n, d, round) + if err != nil { + return nil, errors.Wrap(err, "fraction") + } + if !r.IsInt64() { + return nil, errors.New("fraction: result is out of int64 range") + } + return rideInt(r.Int64()), nil +} + func intToBytes(_ Environment, args ...rideType) (rideType, error) { i, err := intArg(args) if err != nil { return nil, errors.Wrap(err, "intToBytes") } + out := make([]byte, 8) binary.BigEndian.PutUint64(out, uint64(i)) return rideBytes(out), nil diff --git a/pkg/ride/functions_int_test.go b/pkg/ride/functions_int_test.go index 7770f6385..27c350f78 100644 --- a/pkg/ride/functions_int_test.go +++ b/pkg/ride/functions_int_test.go @@ -248,8 +248,14 @@ func TestFraction(t *testing.T) { }{ {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(6)}, false, rideInt(6148914691236517204)}, {[]rideType{rideInt(8), rideInt(4), rideInt(2)}, false, rideInt(16)}, + {[]rideType{rideInt(math.MaxInt64), rideInt(math.MinInt64), rideInt(math.MinInt64)}, false, rideInt(math.MaxInt64)}, + {[]rideType{rideInt(1), rideInt(math.MinInt64), rideInt(1)}, false, rideInt(math.MinInt64)}, + {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(1)}, true, nil}, {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(0)}, true, nil}, + {[]rideType{rideInt(1), rideInt(-1), rideInt(0)}, true, nil}, + {[]rideType{rideInt(math.MaxInt64), rideInt(math.MinInt64), rideInt(1)}, true, nil}, + {[]rideType{rideInt(2), rideInt(2)}, true, nil}, {[]rideType{rideInt(1), rideInt(2), rideUnit{}}, true, nil}, {[]rideType{rideInt(1), rideInt(2), rideString("x")}, true, nil}, @@ -266,6 +272,57 @@ func TestFraction(t *testing.T) { } } +func TestFractionIntRounds(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(6), newDown(nil)}, false, rideInt(6148914691236517204)}, + {[]rideType{rideInt(8), rideInt(4), rideInt(2), newDown(nil)}, false, rideInt(16)}, + {[]rideType{rideInt(math.MaxInt64), rideInt(math.MinInt64), rideInt(math.MinInt64), newHalfEven(nil)}, false, rideInt(math.MaxInt64)}, + {[]rideType{rideInt(1), rideInt(math.MinInt64), rideInt(1), newHalfEven(nil)}, false, rideInt(math.MinInt64)}, + {[]rideType{rideInt(5), rideInt(1), rideInt(2), newDown(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(5), rideInt(1), rideInt(2), newHalfUp(nil)}, false, rideInt(3)}, + {[]rideType{rideInt(5), rideInt(1), rideInt(2), newHalfEven(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(5), rideInt(1), rideInt(2), newCeiling(nil)}, false, rideInt(3)}, + {[]rideType{rideInt(5), rideInt(1), rideInt(2), newFloor(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(2), rideInt(4), rideInt(5), newDown(nil)}, false, rideInt(1)}, + {[]rideType{rideInt(2), rideInt(4), rideInt(5), newHalfUp(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(2), rideInt(4), rideInt(5), newHalfEven(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(2), rideInt(4), rideInt(5), newCeiling(nil)}, false, rideInt(2)}, + {[]rideType{rideInt(2), rideInt(4), rideInt(5), newFloor(nil)}, false, rideInt(1)}, + {[]rideType{rideInt(-2), rideInt(4), rideInt(5), newDown(nil)}, false, rideInt(-1)}, + {[]rideType{rideInt(-2), rideInt(4), rideInt(5), newHalfUp(nil)}, false, rideInt(-2)}, + {[]rideType{rideInt(-2), rideInt(4), rideInt(5), newHalfEven(nil)}, false, rideInt(-2)}, + {[]rideType{rideInt(-2), rideInt(4), rideInt(5), newCeiling(nil)}, false, rideInt(-1)}, + {[]rideType{rideInt(-2), rideInt(4), rideInt(5), newFloor(nil)}, false, rideInt(-2)}, + {[]rideType{rideInt(-5), rideInt(11), rideInt(10), newDown(nil)}, false, rideInt(-5)}, + {[]rideType{rideInt(-5), rideInt(11), rideInt(10), newHalfUp(nil)}, false, rideInt(-6)}, + {[]rideType{rideInt(-5), rideInt(11), rideInt(10), newHalfEven(nil)}, false, rideInt(-6)}, + {[]rideType{rideInt(-5), rideInt(11), rideInt(10), newCeiling(nil)}, false, rideInt(-5)}, + {[]rideType{rideInt(-5), rideInt(11), rideInt(10), newFloor(nil)}, false, rideInt(-6)}, + {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(1), newDown(nil)}, true, nil}, + {[]rideType{rideInt(math.MaxInt64), rideInt(4), rideInt(0), newDown(nil)}, true, nil}, + {[]rideType{rideInt(math.MaxInt64), rideInt(math.MinInt64), rideInt(1), newHalfEven(nil)}, true, nil}, + {[]rideType{rideInt(1), rideInt(-1), rideInt(0), newHalfEven(nil)}, true, nil}, + {[]rideType{rideInt(2), rideInt(2), newDown(nil)}, true, nil}, + {[]rideType{rideInt(1), rideInt(2), rideUnit{}, newDown(nil)}, true, nil}, + {[]rideType{rideInt(1), rideInt(2), rideInt(4)}, true, nil}, + {[]rideType{rideInt(1), rideInt(2), rideString("x")}, true, nil}, + {[]rideType{rideInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := fractionIntRounds(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + func TestIntToBytes(t *testing.T) { for _, test := range []struct { args []rideType diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 65f8ae783..3dd25c5c6 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -499,6 +499,7 @@ func functionsV5() map[string]string { m["1081"] = "calculateLeaseID" m["1092"] = "simplifiedLease" m["1093"] = "fullLease" + m["fraction"] = "fractionIntRounds" m["LeaseCancel"] = "leaseCancel" m["@extrNative(1055)"] = "intValueFromSelfState" m["@extrNative(1056)"] = "booleanValueFromSelfState" @@ -509,6 +510,7 @@ func functionsV5() map[string]string { func catalogueV5() map[string]int { m := catalogueV4() + m["107"] = 14 m["118"] = 200 m["119"] = 200 m["310"] = 1 @@ -543,6 +545,7 @@ func catalogueV5() map[string]int { m["1081"] = 1 m["1092"] = 1 m["1093"] = 1 + m["fraction"] = 17 m["LeaseCancel"] = 1 m["@extrNative(1055)"] = 10 m["@extrNative(1056)"] = 10 From a48a0e04216073590d611797fcfac5816c78c157 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 27 Apr 2021 13:21:11 +0300 Subject: [PATCH 33/52] Merge master into vertion 0.9 (#458) * Costs of RIDE functions transactionHeightByID and blockInfoByHeight reduced for version 4 of standard library (#406) * Fixed empty senderPublicKey field while asset scritp execution. Fixed an issue then half empty TransferScriptAction produced on invalid asset. (#407) * Fixed calculation of size dependant part of fee of protobuf version of DataTransaction (#409) * RIDE function takeString works with string as UTF-16 string (#418) * Switchable bloom filter. (#424) * Switchable bloom filter. * Fix tests. * Proofs validation added to protobuf and json unmarshaling (#429) * Added error loggs handling (#433) * Added errors handling * Changed function name * Deleted useless struct * Changed errors' logs for shutting down * Changed func name and renamed back a few logs * RIDE function to remove element of list by index implemented and tested. (#435) * Fix microblock signature (#430) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Added block state cache (#434) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Added block state cache * Changed the condition of rollback * Changed position of condition of rollback * Adding block states receiving microblocks * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Block cache cleaning moved to key block application functions. * Functions to check that block already exists added to FSM's block applier. * Cache size debug messages added. Fixed block ID to get from cache. Co-authored-by: Alexey Kiselev * Move error logging to debug (#437) * Log level of errors on appending transaction to UTX set to DEBUG * Network connection errrors moved to DEBUG level * More network log messages moved to DEBUG level. Fixed an issue with invalid blocks added to blocks cache. Naming fixed. * Error on state changing while mining micro block moved to DEBUG level. Handling of micro-block mining task added to Sync FSM. * RIDE function addressToString now accepts invalid address (#444) * Update version-0.9 branch. Co-authored-by: Frozen Co-authored-by: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> --- cmd/custom/node.go | 42 ++-- cmd/forkdetector/internal/api.go | 16 +- cmd/node/node.go | 30 +-- cmd/retransmitter/main.go | 4 +- .../retransmit/network/incoming_peer.go | 11 +- .../retransmit/network/outgoing_peer.go | 2 +- cmd/wmd/internal/api.go | 4 +- pkg/api/node_api.go | 13 +- pkg/metrics/metrics.go | 228 +++++++++++++++++- pkg/miner/utxpool/pool.go | 12 +- pkg/node/actions_by_type.go | 50 ++-- pkg/node/blocks_applier/blocks_applier.go | 113 +++++++-- .../blocks_applier/blocks_applier_test.go | 5 +- pkg/node/node.go | 18 +- pkg/node/peer_manager/peer_manager.go | 22 +- pkg/node/state_fsm/default.go | 6 +- pkg/node/state_fsm/errs.go | 8 +- pkg/node/state_fsm/fsm.go | 6 +- pkg/node/state_fsm/fsm_common.go | 11 +- pkg/node/state_fsm/fsm_idle.go | 14 +- pkg/node/state_fsm/fsm_ng.go | 181 ++++++++++---- pkg/node/state_fsm/fsm_sync.go | 42 ++-- pkg/node/state_fsm/fsm_sync_test.go | 2 +- pkg/node/state_fsm/fsm_test.go | 2 +- pkg/node/state_fsm/sync_internal/internal.go | 10 +- pkg/node/state_fsm/tasks/tasks.go | 20 +- pkg/node/state_fsm/tasks/tasks_test.go | 6 +- pkg/p2p/incoming/Incoming.go | 12 +- pkg/p2p/outgoing/outgoing.go | 8 +- pkg/p2p/peer/handle.go | 10 +- pkg/p2p/peer/handle_test.go | 4 +- pkg/proto/block_test.go | 19 +- pkg/proto/errors.go | 19 ++ pkg/proto/microblock.go | 48 ++-- pkg/proto/microblock_test.go | 13 + pkg/proto/proto.go | 199 +++++++-------- pkg/proto/proto_test.go | 22 +- pkg/ride/functions.go | 40 +-- pkg/ride/functions_list.go | 21 ++ pkg/ride/functions_list_test.go | 37 +++ pkg/ride/functions_proto.go | 3 + pkg/ride/functions_test.go | 2 +- pkg/ride/generate/main.go | 2 + pkg/services/services.go | 2 + pkg/state/appender.go | 22 +- pkg/state/state_test.go | 31 ++- 46 files changed, 959 insertions(+), 433 deletions(-) create mode 100644 pkg/proto/errors.go create mode 100644 pkg/ride/functions_list_test.go diff --git a/cmd/custom/node.go b/cmd/custom/node.go index 030115944..43cbe000c 100644 --- a/cmd/custom/node.go +++ b/cmd/custom/node.go @@ -47,7 +47,7 @@ var ( grpcAddr = flag.String("grpc-address", "127.0.0.1:7475", "Address for gRPC API") cfgPath = flag.String("cfg-path", "", "Path to configuration JSON file. No default value.") enableGrpcApi = flag.Bool("enable-grpc-api", true, "Enables/disables gRPC API") - buildExtendedApi = flag.Bool("build-extended-api", false, "Builds extended API. Note that state must be reimported in case it wasn't imported with similar flag set") + buildExtendedApi = flag.Bool("build-extended-api", false, "Builds extended API. Note that state must be re-imported in case it wasn't imported with similar flag set") serveExtendedApi = flag.Bool("serve-extended-api", false, "Serves extended API requests since the very beginning. The default behavior is to import until first block close to current time, and start serving at this point") buildStateHashes = flag.Bool("build-state-hashes", false, "Calculate and store state hashes for each block height.") minerVoteFeatures = flag.String("vote", "", "Miner vote features") @@ -130,7 +130,7 @@ func main() { } } - ntptm, err := ntptime.TryNew("pool.ntp.org", 10) + ntpTime, err := ntptime.TryNew("pool.ntp.org", 10) if err != nil { zap.S().Error(err) return @@ -144,14 +144,14 @@ func main() { ctx, cancel := context.WithCancel(context.Background()) - go ntptm.Run(ctx, 2*time.Minute) + go ntpTime.Run(ctx, 2*time.Minute) params := state.DefaultStateParams() params.StoreExtendedApiData = *buildExtendedApi params.ProvideExtendedApi = *serveExtendedApi params.BuildStateHashes = *buildStateHashes - params.Time = ntptm - state, err := state.NewState(path, params, custom) + params.Time = ntpTime + nodeState, err := state.NewState(path, params, custom) if err != nil { zap.S().Error(err) cancel() @@ -159,7 +159,7 @@ func main() { } // Check if we need to start serving extended API right now. - if err := node.MaybeEnableExtendedApi(state, ntptm); err != nil { + if err := node.MaybeEnableExtendedApi(nodeState, ntpTime); err != nil { zap.S().Error(err) cancel() return @@ -172,7 +172,7 @@ func main() { return } - features, err = miner.ValidateFeatures(state, features) + features, err = miner.ValidateFeatures(nodeState, features) if err != nil { cancel() zap.S().Error(err) @@ -186,7 +186,7 @@ func main() { parent := peer.NewParent() - utx := utxpool.New(10000, utxpool.NewValidator(state, ntptm, outdateSeconds*1000), custom) + utx := utxpool.New(10000, utxpool.NewValidator(nodeState, ntpTime, outdateSeconds*1000), custom) peerSpawnerImpl := peer_manager.NewPeerSpawner(btsPool, parent, conf.WavesNetwork, declAddr, "gowaves", uint64(rand.Int()), version) @@ -196,10 +196,10 @@ func main() { go peerManager.Run(ctx) scheduler := scheduler2.NewScheduler( - state, + nodeState, wal, custom, - ntptm, + ntpTime, scheduler2.NewMinerConsensus(peerManager, *minPeersMining), proto.NewTimestampFromUSeconds(outdateSeconds), ) @@ -211,8 +211,8 @@ func main() { InternalCh := messages.NewInternalChannel() - var services = services.Services{ - State: state, + var nodeServices = services.Services{ + State: nodeState, Peers: peerManager, Scheduler: scheduler, BlocksApplier: blockApplier, @@ -222,31 +222,31 @@ func main() { LoggableRunner: logRunner, MicroBlockCache: microblock_cache.NewMicroblockCache(), InternalChannel: InternalCh, - Time: ntptm, + Time: ntpTime, } - Miner := miner.NewMicroblockMiner(services, features, reward, proto.NewTimestampFromUSeconds(outdateSeconds)) + Miner := miner.NewMicroblockMiner(nodeServices, features, reward, proto.NewTimestampFromUSeconds(outdateSeconds)) go miner.Run(ctx, Miner, scheduler, InternalCh) - n := node.NewNode(services, declAddr, declAddr, proto.NewTimestampFromUSeconds(outdateSeconds)) + n := node.NewNode(nodeServices, declAddr, declAddr, proto.NewTimestampFromUSeconds(outdateSeconds)) go n.Run(ctx, parent, InternalCh) if len(conf.Addresses) > 0 { - adrs := strings.Split(conf.Addresses, ",") - for _, addr := range adrs { + addresses := strings.Split(conf.Addresses, ",") + for _, addr := range addresses { peerManager.AddAddress(ctx, addr) } } // TODO hardcore - app, err := api.NewApp("integration-test-rest-api", scheduler, services) + app, err := api.NewApp("integration-test-rest-api", scheduler, nodeServices) if err != nil { zap.S().Error(err) cancel() return } - webApi := api.NewNodeApi(app, state, n) + webApi := api.NewNodeApi(app, nodeState, n) go func() { zap.S().Info("===== ", conf.HttpAddr) err := api.Run(ctx, conf.HttpAddr, webApi) @@ -256,7 +256,7 @@ func main() { }() if *enableGrpcApi { - grpcServer, err := server.NewServer(services) + grpcServer, err := server.NewServer(nodeServices) if err != nil { zap.S().Errorf("Failed to create gRPC server: %v", err) } @@ -273,7 +273,7 @@ func main() { signal.Notify(gracefulStop, syscall.SIGINT) sig := <-gracefulStop - zap.S().Infow("Caught signal, stopping", "signal", sig) + zap.S().Infof("Caught signal '%s', stopping...", sig) cancel() n.Close() <-time.After(1 * time.Second) diff --git a/cmd/forkdetector/internal/api.go b/cmd/forkdetector/internal/api.go index 720a69029..1247c22d6 100644 --- a/cmd/forkdetector/internal/api.go +++ b/cmd/forkdetector/internal/api.go @@ -106,7 +106,7 @@ func (a *api) Start() <-chan struct{} { zap.S().Debug("Shutting down API...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) err := a.srv.Shutdown(ctx) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { zap.S().Errorf("Failed to shutdown API server: %v", err) } cancel() @@ -119,7 +119,7 @@ func (a *api) routes() chi.Router { r := chi.NewRouter() r.Get("/status", a.status) // Status information r.Get("/peers/all", a.peers) // Returns the list of all known peers - r.Get("/peers/friendly", a.friendly) // Returns the list of peers that have been successfully handshaked at least once + r.Get("/peers/friendly", a.friendly) // Returns the list of peers that have been successfully connected at least once r.Get("/connections", a.connections) // Returns the list of active connections r.Get("/forks", a.forks) // Returns the combined info about forks for all connected peers r.Get("/all-forks", a.allForks) // Returns the combined info about all registered forks @@ -129,7 +129,7 @@ func (a *api) routes() chi.Router { return r } -func (a *api) status(w http.ResponseWriter, r *http.Request) { +func (a *api) status(w http.ResponseWriter, _ *http.Request) { goroutines := runtime.NumGoroutine() stats := a.drawer.stats() peers, err := a.registry.Peers() @@ -159,7 +159,7 @@ func (a *api) status(w http.ResponseWriter, r *http.Request) { } } -func (a *api) peers(w http.ResponseWriter, r *http.Request) { +func (a *api) peers(w http.ResponseWriter, _ *http.Request) { peers, err := a.registry.Peers() if err != nil { http.Error(w, fmt.Sprintf("Failed to complete request: %v", err), http.StatusInternalServerError) @@ -172,7 +172,7 @@ func (a *api) peers(w http.ResponseWriter, r *http.Request) { } } -func (a *api) friendly(w http.ResponseWriter, r *http.Request) { +func (a *api) friendly(w http.ResponseWriter, _ *http.Request) { peers, err := a.registry.FriendlyPeers() if err != nil { http.Error(w, fmt.Sprintf("Failed to complete request: %v", err), http.StatusInternalServerError) @@ -185,7 +185,7 @@ func (a *api) friendly(w http.ResponseWriter, r *http.Request) { } } -func (a *api) connections(w http.ResponseWriter, r *http.Request) { +func (a *api) connections(w http.ResponseWriter, _ *http.Request) { connections := a.registry.Connections() err := json.NewEncoder(w).Encode(connections) if err != nil { @@ -194,7 +194,7 @@ func (a *api) connections(w http.ResponseWriter, r *http.Request) { } } -func (a *api) forks(w http.ResponseWriter, r *http.Request) { +func (a *api) forks(w http.ResponseWriter, _ *http.Request) { nodes := a.registry.Connections() ips := make([]net.IP, len(nodes)) for i, n := range nodes { @@ -214,7 +214,7 @@ func (a *api) forks(w http.ResponseWriter, r *http.Request) { } } -func (a *api) allForks(w http.ResponseWriter, r *http.Request) { +func (a *api) allForks(w http.ResponseWriter, _ *http.Request) { nodes, err := a.registry.Peers() if err != nil { http.Error(w, fmt.Sprintf("Failed to complete request: %v", err), http.StatusInternalServerError) diff --git a/cmd/node/node.go b/cmd/node/node.go index d7145bd48..157a621f6 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -229,7 +229,7 @@ func main() { return } - ntptm, err := getNtp(ctx) + ntpTime, err := getNtp(ctx) if err != nil { zap.S().Error(err) cancel() @@ -247,7 +247,7 @@ func main() { params.StoreExtendedApiData = *buildExtendedApi params.ProvideExtendedApi = *serveExtendedApi params.BuildStateHashes = *buildStateHashes - params.Time = ntptm + params.Time = ntpTime if !*bloomFilter { params.DbParams.BloomFilterParams.Disable = true } @@ -273,7 +273,7 @@ func main() { } // Check if we need to start serving extended API right now. - if err := node.MaybeEnableExtendedApi(st, ntptm); err != nil { + if err := node.MaybeEnableExtendedApi(st, ntpTime); err != nil { zap.S().Error(err) cancel() return @@ -288,7 +288,7 @@ func main() { mb := 1024 * 1014 pool := bytespool.NewBytesPool(64, mb+(mb/2)) - utx := utxpool.New(uint64(1024*mb), utxpool.NewValidator(st, ntptm, outdatePeriodSeconds*1000), cfg) + utx := utxpool.New(uint64(1024*mb), utxpool.NewValidator(st, ntpTime, outdatePeriodSeconds*1000), cfg) parent := peer.NewParent() @@ -304,28 +304,28 @@ func main() { ) go peerManager.Run(ctx) - var sched Scheduler = scheduler.NewScheduler( + var minerScheduler Scheduler = scheduler.NewScheduler( st, wal, cfg, - ntptm, + ntpTime, scheduler.NewMinerConsensus(peerManager, *minPeersMining), proto.NewTimestampFromUSeconds(outdatePeriodSeconds), ) if *disableMiner { - sched = scheduler.DisabledScheduler{} + minerScheduler = scheduler.DisabledScheduler{} } blockApplier := blocks_applier.NewBlocksApplier() svs := services.Services{ State: st, Peers: peerManager, - Scheduler: sched, + Scheduler: minerScheduler, BlocksApplier: blockApplier, UtxPool: utx, Scheme: cfg.AddressSchemeCharacter, LoggableRunner: logRunner, - Time: ntptm, + Time: ntpTime, Wallet: wal, MicroBlockCache: microblock_cache.NewMicroblockCache(), InternalChannel: messages.NewInternalChannel(), @@ -334,21 +334,21 @@ func main() { mine := miner.NewMicroblockMiner(svs, features, reward, maxTransactionTimeForwardOffset) peerManager.SetConnectPeers(!*disableOutgoingConnections) - go miner.Run(ctx, mine, sched, svs.InternalChannel) + go miner.Run(ctx, mine, minerScheduler, svs.InternalChannel) n := node.NewNode(svs, declAddr, bindAddr, proto.NewTimestampFromUSeconds(outdatePeriodSeconds)) go n.Run(ctx, parent, svs.InternalChannel) - go sched.Reschedule() + go minerScheduler.Reschedule() if len(conf.Addresses) > 0 { - adrs := strings.Split(conf.Addresses, ",") - for _, addr := range adrs { + addresses := strings.Split(conf.Addresses, ",") + for _, addr := range addresses { peerManager.AddAddress(ctx, addr) } } - app, err := api.NewApp(*apiKey, sched, svs) + app, err := api.NewApp(*apiKey, minerScheduler, svs) if err != nil { zap.S().Error(err) cancel() @@ -390,7 +390,7 @@ func main() { signal.Notify(gracefulStop, syscall.SIGINT) sig := <-gracefulStop - zap.S().Infow("Caught signal, stopping", "signal", sig) + zap.S().Infof("Caught signal '%s', stopping...", sig) cancel() n.Close() <-time.After(1 * time.Second) diff --git a/cmd/retransmitter/main.go b/cmd/retransmitter/main.go index ebf8b1704..68c5a3e70 100644 --- a/cmd/retransmitter/main.go +++ b/cmd/retransmitter/main.go @@ -40,7 +40,7 @@ func memProfile(filename string) { if err := pprof.WriteHeapProfile(f); err != nil { zap.S().Fatal(err) } - f.Close() + _ = f.Close() } func skipUselessMessages(header proto.Header) bool { @@ -190,7 +190,7 @@ func main() { if memprofile != "" { memProfile(memprofile) } - zap.S().Infow("Caught signal, stopping", "signal", sig) + zap.S().Infof("Caught signal '%s', stopping...", sig) _ = srv.Shutdown(ctx) cancel() } diff --git a/cmd/retransmitter/retransmit/network/incoming_peer.go b/cmd/retransmitter/retransmit/network/incoming_peer.go index d7e9aa664..b5ebeee37 100644 --- a/cmd/retransmitter/retransmit/network/incoming_peer.go +++ b/cmd/retransmitter/retransmit/network/incoming_peer.go @@ -3,10 +3,11 @@ package network import ( "context" "fmt" - "github.com/wavesplatform/gowaves/pkg/p2p/peer" "net" "time" + "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/libs/bytespool" "github.com/wavesplatform/gowaves/pkg/p2p/conn" "github.com/wavesplatform/gowaves/pkg/proto" @@ -37,13 +38,13 @@ func RunIncomingPeer(ctx context.Context, params IncomingPeerParams) { _, err := readHandshake.ReadFrom(c) if err != nil { zap.S().Error("failed to read handshake: ", err) - c.Close() + _ = c.Close() return } select { case <-ctx.Done(): - c.Close() + _ = c.Close() return default: } @@ -64,13 +65,13 @@ func RunIncomingPeer(ctx context.Context, params IncomingPeerParams) { _, err = writeHandshake.WriteTo(c) if err != nil { zap.S().Error("failed to write handshake: ", err) - c.Close() + _ = c.Close() return } select { case <-ctx.Done(): - c.Close() + _ = c.Close() return default: } diff --git a/cmd/retransmitter/retransmit/network/outgoing_peer.go b/cmd/retransmitter/retransmit/network/outgoing_peer.go index d985a3239..85012c4d9 100644 --- a/cmd/retransmitter/retransmit/network/outgoing_peer.go +++ b/cmd/retransmitter/retransmit/network/outgoing_peer.go @@ -112,7 +112,7 @@ func (a *OutgoingPeer) connect(ctx context.Context, wavesNetwork string, remote select { case <-ctx.Done(): - c.Close() + _ = c.Close() return nil, nil, errors.Wrap(ctx.Err(), "OutgoingPeer.connect") default: } diff --git a/cmd/wmd/internal/api.go b/cmd/wmd/internal/api.go index 9dba57eda..31294a377 100644 --- a/cmd/wmd/internal/api.go +++ b/cmd/wmd/internal/api.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/pkg/errors" + "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "github.com/rakyll/statik/fs" @@ -98,7 +100,7 @@ func NewDataFeedAPI(interrupt <-chan struct{}, logger *zap.Logger, storage *stat zap.S().Info("Shutting down API...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) err := apiServer.Shutdown(ctx) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { zap.S().Errorf("Failed to shutdown API server: %v", err) } cancel() diff --git a/pkg/api/node_api.go b/pkg/api/node_api.go index 5331a04d7..3c1ab86e1 100644 --- a/pkg/api/node_api.go +++ b/pkg/api/node_api.go @@ -4,11 +4,14 @@ import ( "context" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "strconv" "time" + "github.com/pkg/errors" + "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "github.com/wavesplatform/gowaves/pkg/node" @@ -57,13 +60,17 @@ func NewNodeApi(app *App, state state.State, node *node.Node) *NodeApi { } func (a *NodeApi) TransactionsBroadcast(w http.ResponseWriter, r *http.Request) { + defer func(body io.ReadCloser) { + err := body.Close() + if err != nil { + zap.S().Warnf("Failed to close body: %v", err) + } + }(r.Body) b, err := ioutil.ReadAll(r.Body) - defer r.Body.Close() if err != nil { handleError(w, &BadRequestError{err}) return } - err = a.app.TransactionsBroadcast(r.Context(), b) if err != nil { handleError(w, err) @@ -195,7 +202,7 @@ func Run(ctx context.Context, address string, n *NodeApi) error { <-ctx.Done() zap.S().Info("Shutting down API...") err := apiServer.Shutdown(ctx) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { zap.S().Errorf("Failed to shutdown API server: %v", err) } }() diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 0300d9e36..1e5c5e948 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -11,6 +11,7 @@ import ( influx "github.com/influxdata/influxdb1-client/v2" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "go.uber.org/zap" ) @@ -29,6 +30,44 @@ const ( eventMined = "Mined" ) +/* + +Notes on InfluxDB schema design. + +Both tags and fields are key-value pairs but with one significant difference is that tags are automatically indexed. +Because fields are not being indexed, every query where InfluxDB is asked to find a specified field, it needs to +sequentially scan every value of the field column. On the other hand, to index tags InfluxDB would try to construct an +inverted index in memory, which would always be growing with the cardinality. + +A rule of thumb would be to persist highly dynamic values as fields and only use tags for GROUP BY clauses. + +Tag keys and values are stored only once and always as strings, where field values and timestamps are stored per-point. +This however doesn't affect the memory footprint, only the storage requirements. + +Excerpt from the documentation: + +In general, your queries should guide what gets stored as a tag and what gets stored as a field: + + * Store commonly-queried meta data in tags. + * Store data in fields if each data point contains a different value. + * Store numeric values as fields (tag values only support string values). + +Tags containing highly variable information like unique IDs, hashes, and random strings lead to a large number of +series, also known as high series cardinality. + +High series cardinality is a primary driver of high memory usage for many database workloads. InfluxDB uses +measurements and tags to create indexes and speed up reads. However, when too many indexes created, both writes and +reads may start to slow down. Therefore, if a system has memory constraints, consider storing high-cardinality data as +a field rather than a tag. + +Use the following conventions when naming your tag and field keys: + + * Avoid keywords in tag and field names + * Avoid the same tag and field name + * Avoid encoding data in measurement names + * Avoid more than one piece of information in one tag + +*/ var ( once sync.Once rep *reporter = nil @@ -133,10 +172,96 @@ func BlockMined(block *proto.Block, height proto.Height) { reportBlock(t, f) } +func FSMKeyBlockReceived(fsm string, block *proto.Block, source string) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).block().received() + f := emptyFields().blockID(block.BlockID()).referenceID(block.Parent).source(source).blockTS(block.Timestamp).genPK(block.GenPublicKey) + reportFSM(t, f) +} + +func FSMKeyBlockGenerated(fsm string, block *proto.Block) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).block().generated() + f := emptyFields().blockID(block.BlockID()).referenceID(block.Parent) + reportFSM(t, f) +} + +func FSMKeyBlockApplied(fsm string, block *proto.Block) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).block().applied() + f := emptyFields().blockID(block.BlockID()).referenceID(block.Parent) + reportFSM(t, f) +} + +func FSMKeyBlockDeclined(fsm string, block *proto.Block, err error) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).block().declined() + f := emptyFields().blockID(block.BlockID()).referenceID(block.Parent).error(err) + reportFSM(t, f) +} + +func FSMMicroBlockReceived(fsm string, microblock *proto.MicroBlock, source string) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).microblock().received() + f := emptyFields().blockID(microblock.TotalBlockID).referenceID(microblock.Reference).source(source) + reportFSM(t, f) +} + +func FSMMicroBlockGenerated(fsm string, microblock *proto.MicroBlock) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).microblock().generated() + f := emptyFields().blockID(microblock.TotalBlockID).referenceID(microblock.Reference).signature(microblock.TotalResBlockSigField) + reportFSM(t, f) +} + +func FSMMicroBlockDeclined(fsm string, microblock *proto.MicroBlock, err error) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).microblock().declined() + f := emptyFields().blockID(microblock.TotalBlockID).referenceID(microblock.Reference).signature(microblock.TotalResBlockSigField).error(err) + reportFSM(t, f) +} + +func FSMMicroBlockApplied(fsm string, microblock *proto.MicroBlock) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).microblock().applied() + f := emptyFields().blockID(microblock.TotalBlockID).referenceID(microblock.Reference).signature(microblock.TotalResBlockSigField) + reportFSM(t, f) +} + +func FSMScore(fsm string, score *proto.Score, source string) { + if rep == nil { + return + } + t := emptyTags().node().fsm(fsm).score().received() + f := emptyFields().score(score).source(source) + reportFSM(t, f) +} + type tags map[string]string -func newTags() tags { +func emptyTags() tags { t := make(map[string]string) + return t +} + +func newTags() tags { + t := emptyTags() t["node"] = strconv.Itoa(rep.id) return t } @@ -146,6 +271,51 @@ func (t tags) withHost() tags { return t } +func (t tags) node() tags { + t["node"] = strconv.Itoa(rep.id) + return t +} + +func (t tags) fsm(fsm string) tags { + t["fsm"] = fsm + return t +} + +func (t tags) block() tags { + t["object"] = "block" + return t +} + +func (t tags) microblock() tags { + t["object"] = "micro" + return t +} + +func (t tags) received() tags { + t["event"] = "received" + return t +} + +func (t tags) generated() tags { + t["event"] = "generated" + return t +} + +func (t tags) declined() tags { + t["event"] = "declined" + return t +} + +func (t tags) applied() tags { + t["event"] = "applied" + return t +} + +func (t tags) score() tags { + t["object"] = "score" + return t +} + func (t tags) withEvent(event string) tags { t["event"] = event return t @@ -183,12 +353,57 @@ func (t tags) withExtension() tags { type fields map[string]interface{} -func newFields() fields { +func emptyFields() fields { f := make(map[string]interface{}) + return f +} + +func newFields() fields { + f := emptyFields() f["node"] = rep.id return f } +func (f fields) blockID(id proto.BlockID) fields { + f["block_id"] = id.String() + return f +} + +func (f fields) source(source string) fields { + f["source"] = source + return f +} + +func (f fields) referenceID(id proto.BlockID) fields { + f["reference_id"] = id.String() + return f +} + +func (f fields) error(err error) fields { + f["error"] = err.Error() + return f +} + +func (f fields) score(score *proto.Score) fields { + f["score"] = score.String() + return f +} + +func (f fields) blockTS(ts uint64) fields { + f["block_ts"] = ts + return f +} + +func (f fields) genPK(pk crypto.PublicKey) fields { + f["gen_pk"] = pk.String() + return f +} + +func (f fields) signature(sig crypto.Signature) fields { + f["sig"] = sig.String() + return f +} + func (f fields) withBaseTarget(bt uint64) fields { f["bt"] = int(bt) return f @@ -332,6 +547,15 @@ func reportBlock(t tags, f fields) { rep.in <- p } +func reportFSM(t tags, f fields) { + p, err := influx.NewPoint("fsm", t, f, time.Now()) + if err != nil { + zap.S().Warn("Failed to create metrics point 'fsm': %v", err) + return + } + rep.in <- p +} + func shortID(id proto.BlockID) string { return id.String()[:6] } diff --git a/pkg/miner/utxpool/pool.go b/pkg/miner/utxpool/pool.go index cb87105a0..ae0287e44 100644 --- a/pkg/miner/utxpool/pool.go +++ b/pkg/miner/utxpool/pool.go @@ -87,11 +87,11 @@ func (a *UtxImpl) AddBytes(bts []byte) error { return a.addWithBytes(t, bts) } -// TODO: add flag here to distinguish adding using API and accepting -// through the network from other nodes. -// When API is used, we should check all scripts completely. -// When adding from the network, only free complexity limit is checked. func (a *UtxImpl) AddWithBytes(t proto.Transaction, b []byte) error { + // TODO: add flag here to distinguish adding using API and accepting + // through the network from other nodes. + // When API is used, we should check all scripts completely. + // When adding from the network, only free complexity limit is checked. a.mu.Lock() defer a.mu.Unlock() return a.addWithBytes(t, b) @@ -113,7 +113,7 @@ func (a *UtxImpl) addWithBytes(t proto.Transaction, b []byte) error { return err } if a.exists(t) { - return errors.Errorf("transaction with id %s exists", base58.Encode(tID)) + return proto.NewInfoMsg(errors.Errorf("transaction with id %s exists", base58.Encode(tID))) } err = a.validator.Validate(t) if err != nil { @@ -136,7 +136,7 @@ func (a *UtxImpl) Count() int { return len(a.transactions) } -func makeDigest(b []byte, e error) crypto.Digest { +func makeDigest(b []byte, _ error) crypto.Digest { d := crypto.Digest{} copy(d[:], b) return d diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index 40d88dca6..045a36123 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -2,7 +2,6 @@ package node import ( "math/big" - "net" "reflect" "github.com/pkg/errors" @@ -33,7 +32,7 @@ func GetPeersAction(services services.Services, mess peer.ProtoMessage, fsm stat var out []proto.PeerInfo for _, r := range rs { out = append(out, proto.PeerInfo{ - Addr: net.IP(r.IP[:]), + Addr: r.IP[:], Port: uint16(r.Port), }) } @@ -85,17 +84,17 @@ func GetBlockAction(services services.Services, mess peer.ProtoMessage, fsm stat return fsm, nil, nil } -// received asked earlier signatures -func SignaturesAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { - sigs := mess.Message.(*proto.SignaturesMessage).Signatures - blockIDs := make([]proto.BlockID, len(sigs)) - for i, sig := range sigs { +// SignaturesAction receives requested earlier signatures +func SignaturesAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { + signatures := mess.Message.(*proto.SignaturesMessage).Signatures + blockIDs := make([]proto.BlockID, len(signatures)) + for i, sig := range signatures { blockIDs[i] = proto.NewBlockIDFromSignature(sig) } return fsm.BlockIDs(mess.ID, blockIDs) } -// peers asks us about our signatures +// GetSignaturesAction replies to signature requests func GetSignaturesAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { for _, sig := range mess.Message.(*proto.GetSignaturesMessage).Signatures { block, err := services.State.Header(proto.NewBlockIDFromSignature(sig)) @@ -126,7 +125,7 @@ func sendSignatures(services services.Services, block *proto.BlockHeader, p peer out = append(out, b.BlockSignature) } - // if we put smth except first block + // There are block signatures to send in addition to requested one if len(out) > 1 { p.SendMessage(&proto.SignaturesMessage{ Signatures: out, @@ -152,7 +151,7 @@ func sendBlockIds(services services.Services, block *proto.BlockHeader, p peer.P out = append(out, b.BlockID()) } - // if we put smth except first block + // There are block signatures to send in addition to requested one if len(out) > 1 { p.SendMessage(&proto.BlockIdsMessage{ Blocks: out, @@ -160,8 +159,8 @@ func sendBlockIds(services services.Services, block *proto.BlockHeader, p peer.P } } -// remote node mined microblock and sent us info about it. -func MicroBlockInvAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { +// MicroBlockInvAction handles notification about new microblock. +func MicroBlockInvAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { inv := &proto.MicroBlockInv{} err := inv.UnmarshalBinary(mess.Message.(*proto.MicroBlockInvMessage).Body) if err != nil { @@ -170,7 +169,7 @@ func MicroBlockInvAction(services services.Services, mess peer.ProtoMessage, fsm return fsm.MicroBlockInv(mess.ID, inv) } -// Our miner mined microblock, sent MicroblockInv to other nodes, they asked us about Microblock. +// MicroBlockRequestAction handles microblock requests. func MicroBlockRequestAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { blockID, err := proto.NewBlockIDFromBytes(mess.Message.(*proto.MicroBlockRequestMessage).TotalBlockSig) if err != nil { @@ -192,7 +191,7 @@ func MicroBlockAction(services services.Services, mess peer.ProtoMessage, fsm st return fsm.MicroBlock(mess.ID, micro) } -// arrived protobuf block +// PBBlockAction handles protobuf block message. func PBBlockAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { b := &proto.Block{} err := b.UnmarshalFromProtobuf(mess.Message.(*proto.PBBlockMessage).PBBlockBytes) @@ -204,7 +203,7 @@ func PBBlockAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FS return fsm.Block(mess.ID, b) } -func PBMicroBlockAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { +func PBMicroBlockAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { micro := &proto.MicroBlock{} err := micro.UnmarshalFromProtobuf(mess.Message.(*proto.PBMicroBlockMessage).MicroBlockBytes) if err != nil { @@ -229,13 +228,24 @@ func BlockIdsAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.F return fsm.BlockIDs(mess.ID, mess.Message.(*proto.BlockIdsMessage).Blocks) } -// TODO broadcast +// TransactionAction handles new transaction message. func TransactionAction(s services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { - tbts := mess.Message.(*proto.TransactionMessage).Transaction - t, err := proto.BytesToTransaction(tbts, s.Scheme) + b := mess.Message.(*proto.TransactionMessage).Transaction + tx, err := proto.BytesToTransaction(b, s.Scheme) if err != nil { return fsm, nil, err } + return fsm.Transaction(mess.ID, tx) +} + +// PBTransactionAction handles protobuf transaction message. +func PBTransactionAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { + b := mess.Message.(*proto.PBTransactionMessage).Transaction + t, err := proto.SignedTxFromProtobuf(b) + if err != nil { + return fsm, nil, err + } + // TODO add transaction re-broadcast return fsm.Transaction(mess.ID, t) } @@ -255,7 +265,7 @@ func CreateActions() map[reflect.Type]Action { reflect.TypeOf(&proto.PBMicroBlockMessage{}): PBMicroBlockAction, reflect.TypeOf(&proto.GetBlockIdsMessage{}): GetBlockIdsAction, reflect.TypeOf(&proto.BlockIdsMessage{}): BlockIdsAction, - - reflect.TypeOf(&proto.TransactionMessage{}): TransactionAction, + reflect.TypeOf(&proto.TransactionMessage{}): TransactionAction, + reflect.TypeOf(&proto.PBTransactionMessage{}): PBTransactionAction, } } diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index 95bf852e6..a63a0bf1c 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -21,64 +21,75 @@ type innerState interface { RollbackToHeight(height proto.Height) error } -func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (*proto.Block, proto.Height, error) { +func (a *innerBlocksApplier) exists(storage innerState, block *proto.Block) (bool, error) { + _, err := storage.Block(block.BlockID()) + if err == nil { + return true, nil + } + if state.IsNotFound(err) { + return false, nil + } + return false, err +} + +func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (proto.Height, error) { if len(blocks) == 0 { - return nil, 0, errors.New("empty blocks") + return 0, errors.New("empty blocks") } firstBlock := blocks[0] // check first block if exists _, err := storage.Block(firstBlock.BlockID()) if err == nil { - return nil, 0, errors.Errorf("first block %s exists", firstBlock.BlockID().String()) + return 0, proto.NewInfoMsg(errors.Errorf("first block %s exists", firstBlock.BlockID().String())) } if !state.IsNotFound(err) { - return nil, 0, errors.Wrap(err, "unknown error") + return 0, errors.Wrap(err, "unknown error") } currentHeight, err := storage.Height() if err != nil { - return nil, 0, err + return 0, err } // current score. Main idea is to find parent block, and check if score // of all passed blocks higher than currentScore. If yes, we can add blocks currentScore, err := storage.ScoreAtHeight(currentHeight) if err != nil { - return nil, 0, err + return 0, err } // try to find parent. If not - we can't add blocks, skip it parentHeight, err := storage.BlockIDToHeight(firstBlock.Parent) if err != nil { - return nil, 0, errors.Wrapf(err, "BlocksApplier: failed get parent height, firstBlock id %s, for firstBlock %s", - firstBlock.Parent.String(), firstBlock.BlockID().String()) + return 0, proto.NewInfoMsg(errors.Wrapf(err, "failed get parent height, firstBlock id %s, for firstBlock %s", + firstBlock.Parent.String(), firstBlock.BlockID().String())) } // calculate score of all passed blocks forkScore, err := calcMultipleScore(blocks) if err != nil { - return nil, 0, errors.Wrap(err, "failed calculate score of passed blocks") + return 0, errors.Wrap(err, "failed calculate score of passed blocks") } parentScore, err := storage.ScoreAtHeight(parentHeight) if err != nil { - return nil, 0, errors.Wrapf(err, "failed get score at %d", parentHeight) + return 0, errors.Wrapf(err, "failed get score at %d", parentHeight) } cumulativeScore := forkScore.Add(forkScore, parentScore) - if currentScore.Cmp(cumulativeScore) > 0 { // current height is higher - return nil, 0, errors.Errorf("BlockApplier: low fork score: current blockchain score (%s) is higher than fork's score (%s)", - currentScore.String(), cumulativeScore.String()) + if currentScore.Cmp(cumulativeScore) >= 0 { // current score is higher or the same as fork score - do not apply blocks + return 0, proto.NewInfoMsg(errors.Errorf("low fork score: current blockchain score (%s) is higher than or equal to fork's score (%s)", + currentScore.String(), cumulativeScore.String())) } // so, new blocks has higher score, try apply it. // Do we need rollback? if parentHeight == currentHeight { // no, don't rollback, just add blocks - newBlock, err := storage.AddNewDeserializedBlocks(blocks) + _, err := storage.AddNewDeserializedBlocks(blocks) if err != nil { - return nil, 0, err + return 0, err } - return newBlock, currentHeight + proto.Height(len(blocks)), nil + return currentHeight + proto.Height(len(blocks)), nil } deltaHeight := currentHeight - parentHeight if deltaHeight > 100 { // max number that we can rollback - return nil, 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) + return 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) } // save previously added blocks. If new firstBlock failed to add, then return them back @@ -86,26 +97,71 @@ func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (* for i := proto.Height(1); i <= deltaHeight; i++ { block, err := storage.BlockByHeight(parentHeight + i) if err != nil { - return nil, 0, errors.Wrapf(err, "failed to get firstBlock by height %d", parentHeight+i) + return 0, errors.Wrapf(err, "failed to get firstBlock by height %d", parentHeight+i) } rollbackBlocks = append(rollbackBlocks, block) } err = storage.RollbackToHeight(parentHeight) if err != nil { - return nil, 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) + return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) } // applying new blocks - newBlock, err := storage.AddNewDeserializedBlocks(blocks) + _, err = storage.AddNewDeserializedBlocks(blocks) if err != nil { // return back saved blocks _, err2 := storage.AddNewDeserializedBlocks(rollbackBlocks) if err2 != nil { - return nil, 0, errors.Wrap(err2, "failed rollback deserialized blocks") + return 0, errors.Wrap(err2, "failed rollback deserialized blocks") } - return nil, 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", firstBlock.BlockID().String()) + return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", firstBlock.BlockID().String()) } - return newBlock, parentHeight + proto.Height(len(blocks)), nil + return parentHeight + proto.Height(len(blocks)), nil +} + +func (a *innerBlocksApplier) applyMicro(storage innerState, block *proto.Block) (proto.Height, error) { + _, err := storage.Block(block.BlockID()) + if err == nil { + return 0, errors.Errorf("block '%s' already exist", block.BlockID().String()) + } + if !state.IsNotFound(err) { + return 0, errors.Wrap(err, "unexpected error") + } + + currentHeight, err := storage.Height() + if err != nil { + return 0, err + } + parentHeight, err := storage.BlockIDToHeight(block.Parent) + if err != nil { + return 0, errors.Wrapf(err, "failed get height of parent block '%s'", block.Parent.String()) + } + + if currentHeight-parentHeight != 1 { + return 0, errors.Errorf("invalid parent height %d", parentHeight) + } + + currentBlock, err := storage.BlockByHeight(currentHeight) + if err != nil { + return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) + } + + err = storage.RollbackToHeight(parentHeight) + if err != nil { + return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) + } + + // applying new blocks + _, err = storage.AddNewDeserializedBlocks([]*proto.Block{block}) + if err != nil { + // return back saved blocks + _, err2 := storage.AddNewDeserializedBlocks([]*proto.Block{currentBlock}) + if err2 != nil { + return 0, errors.Wrap(err2, "failed rollback block") + } + return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) + } + return currentHeight, nil } type BlocksApplier struct { @@ -118,9 +174,16 @@ func NewBlocksApplier() *BlocksApplier { } } +func (a *BlocksApplier) BlockExists(state state.State, block *proto.Block) (bool, error) { + return a.inner.exists(state, block) +} + func (a *BlocksApplier) Apply(state state.State, blocks []*proto.Block) (proto.Height, error) { - _, h, err := a.inner.apply(state, blocks) - return h, err + return a.inner.apply(state, blocks) +} + +func (a *BlocksApplier) ApplyMicro(state state.State, block *proto.Block) (proto.Height, error) { + return a.inner.applyMicro(state, block) } func calcMultipleScore(blocks []*proto.Block) (*big.Int, error) { diff --git a/pkg/node/blocks_applier/blocks_applier_test.go b/pkg/node/blocks_applier/blocks_applier_test.go index 18b851e3d..314accf33 100644 --- a/pkg/node/blocks_applier/blocks_applier_test.go +++ b/pkg/node/blocks_applier/blocks_applier_test.go @@ -50,7 +50,7 @@ func TestApply_ValidBlockWithRollback(t *testing.T) { require.NoError(t, err) ba := innerBlocksApplier{} - _, height, err := ba.apply(mockState, []*proto.Block{block2}) + height, err := ba.apply(mockState, []*proto.Block{block2}) require.NoError(t, err) require.EqualValues(t, 2, height) newBlock, _ := mockState.BlockByHeight(2) @@ -103,6 +103,7 @@ func TestApply_InvalidBlockWithRollback(t *testing.T) { stateMock.EXPECT().AddNewDeserializedBlocks([]*proto.Block{block1}).Return(nil, nil) ba := innerBlocksApplier{} - _, _, err := ba.apply(stateMock, []*proto.Block{block2}) + _, err := ba.apply(stateMock, []*proto.Block{block2}) + require.NotNil(t, err) require.Equal(t, "failed add deserialized blocks, first block id sV8beveiVKCiUn9BGZRgZj7V5tRRWPMRj1V9WWzKWnigtfQyZ2eErVXHi7vyGXj5hPuaxF9sGxowZr5XuD4UAwW: error message", err.Error()) } diff --git a/pkg/node/node.go b/pkg/node/node.go index da1076520..42e973b2b 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -2,6 +2,7 @@ package node import ( "context" + "errors" "fmt" "net" "reflect" @@ -93,13 +94,22 @@ func (a *Node) Serve(ctx context.Context) error { go func() { if err := a.peers.SpawnIncomingConnection(ctx, conn); err != nil { - zap.S().Error(err) + zap.S().Debugf("Incoming connection error: %v", err) return } }() } } +func (a *Node) logErrors(err error) { + switch e := err.(type) { + case *proto.InfoMsg: + zap.S().Debug(e.Error()) + default: + zap.S().Error(e.Error()) + } +} + func (a *Node) Run(ctx context.Context, p peer.Parent, InternalMessageCh chan messages.InternalMessage) { go func() { for { @@ -177,7 +187,7 @@ func (a *Node) Run(ctx context.Context, p peer.Parent, InternalMessageCh chan me fsm, async, err = action(a.services, mess, fsm) } if err != nil { - zap.S().Error(err) + a.logErrors(err) } spawnAsync(ctx, tasksCh, a.services.LoggableRunner, async) zap.S().Debugf("FSM %T", fsm) @@ -189,8 +199,8 @@ func spawnAsync(ctx context.Context, ch chan tasks.AsyncTask, r runner.LogRunner func(t tasks.Task) { r.Named(fmt.Sprintf("Async Task %T", t), func() { err := t.Run(ctx, ch) - if err != nil { - zap.S().Errorf("Async Task %T, error %q", t, err) + if err != nil && !errors.Is(err, context.Canceled) { + zap.S().Warnf("Async task '%T' finished with error: %q", t, err) } }) }(t) diff --git a/pkg/node/peer_manager/peer_manager.go b/pkg/node/peer_manager/peer_manager.go index d9e6110e8..dba413efe 100644 --- a/pkg/node/peer_manager/peer_manager.go +++ b/pkg/node/peer_manager/peer_manager.go @@ -53,7 +53,7 @@ type PeerManager interface { Connect(context.Context, proto.TCPAddr) error Score(p peer.Peer) (*proto.Score, error) - // for all connected node send GetPeersMessage + // AskPeers sends GetPeersMessage message to all connected nodes. AskPeers() Disconnect(peer.Peer) @@ -170,11 +170,11 @@ func (a *PeerManagerImpl) connectedCount() int { func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { _, connected := a.Connected(p) if connected { - p.Close() + _ = p.Close() return errors.New("already connected") } if a.IsSuspended(p) { - p.Close() + _ = p.Close() return errors.New("peer is suspended") } if p.Handshake().Version.CmpMinor(a.version) >= 2 { @@ -184,8 +184,8 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { p.Handshake().Version.String(), ) a.Suspend(p, err.Error()) - p.Close() - return err + _ = p.Close() + return proto.NewInfoMsg(err) } in, out := a.InOutCount() @@ -193,7 +193,7 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { case peer.Incoming: if in >= a.limitConnections { _ = p.Close() - return errors.New("exceed incoming connections limit") + return proto.NewInfoMsg(errors.New("exceed incoming connections limit")) } case peer.Outgoing: if !p.Handshake().DeclaredAddr.Empty() { @@ -201,7 +201,7 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { } if out >= a.limitConnections { _ = p.Close() - return errors.New("exceed outgoing connections limit") + return proto.NewInfoMsg(errors.New("exceed outgoing connections limit")) } default: _ = p.Close() @@ -239,7 +239,7 @@ func (a *PeerManagerImpl) PeerWithHighestScore() (peer.Peer, *big.Int, bool) { return nil, nil, false } - var peers []peerInfo + peers := make([]peerInfo, 0) for _, p := range a.active { peers = append(peers, p) } @@ -266,7 +266,7 @@ func (a *PeerManagerImpl) IsSuspended(p peer.Peer) bool { return a.suspended.Blocked(p.RemoteAddr().ToIpPort(), time.Now()) } -// Count connected peers, +// InOutCount counts connected peers, // in - incoming connections // out - outgoing connections func (a *PeerManagerImpl) InOutCount() (in int, out int) { @@ -300,7 +300,7 @@ func (a *PeerManagerImpl) AddAddress(ctx context.Context, addr string) { _ = a.state.Add([]proto.TCPAddr{proto.NewTCPAddrFromString(addr)}) go func() { if err := a.spawner.SpawnOutgoing(ctx, proto.NewTCPAddrFromString(addr)); err != nil { - zap.S().Info(err) + zap.S().Debug(err) } }() } @@ -319,7 +319,7 @@ func (a *PeerManagerImpl) KnownPeers() ([]proto.TCPAddr, error) { func (a *PeerManagerImpl) Close() { a.mu.Lock() for _, v := range a.active { - v.peer.Close() + _ = v.peer.Close() } a.mu.Unlock() } diff --git a/pkg/node/state_fsm/default.go b/pkg/node/state_fsm/default.go index 6a3e55f7b..dd9dd7965 100644 --- a/pkg/node/state_fsm/default.go +++ b/pkg/node/state_fsm/default.go @@ -2,6 +2,7 @@ package state_fsm import ( . "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/proto" ) type Default interface { @@ -27,6 +28,9 @@ func (a DefaultImpl) PeerError(fsm FSM, p Peer, baseInfo BaseInfo, _ error) (FSM func (a DefaultImpl) NewPeer(fsm FSM, p Peer, info BaseInfo) (FSM, Async, error) { err := info.peers.NewConnection(p) + if err != nil { + return fsm, nil, proto.NewInfoMsg(err) + } info.Reschedule() - return fsm, nil, err + return fsm, nil, nil } diff --git a/pkg/node/state_fsm/errs.go b/pkg/node/state_fsm/errs.go index 3fb89bd9d..96ec04903 100644 --- a/pkg/node/state_fsm/errs.go +++ b/pkg/node/state_fsm/errs.go @@ -1,5 +1,9 @@ package state_fsm -import "errors" +import ( + "errors" -var TimeoutErr = errors.New("timeout") + "github.com/wavesplatform/gowaves/pkg/proto" +) + +var TimeoutErr = proto.NewInfoMsg(errors.New("timeout")) diff --git a/pkg/node/state_fsm/fsm.go b/pkg/node/state_fsm/fsm.go index f27f9cfb5..63ec1b7d0 100644 --- a/pkg/node/state_fsm/fsm.go +++ b/pkg/node/state_fsm/fsm.go @@ -20,7 +20,9 @@ import ( type Async []Task type BlocksApplier interface { + BlockExists(state storage.State, block *proto.Block) (bool, error) Apply(state storage.State, block []*proto.Block) (proto.Height, error) + ApplyMicro(state storage.State, block *proto.Block) (proto.Height, error) } type BaseInfo struct { @@ -83,17 +85,15 @@ type FSM interface { Block(p peer.Peer, block *proto.Block) (FSM, Async, error) MinedBlock(block *proto.Block, limits proto.MiningLimits, keyPair proto.KeyPair, vrf []byte) (FSM, Async, error) - // Received signatures after asking by GetSignatures + // BlockIDs receives signatures that was requested by GetSignatures BlockIDs(peer.Peer, []proto.BlockID) (FSM, Async, error) Task(task AsyncTask) (FSM, Async, error) - // micro MicroBlock(p peer.Peer, micro *proto.MicroBlock) (FSM, Async, error) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (FSM, Async, error) Transaction(p peer.Peer, t proto.Transaction) (FSM, Async, error) - // Halt() (FSM, Async, error) } diff --git a/pkg/node/state_fsm/fsm_common.go b/pkg/node/state_fsm/fsm_common.go index 6c30bbf7e..c8d1b8fbd 100644 --- a/pkg/node/state_fsm/fsm_common.go +++ b/pkg/node/state_fsm/fsm_common.go @@ -5,13 +5,15 @@ import ( . "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/state" - "github.com/wavesplatform/gowaves/pkg/types" "go.uber.org/zap" ) func newPeer(fsm FSM, p Peer, peers peer_manager.PeerManager) (FSM, Async, error) { err := peers.NewConnection(p) - return fsm, nil, err + if err != nil { + return fsm, nil, proto.NewInfoMsg(err) + } + return fsm, nil, nil } // TODO handle no peers @@ -24,11 +26,6 @@ func noop(fsm FSM) (FSM, Async, error) { return fsm, nil, nil } -func IsOutdate(period proto.Timestamp, lastBlock *proto.Block, tm types.Time) bool { - curTime := proto.NewTimestampFromTime(tm.Now()) - return curTime-lastBlock.Timestamp > period -} - func handleScore(fsm FSM, info BaseInfo, p Peer, score *proto.Score) (FSM, Async, error) { err := info.peers.UpdateScore(p, score) if err != nil { diff --git a/pkg/node/state_fsm/fsm_idle.go b/pkg/node/state_fsm/fsm_idle.go index 1d0c38d1a..562182e99 100644 --- a/pkg/node/state_fsm/fsm_idle.go +++ b/pkg/node/state_fsm/fsm_idle.go @@ -2,6 +2,7 @@ package state_fsm import ( "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/metrics" . "github.com/wavesplatform/gowaves/pkg/node/state_fsm/tasks" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" @@ -33,22 +34,24 @@ func (a *IdleFsm) MinedBlock(block *proto.Block, limits proto.MiningLimits, keyP return MinedBlockNgTransition(a.baseInfo, block, limits, keyPair, vrf) } -func (a *IdleFsm) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (FSM, Async, error) { +func (a *IdleFsm) MicroBlock(_ peer.Peer, _ *proto.MicroBlock) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } -func (a *IdleFsm) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (FSM, Async, error) { +func (a *IdleFsm) MicroBlockInv(_ peer.Peer, _ *proto.MicroBlockInv) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } func (a *IdleFsm) Task(task AsyncTask) (FSM, Async, error) { zap.S().Debugf("IdleFsm Task: got task type %d, data %+v", task.TaskType, task.Data) switch task.TaskType { - case PING: + case Ping: return noop(a) - case ASK_PEERS: + case AskPeers: a.baseInfo.peers.AskPeers() return a, nil, nil + case MineMicro: // Do nothing + return a, nil, nil default: return a, nil, errors.Errorf("IdleFsm Task: unknown task type %d, data %+v", task.TaskType, task.Data) } @@ -78,9 +81,10 @@ func (a *IdleFsm) NewPeer(p peer.Peer) (FSM, Async, error) { } func (a *IdleFsm) Score(p peer.Peer, score *proto.Score) (FSM, Async, error) { + metrics.FSMScore("idle", score, p.Handshake().NodeName) return handleScore(a, a.baseInfo, p, score) } -func (a *IdleFsm) Block(peer peer.Peer, block *proto.Block) (FSM, Async, error) { +func (a *IdleFsm) Block(_ peer.Peer, _ *proto.Block) (FSM, Async, error) { return noop(a) } diff --git a/pkg/node/state_fsm/fsm_ng.go b/pkg/node/state_fsm/fsm_ng.go index 749fe8625..21f080f28 100644 --- a/pkg/node/state_fsm/fsm_ng.go +++ b/pkg/node/state_fsm/fsm_ng.go @@ -15,6 +15,7 @@ import ( type NGFsm struct { BaseInfo + blocksCache blockStatesCache } func (a *NGFsm) Transaction(p peer.Peer, t proto.Transaction) (FSM, Async, error) { @@ -27,12 +28,12 @@ func (a *NGFsm) Transaction(p peer.Peer, t proto.Transaction) (FSM, Async, error func (a *NGFsm) Task(task AsyncTask) (FSM, Async, error) { switch task.TaskType { - case PING: + case Ping: return noop(a) - case ASK_PEERS: + case AskPeers: a.peers.AskPeers() return a, nil, nil - case MINE_MICRO: + case MineMicro: t := task.Data.(MineMicroTaskData) return a.mineMicro(t.Block, t.Limits, t.KeyPair, t.Vrf) default: @@ -46,7 +47,8 @@ func (a *NGFsm) Halt() (FSM, Async, error) { func NewNGFsm12(info BaseInfo) *NGFsm { return &NGFsm{ - BaseInfo: info, + BaseInfo: info, + blocksCache: blockStatesCache{blockStates: map[proto.BlockID]proto.Block{}}, } } @@ -64,62 +66,112 @@ func (a *NGFsm) PeerError(p peer.Peer, e error) (FSM, Async, error) { } func (a *NGFsm) Score(p peer.Peer, score *proto.Score) (FSM, Async, error) { + metrics.FSMScore("ng", score, p.Handshake().NodeName) return handleScore(a, a.BaseInfo, p, score) } +func (a *NGFsm) rollbackToStateFromCache(blockFromCache *proto.Block) error { + previousBlockID := blockFromCache.Parent + err := a.storage.RollbackTo(previousBlockID) + if err != nil { + return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", + previousBlockID.String(), blockFromCache.ID.String()) + } + _, err = a.blocksApplier.Apply(a.storage, []*proto.Block{blockFromCache}) + if err != nil { + return err + } + return nil +} + func (a *NGFsm) Block(peer peer.Peer, block *proto.Block) (FSM, Async, error) { - metrics.BlockReceived(block, peer.Handshake().NodeName) - h, err := a.blocksApplier.Apply(a.storage, []*proto.Block{block}) + ok, err := a.blocksApplier.BlockExists(a.storage, block) + if err != nil { + return a, nil, err + } + if ok { + return a, nil, proto.NewInfoMsg(errors.Errorf("Block '%s' already exists", block.BlockID().String())) + } + + metrics.FSMKeyBlockReceived("ng", block, peer.Handshake().NodeName) + + top := a.storage.TopBlock() + if top.BlockID() != block.Parent { // does block refer to last block + zap.S().Debugf("Key-block '%s' has parent '%s' which is not the top block '%s'", + block.ID.String(), block.Parent.String(), top.ID.String()) + if blockFromCache, ok := a.blocksCache.Get(block.Parent); ok { + zap.S().Debugf("Re-applying block '%s' from cache", blockFromCache.ID.String()) + err := a.rollbackToStateFromCache(blockFromCache) + if err != nil { + return a, nil, err + } + } + } + + _, err = a.blocksApplier.Apply(a.storage, []*proto.Block{block}) if err != nil { - metrics.BlockDeclined(block) + metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, err } - metrics.BlockApplied(block, h) + metrics.FSMKeyBlockApplied("ng", block) + + a.blocksCache.Clear() + a.blocksCache.AddBlockState(block) + a.Scheduler.Reschedule() a.actions.SendScore(a.storage) a.CleanUtx() + return NewNGFsm12(a.BaseInfo), nil, nil } func (a *NGFsm) MinedBlock(block *proto.Block, limits proto.MiningLimits, keyPair proto.KeyPair, vrf []byte) (FSM, Async, error) { - var h proto.Height + metrics.FSMKeyBlockGenerated("ng", block) err := a.storage.Map(func(state state.NonThreadSafeState) error { var err error - h, err = a.blocksApplier.Apply(state, []*proto.Block{block}) + _, err = a.blocksApplier.Apply(state, []*proto.Block{block}) return err }) if err != nil { - zap.S().Info("NGFsm MinedBlock err ", err) + zap.S().Warnf("Failed to apply mined block '%s': %v", block.ID.String(), err) + metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, err } - metrics.BlockMined(block, h) + metrics.FSMKeyBlockApplied("ng", block) + + a.blocksCache.Clear() + a.blocksCache.AddBlockState(block) + a.Reschedule() a.actions.SendBlock(block) a.actions.SendScore(a.storage) a.CleanUtx() + return NewNGFsm12(a.BaseInfo), Tasks(NewMineMicroTask(1*time.Second, block, limits, keyPair, vrf)), nil } -func (a *NGFsm) BlockIDs(peer peer.Peer, sigs []proto.BlockID) (FSM, Async, error) { +func (a *NGFsm) BlockIDs(_ peer.Peer, _ []proto.BlockID) (FSM, Async, error) { return noop(a) } -// received microblock +// MicroBlock handles new microblock message. func (a *NGFsm) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (FSM, Async, error) { - defer func() { - zap.S().Debug("Reschedule form NGFsm.MicroBlock defer") - a.BaseInfo.Reschedule() - }() - metrics.MicroBlockReceived(micro, p.Handshake().NodeName) - _, _, err := a.microBlockByID(micro) + metrics.FSMMicroBlockReceived("ng", micro, p.Handshake().NodeName) + block, err := a.checkAndAppendMicroblock(micro) // the TopBlock() is used here if err != nil { + metrics.FSMMicroBlockDeclined("ng", micro, err) return a, nil, err } - a.MicroBlockCache.Add(a.storage.TopBlock().BlockID(), micro) - inv, ok := a.MicroBlockInvCache.Get(a.storage.TopBlock().BlockID()) + a.MicroBlockCache.Add(block.BlockID(), micro) + a.blocksCache.AddBlockState(block) + a.BaseInfo.Reschedule() + + // Notify all connected peers about new microblock, send them microblock inv network message + inv, ok := a.MicroBlockInvCache.Get(block.BlockID()) if ok { invBts, err := inv.MarshalBinary() if err == nil { + //TODO: We have to exclude from recipients peers that already have this microblock a.peers.EachConnected(func(p peer.Peer, score *proto.Score) { p.SendMessage( &proto.MicroBlockInvMessage{ @@ -134,28 +186,32 @@ func (a *NGFsm) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (FSM, Async, er return a, nil, nil } +// New microblock generated by miner func (a *NGFsm) mineMicro(minedBlock *proto.Block, rest proto.MiningLimits, keyPair proto.KeyPair, vrf []byte) (FSM, Async, error) { - defer func() { - zap.S().Debug("Reschedule form NGFsm.mineMicro defer") - a.Reschedule() - }() block, micro, rest, err := a.microMiner.Micro(minedBlock, rest, keyPair) if err == miner.NoTransactionsErr { return a, Tasks(NewMineMicroTask(5*time.Second, minedBlock, rest, keyPair, vrf)), nil } + if err == miner.StateChangedErr { + return a, nil, proto.NewInfoMsg(err) + } if err != nil { return a, nil, errors.Wrap(err, "NGFsm.mineMicro") } + metrics.FSMMicroBlockGenerated("ng", micro) err = a.storage.Map(func(s state.NonThreadSafeState) error { - _, err := a.blocksApplier.Apply(s, []*proto.Block{block}) + _, err := a.blocksApplier.ApplyMicro(s, block) return err }) if err != nil { return a, nil, err } + a.blocksCache.AddBlockState(block) + a.Reschedule() + metrics.FSMMicroBlockApplied("ng", micro) inv := proto.NewUnsignedMicroblockInv( micro.SenderPK, - block.ID, + block.BlockID(), micro.Reference) err = inv.Sign(keyPair.Secret, a.scheme) if err != nil { @@ -165,8 +221,9 @@ func (a *NGFsm) mineMicro(minedBlock *proto.Block, rest proto.MiningLimits, keyP if err != nil { return a, nil, err } - a.MicroBlockCache.Add(block.ID, micro) - a.MicroBlockInvCache.Add(block.ID, inv) + + a.MicroBlockCache.Add(block.BlockID(), micro) + a.MicroBlockInvCache.Add(block.BlockID(), inv) // TODO wrap a.peers.EachConnected(func(p peer.Peer, score *proto.Score) { p.SendMessage( @@ -175,44 +232,52 @@ func (a *NGFsm) mineMicro(minedBlock *proto.Block, rest proto.MiningLimits, keyP }, ) }) + return a, Tasks(NewMineMicroTask(5*time.Second, block, rest, keyPair, vrf)), nil } -func (a *NGFsm) microBlockByID(micro *proto.MicroBlock) (FSM, Async, error) { - top := a.storage.TopBlock() - if top.BlockID() != micro.Reference { - return a, nil, errors.New("micro reference not found") +// Check than microblock is appendable and append it +func (a *NGFsm) checkAndAppendMicroblock(micro *proto.MicroBlock) (*proto.Block, error) { + top := a.storage.TopBlock() // Get the last block + if top.BlockID() != micro.Reference { // Microblock doesn't refer to last block + err := errors.Errorf("microblock TBID '%s' refer to block ID '%s' but last block ID is '%s'", micro.TotalBlockID.String(), micro.Reference.String(), top.BlockID().String()) + metrics.FSMMicroBlockDeclined("ng", micro, err) + return &proto.Block{}, proto.NewInfoMsg(err) } - b, err := a.storage.Block(micro.Reference) + ok, err := micro.VerifySignature(a.scheme) if err != nil { - return a, nil, err + return nil, err + } + if !ok { + return nil, errors.Errorf("microblock '%s' has invalid signature", micro.TotalBlockID.String()) } - newTrs := b.Transactions.Join(micro.Transactions) - newBlock, err := proto.CreateBlock(newTrs, b.Timestamp, b.Parent, b.GenPublicKey, b.NxtConsensus, b.Version, b.Features, b.RewardVote, a.scheme) + newTrs := top.Transactions.Join(micro.Transactions) + newBlock, err := proto.CreateBlock(newTrs, top.Timestamp, top.Parent, top.GenPublicKey, top.NxtConsensus, top.Version, top.Features, top.RewardVote, a.scheme) if err != nil { - return a, nil, err + return nil, err } newBlock.BlockSignature = micro.TotalResBlockSigField - ok, err := newBlock.VerifySignature(a.scheme) + ok, err = newBlock.VerifySignature(a.scheme) if err != nil { - return a, nil, err + return nil, err } if !ok { - return a, nil, errors.New("incorrect signature for applied microblock") + return nil, errors.New("incorrect signature for applied microblock") } err = newBlock.GenerateBlockID(a.scheme) if err != nil { - return a, nil, errors.Wrap(err, "NGFsm microBlockByID: failed generate block id") + return nil, errors.Wrap(err, "NGFsm microBlockByID: failed generate block id") } err = a.storage.Map(func(state state.State) error { - _, err := a.blocksApplier.Apply(state, []*proto.Block{newBlock}) + _, err := a.blocksApplier.ApplyMicro(state, newBlock) return err }) if err != nil { - return a, nil, errors.Wrap(err, "failed to apply created from micro block") + metrics.FSMMicroBlockDeclined("ng", micro, err) + return nil, errors.Wrap(err, "failed to apply created from micro block") } - metrics.MicroBlockApplied(micro) - return a, nil, nil + metrics.FSMMicroBlockApplied("ng", micro) + return newBlock, nil } func (a *NGFsm) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (FSM, Async, error) { @@ -225,3 +290,25 @@ func (a *NGFsm) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (FSM, Async func MinedBlockNgTransition(info BaseInfo, block *proto.Block, limits proto.MiningLimits, keyPair proto.KeyPair, vrf []byte) (FSM, Async, error) { return NewNGFsm12(info).MinedBlock(block, limits, keyPair, vrf) } + +type blockStatesCache struct { + blockStates map[proto.BlockID]proto.Block +} + +func (c *blockStatesCache) AddBlockState(block *proto.Block) { + c.blockStates[block.ID] = *block + zap.S().Debugf("Block '%s' added to cache, total blocks in cache: %d", block.ID.String(), len(c.blockStates)) +} + +func (c *blockStatesCache) Clear() { + c.blockStates = map[proto.BlockID]proto.Block{} + zap.S().Debug("Block cache is empty") +} + +func (c *blockStatesCache) Get(blockID proto.BlockID) (*proto.Block, bool) { + block, ok := c.blockStates[blockID] + if !ok { + return nil, false + } + return &block, true +} diff --git a/pkg/node/state_fsm/fsm_sync.go b/pkg/node/state_fsm/fsm_sync.go index a9d667f0f..156176106 100644 --- a/pkg/node/state_fsm/fsm_sync.go +++ b/pkg/node/state_fsm/fsm_sync.go @@ -46,12 +46,12 @@ func (a *SyncFsm) Transaction(p Peer, t proto.Transaction) (FSM, Async, error) { return a, nil, err } -// ignore microblocks +// MicroBlock ignores new microblock message. func (a *SyncFsm) MicroBlock(_ Peer, _ *proto.MicroBlock) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } -// ignore microblocks +// MicroBlockInv ignores new microblock message. func (a *SyncFsm) MicroBlockInv(_ Peer, _ *proto.MicroBlockInv) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } @@ -59,15 +59,17 @@ func (a *SyncFsm) MicroBlockInv(_ Peer, _ *proto.MicroBlockInv) (FSM, Async, err func (a *SyncFsm) Task(task AsyncTask) (FSM, Async, error) { zap.S().Debugf("SyncFsm Task: got task type %d, data %+v", task.TaskType, task.Data) switch task.TaskType { - case ASK_PEERS: + case AskPeers: a.baseInfo.peers.AskPeers() return a, nil, nil - case PING: + case Ping: timeout := a.conf.lastReceiveTime.Add(a.conf.timeout).Before(a.baseInfo.tm.Now()) if timeout { return NewIdleFsm(a.baseInfo), nil, TimeoutErr } return a, nil, nil + case MineMicro: // Do nothing + return a, nil, nil default: return a, nil, errors.Errorf("SyncFsm Task: unknown task type %d, data %+v", task.TaskType, task.Data) } @@ -82,7 +84,7 @@ func (noopWrapper) AskBlocksIDs([]proto.BlockID) { func (noopWrapper) AskBlock(proto.BlockID) { } -func (a *SyncFsm) PeerError(p Peer, e error) (FSM, Async, error) { +func (a *SyncFsm) PeerError(p Peer, _ error) (FSM, Async, error) { a.baseInfo.peers.Disconnect(p) if a.conf.peerSyncWith == p { _, blocks, _ := a.internal.Blocks(noopWrapper{}) @@ -97,11 +99,11 @@ func (a *SyncFsm) PeerError(p Peer, e error) (FSM, Async, error) { return a, nil, nil } -func (a *SyncFsm) BlockIDs(peer Peer, sigs []proto.BlockID) (FSM, Async, error) { +func (a *SyncFsm) BlockIDs(peer Peer, signatures []proto.BlockID) (FSM, Async, error) { if a.conf.peerSyncWith != peer { return a, nil, nil } - internal, err := a.internal.BlockIDs(extension.NewPeerExtension(peer, a.baseInfo.scheme), sigs) + internal, err := a.internal.BlockIDs(extension.NewPeerExtension(peer, a.baseInfo.scheme), signatures) if err != nil { return newSyncFsm(a.baseInfo, a.conf, internal), nil, err } @@ -119,11 +121,15 @@ func (a *SyncFsm) BlockIDs(peer Peer, sigs []proto.BlockID) (FSM, Async, error) func (a *SyncFsm) NewPeer(p Peer) (FSM, Async, error) { err := a.baseInfo.peers.NewConnection(p) - return a, nil, err + if err != nil { + return a, nil, proto.NewInfoMsg(err) + } + return a, nil, nil } func (a *SyncFsm) Score(p Peer, score *proto.Score) (FSM, Async, error) { // TODO handle new max score + metrics.FSMScore("sync", score, p.Handshake().NodeName) err := a.baseInfo.peers.UpdateScore(p, score) if err != nil { return a, nil, err @@ -135,7 +141,7 @@ func (a *SyncFsm) Block(p Peer, block *proto.Block) (FSM, Async, error) { if p != a.conf.peerSyncWith { return a, nil, nil } - metrics.BlockReceivedFromExtension(block, p.Handshake().NodeName) + metrics.FSMKeyBlockReceived("sync", block, p.Handshake().NodeName) zap.S().Debugf("[%s] Received block %s", p.ID(), block.ID.String()) internal, err := a.internal.Block(block) if err != nil { @@ -145,12 +151,13 @@ func (a *SyncFsm) Block(p Peer, block *proto.Block) (FSM, Async, error) { } func (a *SyncFsm) MinedBlock(block *proto.Block, limits proto.MiningLimits, keyPair proto.KeyPair, vrf []byte) (FSM, Async, error) { + metrics.FSMKeyBlockGenerated("sync", block) zap.S().Infof("New key block '%s' mined", block.ID.String()) - h, err := a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}) + _, err := a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}) if err != nil { return a, nil, nil // We've failed to apply mined block, it's not an error } - metrics.BlockMined(block, h) + metrics.FSMKeyBlockApplied("sync", block) a.baseInfo.Reschedule() // first we should send block @@ -169,10 +176,9 @@ func (a *SyncFsm) applyBlocks(baseInfo BaseInfo, conf conf, internal sync_intern if len(blocks) == 0 { return newSyncFsm(baseInfo, conf, internal), nil, nil } - var last proto.Height err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { var err error - last, err = a.baseInfo.blocksApplier.Apply(s, blocks) + _, err = a.baseInfo.blocksApplier.Apply(s, blocks) return err }) if err != nil { @@ -180,12 +186,12 @@ func (a *SyncFsm) applyBlocks(baseInfo BaseInfo, conf conf, internal sync_intern a.baseInfo.peers.Suspend(conf.peerSyncWith, err.Error()) } for _, b := range blocks { - metrics.BlockDeclinedFromExtension(b) + metrics.FSMKeyBlockDeclined("sync", b, err) } return NewIdleFsm(a.baseInfo), nil, err } - for i, b := range blocks { - metrics.BlockAppliedFromExtension(b, last-uint64(len(blocks)-1-i)) + for _, b := range blocks { + metrics.FSMKeyBlockApplied("sync", b) } a.baseInfo.Reschedule() a.baseInfo.actions.SendScore(a.baseInfo.storage) @@ -219,11 +225,11 @@ func newSyncFsm(baseInfo BaseInfo, conf conf, internal sync_internal.Internal) F } func NewIdleToSyncTransition(baseInfo BaseInfo, p Peer) (FSM, Async, error) { - lastSigs, err := signatures.LastSignaturesImpl{}.LastBlockIDs(baseInfo.storage) + lastSignatures, err := signatures.LastSignaturesImpl{}.LastBlockIDs(baseInfo.storage) if err != nil { return NewIdleFsm(baseInfo), nil, err } - internal := sync_internal.InternalFromLastSignatures(extension.NewPeerExtension(p, baseInfo.scheme), lastSigs) + internal := sync_internal.InternalFromLastSignatures(extension.NewPeerExtension(p, baseInfo.scheme), lastSignatures) c := conf{ peerSyncWith: p, timeout: 30 * time.Second, diff --git a/pkg/node/state_fsm/fsm_sync_test.go b/pkg/node/state_fsm/fsm_sync_test.go index 74c85c399..203c8acc9 100644 --- a/pkg/node/state_fsm/fsm_sync_test.go +++ b/pkg/node/state_fsm/fsm_sync_test.go @@ -47,7 +47,7 @@ func TestSyncFsm_SignaturesTimeout(t *testing.T) { require.NotNil(t, fsm) fsm, _, _ = fsm.Task(AsyncTask{ - TaskType: PING, + TaskType: Ping, }) require.IsType(t, &IdleFsm{}, fsm) diff --git a/pkg/node/state_fsm/fsm_test.go b/pkg/node/state_fsm/fsm_test.go index 69eadcf9e..82249f8d7 100644 --- a/pkg/node/state_fsm/fsm_test.go +++ b/pkg/node/state_fsm/fsm_test.go @@ -26,7 +26,7 @@ func TestNewFsm(t *testing.T) { fsm, async, err := NewFsm(services.Services{Scheduler: noopReschedule{}}, 1000) require.NoError(t, err) - require.Equal(t, []int{tasks.ASK_PEERS, tasks.PING}, mapAsync(async)) + require.Equal(t, []int{tasks.AskPeers, tasks.Ping}, mapAsync(async)) require.NotNil(t, fsm) } diff --git a/pkg/node/state_fsm/sync_internal/internal.go b/pkg/node/state_fsm/sync_internal/internal.go index 2a4573218..80a713ca5 100644 --- a/pkg/node/state_fsm/sync_internal/internal.go +++ b/pkg/node/state_fsm/sync_internal/internal.go @@ -13,8 +13,8 @@ type Blocks []*proto.Block type Eof = bool type BlockApplied bool -var NoSignaturesExpectedErr = errors.New("no signatures expected") -var UnexpectedBlockErr = errors.New("unexpected block") +var NoSignaturesExpectedErr = proto.NewInfoMsg(errors.New("no signatures expected")) +var UnexpectedBlockErr = proto.NewInfoMsg(errors.New("unexpected block")) type PeerExtension interface { AskBlocksIDs(id []proto.BlockID) @@ -27,9 +27,9 @@ type Internal struct { waitingForSignatures bool } -func InternalFromLastSignatures(p extension.PeerExtension, sigs *signatures.ReverseOrdering) Internal { - p.AskBlocksIDs(sigs.BlockIDS()) - return NewInternal(ordered_blocks.NewOrderedBlocks(), sigs, true) +func InternalFromLastSignatures(p extension.PeerExtension, signatures *signatures.ReverseOrdering) Internal { + p.AskBlocksIDs(signatures.BlockIDS()) + return NewInternal(ordered_blocks.NewOrderedBlocks(), signatures, true) } func NewInternal(orderedBlocks *ordered_blocks.OrderedBlocks, respondedSignatures *signatures.ReverseOrdering, waitingForSignatures bool) Internal { diff --git a/pkg/node/state_fsm/tasks/tasks.go b/pkg/node/state_fsm/tasks/tasks.go index 2e296c017..19855614c 100644 --- a/pkg/node/state_fsm/tasks/tasks.go +++ b/pkg/node/state_fsm/tasks/tasks.go @@ -9,20 +9,18 @@ import ( ) const ( - PING = iota + 1 - ASK_PEERS - - MINE_MICRO - + Ping = iota + 1 + AskPeers + MineMicro PersistComplete ) -// Sends task into channel with overflow check. +// SendAsyncTask sends task into channel with overflow check. func SendAsyncTask(output chan AsyncTask, task AsyncTask) { select { case output <- task: default: - zap.S().Errorf("AsyncTask channel is full %T", task) + zap.S().Debugf("AsyncTask channel is full on task '%T'", task) } } @@ -49,7 +47,7 @@ type AskPeersTask struct { func NewAskPeersTask(d time.Duration) AskPeersTask { return AskPeersTask{ - type_: ASK_PEERS, + type_: AskPeers, d: d, } } @@ -87,7 +85,7 @@ func NewPingTask() Task { } func (PingTask) Type() int { - return PING + return Ping } func (PingTask) Run(ctx context.Context, output chan AsyncTask) error { @@ -99,7 +97,7 @@ func (PingTask) Run(ctx context.Context, output chan AsyncTask) error { return ctx.Err() case <-t.C: SendAsyncTask(output, AsyncTask{ - TaskType: PING, + TaskType: Ping, Data: nil, }) } @@ -134,7 +132,7 @@ func NewMineMicroTask(timeout time.Duration, block *proto.Block, limits proto.Mi } func (MineMicroTask) Type() int { - return MINE_MICRO + return MineMicro } func (a MineMicroTask) Run(ctx context.Context, output chan AsyncTask) error { diff --git a/pkg/node/state_fsm/tasks/tasks_test.go b/pkg/node/state_fsm/tasks/tasks_test.go index 6cef4a862..730011b39 100644 --- a/pkg/node/state_fsm/tasks/tasks_test.go +++ b/pkg/node/state_fsm/tasks/tasks_test.go @@ -7,15 +7,15 @@ import ( "github.com/stretchr/testify/require" ) -func mkch() chan AsyncTask { +func mkCh() chan AsyncTask { return make(chan AsyncTask, 1) } func TestMineMicroTask_Run(t *testing.T) { task := MineMicroTask{} - require.Equal(t, MINE_MICRO, task.Type()) + require.Equal(t, MineMicro, task.Type()) - ch := mkch() + ch := mkCh() _ = task.Run(context.Background(), ch) require.IsType(t, MineMicroTaskData{}, (<-ch).Data.(MineMicroTaskData)) diff --git a/pkg/p2p/incoming/Incoming.go b/pkg/p2p/incoming/Incoming.go index 6dcb7255f..3413f5068 100644 --- a/pkg/p2p/incoming/Incoming.go +++ b/pkg/p2p/incoming/Incoming.go @@ -41,14 +41,14 @@ func runIncomingPeer(ctx context.Context, cancel context.CancelFunc, params Inco readHandshake := proto.Handshake{} _, err := readHandshake.ReadFrom(c) if err != nil { - zap.S().Error("failed to read handshake: ", err) - c.Close() + zap.S().Debug("Failed to read handshake: ", err) + _ = c.Close() return err } select { case <-ctx.Done(): - c.Close() + _ = c.Close() return errors.Wrap(ctx.Err(), "RunIncomingPeer") default: } @@ -64,14 +64,14 @@ func runIncomingPeer(ctx context.Context, cancel context.CancelFunc, params Inco _, err = writeHandshake.WriteTo(c) if err != nil { - zap.S().Error("failed to write handshake: ", err) - c.Close() + zap.S().Debug("failed to write handshake: ", err) + _ = c.Close() return err } select { case <-ctx.Done(): - c.Close() + _ = c.Close() return errors.Wrap(ctx.Err(), "RunIncomingPeer") default: } diff --git a/pkg/p2p/outgoing/outgoing.go b/pkg/p2p/outgoing/outgoing.go index 11e44764e..8e77e263d 100644 --- a/pkg/p2p/outgoing/outgoing.go +++ b/pkg/p2p/outgoing/outgoing.go @@ -45,7 +45,7 @@ func EstablishConnection(ctx context.Context, params EstablishParams, v proto.Ve connection, handshake, err := p.connect(ctx, c, v) if err != nil { - zap.S().Debug(err, params.Address) + zap.S().Debugf("Outgoing connection to address %s failed with error: %v", params.Address.String(), err) return errors.Wrapf(err, "%q", params.Address) } p.connection = connection @@ -92,20 +92,20 @@ func (a *connector) connect(ctx context.Context, c net.Conn, v proto.Version) (c _, err := handshake.WriteTo(c) if err != nil { - zap.S().Error("failed to send handshake: ", err, a.params.Address) + zap.S().Error("Failed to send handshake: ", err, a.params.Address) return nil, nil, err } select { case <-ctx.Done(): - c.Close() + _ = c.Close() return nil, nil, errors.Wrap(ctx.Err(), "connector.connect") default: } _, err = handshake.ReadFrom(c) if err != nil { - zap.S().Debugf("failed to read handshake: %s %s", err, a.params.Address) + zap.S().Debugf("Failed to read handshake: %s %s", err, a.params.Address) select { case <-ctx.Done(): return nil, nil, errors.Wrap(ctx.Err(), "connector.connect") diff --git a/pkg/p2p/peer/handle.go b/pkg/p2p/peer/handle.go index 5a8f3f00b..675e14722 100644 --- a/pkg/p2p/peer/handle.go +++ b/pkg/p2p/peer/handle.go @@ -39,7 +39,7 @@ func bytesToMessage(b []byte, d DuplicateChecker, resendTo chan ProtoMessage, po select { case resendTo <- mess: default: - zap.S().Debugf("failed to resend to Parent, channel is full: %s, %T", m) + zap.S().Debugf("Failed to resend to Parent, channel is full: %s, %T", m, m) } return nil } @@ -55,12 +55,18 @@ type HandlerParams struct { DuplicateChecker DuplicateChecker } -// for Handle doesn't matter outgoing or incoming Connection, it just send and receive messages +// Handle sends and receives messages no matter outgoing or incoming connection. func Handle(params HandlerParams) error { for { select { case <-params.Ctx.Done(): _ = params.Connection.Close() + //TODO: On Done() Err() contains only Canceled or DeadlineExceeded. + // Actually, those errors are only logged in different places and not used to alter behavior. + // Consider removing wrapping. For now, if context was canceled no error is passed by. + if errors.Is(params.Ctx.Err(), context.Canceled) { + return nil + } return errors.Wrap(params.Ctx.Err(), "Handle") case bts := <-params.Remote.FromCh: diff --git a/pkg/p2p/peer/handle_test.go b/pkg/p2p/peer/handle_test.go index 7bbf466c7..3f032b1ce 100644 --- a/pkg/p2p/peer/handle_test.go +++ b/pkg/p2p/peer/handle_test.go @@ -36,7 +36,7 @@ func (a *mockConnection) Conn() net.Conn { return nil } -func TestHHandleStopContext(t *testing.T) { +func TestHandleStopContext(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) go func() { <-time.After(1 * time.Millisecond) @@ -47,7 +47,7 @@ func TestHHandleStopContext(t *testing.T) { Ctx: ctx, Connection: conn, }) - assert.Error(t, err) + assert.NoError(t, err) assert.Equal(t, 1, conn.closeCalledTimes) } diff --git a/pkg/proto/block_test.go b/pkg/proto/block_test.go index 6efa7b541..ee8856b50 100644 --- a/pkg/proto/block_test.go +++ b/pkg/proto/block_test.go @@ -83,9 +83,9 @@ func blockFromBinaryToBinary(t *testing.T, hexStr, jsonStr string) { var b Block err = b.UnmarshalBinary(decoded, MainNetScheme) assert.NoError(t, err, "UnmarshalBinary() for block failed") - bytes, err := BlockEncodeJson(&b) + bts, err := BlockEncodeJson(&b) assert.NoError(t, err, "json.Marshal() for block failed") - str := string(bytes) + str := string(bts) assert.Equalf(t, jsonStr, str, "block marshaled to wrong json:\nhave: %s\nwant: %s", str, jsonStr) bin, err := b.MarshalBinary() assert.NoError(t, err, "MarshalBinary() for block failed") @@ -96,9 +96,9 @@ func blockFromJSONToJSON(t *testing.T, jsonStr string) { var b Block err := json.Unmarshal([]byte(jsonStr), &b) assert.NoError(t, err, "json.Unmarshal() for block failed") - bytes, err := BlockEncodeJson(&b) + bts, err := BlockEncodeJson(&b) assert.NoError(t, err, "json.Marshal() for block failed") - str := string(bytes) + str := string(bts) assert.JSONEqf(t, jsonStr, str, "block marshaled to wrong json:\nhave: %s\nwant: %s", str, jsonStr) } @@ -130,9 +130,9 @@ func headerFromBinaryToBinary(t *testing.T, hexStr, jsonStr string) { var header BlockHeader err = header.UnmarshalHeaderFromBinary(decoded, MainNetScheme) assert.NoError(t, err, "UnmarshalHeaderFromBinary() failed") - bytes, err := json.Marshal(header) + bts, err := json.Marshal(header) assert.NoError(t, err, "json.Marshal() for header failed") - str := string(bytes) + str := string(bts) assert.Equalf(t, jsonStr, str, "header marshaled to wrong json:\nhave: %s\nwant: %s", str, jsonStr) bin, err := header.MarshalHeaderToBinary() assert.NoError(t, err, "MarshalHeaderToBinary() failed") @@ -143,9 +143,9 @@ func headerFromJSONToJSON(t *testing.T, jsonStr string) { var header BlockHeader err := json.Unmarshal([]byte(jsonStr), &header) assert.NoError(t, err, "json.Unmarshal() for header failed") - bytes, err := json.Marshal(header) + bts, err := json.Marshal(header) assert.NoError(t, err, "json.Marshal() for header failed") - str := string(bytes) + str := string(bts) assert.JSONEqf(t, jsonStr, str, "header marshaled to wrong json:\nhave: %s\nwant: %s", str, jsonStr) } @@ -362,14 +362,13 @@ func TestBlock_Clone(t *testing.T) { // TODO, empty block should not marshal, or unmarshal successfully func TestEmptyBlockMarshall(t *testing.T) { - t.Skip() b1 := Block{} bts, err := b1.MarshalBinary() require.NoError(t, err) b2 := Block{} err = b2.UnmarshalBinary(bts, MainNetScheme) - require.NoError(t, err) + require.Error(t, err) } func TestBlockVerifyRootHash(t *testing.T) { diff --git a/pkg/proto/errors.go b/pkg/proto/errors.go new file mode 100644 index 000000000..f7cb95c3d --- /dev/null +++ b/pkg/proto/errors.go @@ -0,0 +1,19 @@ +package proto + +// This struct describes "info" level of message, which users shouldn't even know about + +type InfoMsg struct { + err error +} + +func NewInfoMsg(err error) error { + return &InfoMsg{err: err} +} + +func (im *InfoMsg) Error() string { + return im.err.Error() +} + +func (im *InfoMsg) IsNil() bool { + return im.err == nil +} diff --git a/pkg/proto/microblock.go b/pkg/proto/microblock.go index 831ad7116..f8aead661 100644 --- a/pkg/proto/microblock.go +++ b/pkg/proto/microblock.go @@ -126,11 +126,11 @@ func (a *MicroBlock) UnmarshalBinary(b []byte, scheme Scheme) error { return errors.Wrap(err, "failed to unmarshal microblock transaction bytes") } if proto { - var txs Transactions + txs := new(Transactions) if err := txs.UnmarshalFromProtobuf(bts); err != nil { return errors.Wrap(err, "failed to unmarshal transactions from protobuf") } - a.Transactions = txs + a.Transactions = *txs } else { a.Transactions, err = NewTransactionsFromBytes(bts, int(a.TransactionCount), scheme) if err != nil { @@ -179,7 +179,7 @@ func (a *MicroBlock) Sign(scheme Scheme, secret crypto.SecretKey) error { func (a *MicroBlock) WriteTo(scheme Scheme, w io.Writer) (int64, error) { n, _ := a.WriteWithoutSignature(scheme, w) - n2, _ := w.Write(a.Signature[:]) + n2, _ := w.Write(a.Signature.Bytes()) return n + int64(n2), nil } @@ -187,14 +187,20 @@ func (a *MicroBlock) WriteWithoutSignature(scheme Scheme, w io.Writer) (int64, e s := serializer.NewNonFallable(w) s.Byte(a.VersionField) s.Bytes(a.Reference.Bytes()) - s.Bytes(a.TotalResBlockSigField[:]) - s.Uint32(uint32(a.Transactions.BinarySize() + 4)) - s.Uint32(a.TransactionCount) + s.Bytes(a.TotalResBlockSigField.Bytes()) + // Serialize transactions in separate buffer to get the size + txsBuf := new(bytes.Buffer) + txsSerializer := serializer.NewNonFallable(txsBuf) proto := a.VersionField >= byte(ProtobufBlockVersion) - if _, err := a.Transactions.WriteTo(proto, scheme, s); err != nil { + if _, err := a.Transactions.WriteTo(proto, scheme, txsSerializer); err != nil { return 0, err } - s.Bytes(a.SenderPK[:]) + // Write transactions bytes size and its count + s.Uint32(uint32(txsBuf.Len() + 4)) + s.Uint32(a.TransactionCount) + // Write transactions bytes + s.Bytes(txsBuf.Bytes()) + s.Bytes(a.SenderPK.Bytes()) return s.N(), nil } @@ -209,7 +215,7 @@ type MicroBlockMessage struct { Body []byte } -func (*MicroBlockMessage) ReadFrom(r io.Reader) (int64, error) { +func (*MicroBlockMessage) ReadFrom(_ io.Reader) (int64, error) { panic("implement me") } @@ -276,7 +282,7 @@ type MicroBlockInvMessage struct { Body []byte } -func (a *MicroBlockInvMessage) ReadFrom(r io.Reader) (n int64, err error) { +func (a *MicroBlockInvMessage) ReadFrom(_ io.Reader) (n int64, err error) { panic("implement me") } @@ -290,7 +296,7 @@ func (a *MicroBlockInvMessage) WriteTo(w io.Writer) (n int64, err error) { if err != nil { return 0, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) n1, err := h.WriteTo(w) if err != nil { return 0, err @@ -314,12 +320,12 @@ func (a *MicroBlockInvMessage) MarshalBinary() ([]byte, error) { return out, nil } -// ?? total block sig or id +// MicroBlockRequestMessage total block signature or ID. type MicroBlockRequestMessage struct { TotalBlockSig []byte } -func (a *MicroBlockRequestMessage) ReadFrom(r io.Reader) (n int64, err error) { +func (a *MicroBlockRequestMessage) ReadFrom(_ io.Reader) (n int64, err error) { panic("implement me") } @@ -333,7 +339,7 @@ func (a *MicroBlockRequestMessage) WriteTo(w io.Writer) (int64, error) { if err != nil { return 0, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) n2, err := h.WriteTo(w) if err != nil { return 0, err @@ -447,7 +453,7 @@ func (a *MicroBlockInv) WriteTo(w io.Writer) (int64, error) { func (a *MicroBlockInv) Sign(key crypto.SecretKey, schema Scheme) error { buf := bytebufferpool.Get() defer bytebufferpool.Put(buf) - err := a.signableBytes(buf, schema) + err := a.bodyBytes(buf, schema) if err != nil { return err } @@ -458,7 +464,7 @@ func (a *MicroBlockInv) Sign(key crypto.SecretKey, schema Scheme) error { return nil } -func (a *MicroBlockInv) signableBytes(w io.Writer, schema Scheme) error { +func (a *MicroBlockInv) bodyBytes(w io.Writer, schema Scheme) error { addr, err := NewAddressFromPublicKey(schema, a.PublicKey) if err != nil { return err @@ -473,18 +479,14 @@ func (a *MicroBlockInv) signableBytes(w io.Writer, schema Scheme) error { func (a *MicroBlockInv) Verify(schema Scheme) (bool, error) { buf := bytebufferpool.Get() defer bytebufferpool.Put(buf) - err := a.signableBytes(buf, schema) + err := a.bodyBytes(buf, schema) if err != nil { return false, err } return crypto.Verify(a.PublicKey, a.Signature, buf.Bytes()), nil } -func NewUnsignedMicroblockInv( - PublicKey crypto.PublicKey, - TotalBlockID BlockID, - Reference BlockID) *MicroBlockInv { - +func NewUnsignedMicroblockInv(PublicKey crypto.PublicKey, TotalBlockID BlockID, Reference BlockID) *MicroBlockInv { return &MicroBlockInv{ PublicKey: PublicKey, TotalBlockID: TotalBlockID, @@ -512,7 +514,7 @@ type PBMicroBlockMessage struct { MicroBlockBytes Bytes } -func (*PBMicroBlockMessage) ReadFrom(r io.Reader) (int64, error) { +func (*PBMicroBlockMessage) ReadFrom(_ io.Reader) (int64, error) { panic("implement me") } diff --git a/pkg/proto/microblock_test.go b/pkg/proto/microblock_test.go index bc3694790..43633d472 100644 --- a/pkg/proto/microblock_test.go +++ b/pkg/proto/microblock_test.go @@ -2,8 +2,10 @@ package proto import ( "bytes" + "encoding/base64" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/crypto" ) @@ -142,3 +144,14 @@ func TestMicroBlockRequestMessage_Marshaling(t *testing.T) { require.Equal(t, mess.TotalBlockSig, mess2.TotalBlockSig) } + +func TestMicroBlockV5VerifySignature(t *testing.T) { + b, err := base64.StdEncoding.DecodeString("CqMCCAUSINDAl9MzGkepj6WsZ+1NZv0grSgzJogVswMTP7+ug6LoGkDJBEdWcsDc/bat2ljrW74o9l7Y+Pcp07ra2VRe/HLU/Oq6cT7xJqyqZ7xoXP5tLKcnq4hF/5FtS/NYx5zX3RMPIiDk9FCvGrDyyqy8jzX1qe6cEdv5NRXv+hSH+BMnnFtqBSqYAQpUCFQSIBjkoQIwpcrsWlpsgLJVOBo27loBDODD+h473uYYaxMSGgQQoI0GIOvZ5ffzLigDwgYeChYKFCCTgv+auCSYevJXZ7mkKyv2/dkoEgQQoI0GEkD5K5E+HKr3IXYhnwLZaWVsIF+tJdbvV4LFjksWIeLoopDf46TTE2XXXb64R2ZsbWV0QJpQ3cNqTnKXGcB2DesIEkA+/2wKSB07Tg2uBH9OGuIXLBH7FzKPLllyjn7TlvYTLZrohyNSBAIQ3sM9UwPQkUDSC1NGYBFwRHRdF+gPfQcDGiAzlpLCohmCR1KXVnxw5AVO7Xq60gorXfInMXSiS3Qf9Q==") + require.NoError(t, err) + micro := new(MicroBlock) + err = micro.UnmarshalFromProtobuf(b) + require.NoError(t, err) + ok, err := micro.VerifySignature('T') + require.NoError(t, err) + assert.True(t, ok) +} diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index aedab5371..f492eb7cc 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -17,9 +17,9 @@ import ( ) const ( - MaxHeaderLength = 17 - headerMagic = 0x12345678 - headerCsumLen = 4 + MaxHeaderLength = 17 + headerMagic = 0x12345678 + headerChecksumLen = 4 HeaderSizeWithPayload = 17 HeaderSizeWithoutPayload = 13 @@ -56,11 +56,11 @@ type Message interface { } type Header struct { - Length uint32 - Magic uint32 - ContentID uint8 - PayloadLength uint32 - PayloadCsum [headerCsumLen]byte + Length uint32 + Magic uint32 + ContentID uint8 + PayloadLength uint32 + PayloadChecksum [headerChecksumLen]byte } func (h *Header) MarshalBinary() ([]byte, error) { @@ -126,7 +126,7 @@ func (h *Header) UnmarshalBinary(data []byte) error { if uint32(len(data)) < HeaderSizeWithPayload { return errors.New("Header UnmarshalBinary: invalid data size") } - copy(h.PayloadCsum[:], data[13:17]) + copy(h.PayloadChecksum[:], data[13:17]) } return nil @@ -144,7 +144,7 @@ func (h *Header) Copy(data []byte) (int, error) { if len(data) < 17 { return 0, errors.New("Header Copy: invalid data size") } - copy(data[13:17], h.PayloadCsum[:]) + copy(data[13:17], h.PayloadChecksum[:]) return HeaderSizeWithPayload, nil } return HeaderSizeWithoutPayload, nil @@ -185,7 +185,7 @@ func (a Version) Cmp(other Version) int { return 0 } -// Compare minor version. +// CmpMinor compares minor version. // If equal return 0. // If diff only 1 version (for example 1.14 and 1.13), then 1 // If more then 1 version, then return 2. @@ -340,7 +340,7 @@ func (a TCPAddr) WriteTo(w io.Writer) (int64, error) { return int64(n + n2), nil } -// ToStaticSize converts TCPAddr to 8-byte array. +// ToUint64 converts TCPAddr to uint64 number. func (a TCPAddr) ToUint64() uint64 { ip := uint64(a.ipToUint32()) << 32 ip = ip | uint64(a.Port) @@ -501,7 +501,7 @@ func (a U8String) MarshalBinary() ([]byte, error) { return data, nil } -// MarshalBinary encodes U8String to binary form +// WriteTo writes U8String into io.Writer w in binary form. func (a U8String) WriteTo(w io.Writer) (int64, error) { l := len(a.S) if l > 255 { @@ -590,12 +590,10 @@ func (a *Handshake) WriteTo(w io.Writer) (int64, error) { // ReadFrom reads Handshake from io.Reader func (a *Handshake) ReadFrom(r io.Reader) (int64, error) { - // max Header size based on fields - //buf := [556]byte{} appName := U8String{} n1, err := appName.ReadFrom(r) if err != nil { - return 0, errors.Wrap(err, "appname") + return 0, errors.Wrap(err, "appName") } a.AppName = appName.S @@ -607,7 +605,7 @@ func (a *Handshake) ReadFrom(r io.Reader) (int64, error) { nodeName := U8String{} n3, err := nodeName.ReadFrom(r) if err != nil { - return 0, errors.Wrap(err, "nodename") + return 0, errors.Wrap(err, "nodeName") } a.NodeName = nodeName.S @@ -632,7 +630,7 @@ func (a *Handshake) ReadFrom(r io.Reader) (int64, error) { } a.Timestamp = uint64(tm) - return int64(n1 + n2 + n3 + n4 + n5 + n6), nil + return n1 + n2 + n3 + n4 + n5 + n6, nil } // GetPeersMessage implements the GetPeers message from the waves protocol @@ -673,7 +671,7 @@ func (m *GetPeersMessage) ReadFrom(r io.Reader) (int64, error) { if err != nil { return nn, err } - return int64(nn), m.UnmarshalBinary(packet) + return nn, m.UnmarshalBinary(packet) } // WriteTo writes GetPeersMessage to io.Writer @@ -700,7 +698,7 @@ func NewIpPortFromTcpAddr(a TCPAddr) IpPort { } func (a IpPort) Addr() net.IP { - return net.IP(a[:net.IPv6len]) + return a[:net.IPv6len] } func (a IpPort) Port() int { @@ -732,10 +730,27 @@ type PeerInfo struct { Port uint16 } -func (a PeerInfo) WriteTo(w io.Writer) (int64, error) { +func NewPeerInfoFromString(addr string) (PeerInfo, error) { + parts := strings.Split(addr, ":") + if len(parts) != 2 { + return PeerInfo{}, errors.Errorf("invalid addr %s", addr) + } + + ip := net.ParseIP(parts[0]) + port, err := strconv.ParseUint(parts[1], 10, 64) + if err != nil { + return PeerInfo{}, errors.Errorf("invalid port %s", parts[1]) + } + return PeerInfo{ + Addr: ip, + Port: uint16(port), + }, nil +} + +func (p PeerInfo) WriteTo(w io.Writer) (int64, error) { b := [8]byte{} - copy(b[:4], a.Addr.To4()) - binary.BigEndian.PutUint32(b[4:8], uint32(a.Port)) + copy(b[:4], p.Addr.To4()) + binary.BigEndian.PutUint32(b[4:8], uint32(p.Port)) n, err := w.Write(b[:]) if err != nil { return int64(n), err @@ -743,86 +758,69 @@ func (a PeerInfo) WriteTo(w io.Writer) (int64, error) { return int64(n), nil } -func (a *PeerInfo) ReadFrom(r io.Reader) (int64, error) { +func (p *PeerInfo) ReadFrom(r io.Reader) (int64, error) { b := [8]byte{} n, err := r.Read(b[:]) if err != nil { return int64(n), err } - a.Addr = net.IPv4(b[0], b[1], b[2], b[3]) - a.Port = uint16(binary.BigEndian.Uint32(b[:4])) + p.Addr = net.IPv4(b[0], b[1], b[2], b[3]) + p.Port = uint16(binary.BigEndian.Uint32(b[:4])) return int64(n), nil } -func NewPeerInfoFromString(addr string) (PeerInfo, error) { - strs := strings.Split(addr, ":") - if len(strs) != 2 { - return PeerInfo{}, errors.Errorf("invalid addr %s", addr) - } - - ip := net.ParseIP(string(strs[0])) - port, err := strconv.ParseUint(strs[1], 10, 64) - if err != nil { - return PeerInfo{}, errors.Errorf("invalid port %s", strs[1]) - } - return PeerInfo{ - Addr: ip, - Port: uint16(port), - }, nil -} - // MarshalBinary encodes PeerInfo message to binary form -func (m *PeerInfo) MarshalBinary() ([]byte, error) { +func (p *PeerInfo) MarshalBinary() ([]byte, error) { buffer := make([]byte, 8) - copy(buffer[0:4], m.Addr.To4()) - binary.BigEndian.PutUint32(buffer[4:8], uint32(m.Port)) + copy(buffer[0:4], p.Addr.To4()) + binary.BigEndian.PutUint32(buffer[4:8], uint32(p.Port)) return buffer, nil } // UnmarshalBinary decodes PeerInfo message from binary form -func (m *PeerInfo) UnmarshalBinary(data []byte) error { +func (p *PeerInfo) UnmarshalBinary(data []byte) error { if len(data) < 8 { return errors.New("too short") } - m.Addr = net.IPv4(data[0], data[1], data[2], data[3]) - m.Port = uint16(binary.BigEndian.Uint32(data[4:8])) + p.Addr = net.IPv4(data[0], data[1], data[2], data[3]) + p.Port = uint16(binary.BigEndian.Uint32(data[4:8])) return nil } // String() implements Stringer interface for PeerInfo -func (m PeerInfo) String() string { +func (p PeerInfo) String() string { var sb strings.Builder - sb.WriteString(m.Addr.String()) + sb.WriteString(p.Addr.String()) sb.WriteRune(':') - sb.WriteString(strconv.Itoa(int(m.Port))) + sb.WriteString(strconv.Itoa(int(p.Port))) return sb.String() } // MarshalJSON writes PeerInfo Value as JSON string -func (m PeerInfo) MarshalJSON() ([]byte, error) { +func (p PeerInfo) MarshalJSON() ([]byte, error) { var sb strings.Builder - if m.Addr == nil { + if p.Addr == nil { return nil, errors.New("invalid addr") } - if m.Port == 0 { + if p.Port == 0 { return nil, errors.New("invalid port") } sb.WriteRune('"') - sb.WriteString(m.Addr.String()) + sb.WriteString(p.Addr.String()) sb.WriteRune(':') - sb.WriteString(strconv.Itoa(int(m.Port))) + sb.WriteString(strconv.Itoa(int(p.Port))) sb.WriteRune('"') return []byte(sb.String()), nil } // UnmarshalJSON reads PeerInfo from JSON string -func (m *PeerInfo) UnmarshalJSON(value []byte) error { +func (p *PeerInfo) UnmarshalJSON(value []byte) error { s := string(value) if s == jsonNull { return nil @@ -833,38 +831,38 @@ func (m *PeerInfo) UnmarshalJSON(value []byte) error { return errors.Wrap(err, "failed to unmarshal PeerInfo from JSON") } - splitted := strings.SplitN(s, "/", 2) - if len(splitted) == 1 { - s = splitted[0] + parts := strings.SplitN(s, "/", 2) + if len(parts) == 1 { + s = parts[0] } else { - s = splitted[1] + s = parts[1] } - splitted = strings.SplitN(s, ":", 2) + parts = strings.SplitN(s, ":", 2) var addr, port string - if len(splitted) == 1 { - addr = splitted[0] + if len(parts) == 1 { + addr = parts[0] port = "0" } else { - addr = splitted[0] - port = splitted[1] + addr = parts[0] + port = parts[1] } - m.Addr = net.ParseIP(addr) + p.Addr = net.ParseIP(addr) port64, err := strconv.ParseUint(port, 10, 16) if err != nil { return errors.Wrap(err, "failed to unmarshal PeerInfo from JSON") } - m.Port = uint16(port64) + p.Port = uint16(port64) return nil } -func (m *PeerInfo) Empty() bool { - if m.Addr == nil || m.Addr.String() == "0.0.0.0" { +func (p *PeerInfo) Empty() bool { + if p.Addr == nil || p.Addr.String() == "0.0.0.0" { return true } - if m.Port == 0 { + if p.Port == 0 { return true } @@ -909,7 +907,7 @@ func (m *PeersMessage) WriteTo(w io.Writer) (int64, error) { if err != nil { return 0, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -990,23 +988,6 @@ func readPacket(r io.Reader) ([]byte, int64, error) { return packet, int64(nn), nil } -func ReadPacket(buf []byte, r io.Reader) (int64, error) { - packetLen := buf[:4] - nn, err := io.ReadFull(r, packetLen) - if err != nil { - return int64(nn), err - } - l := binary.BigEndian.Uint32(packetLen) - buf = buf[4:] - packet := buf[:l] - n, err := io.ReadFull(r, packet) - if err != nil { - return int64(nn + n), err - } - nn += n - return int64(nn), nil -} - func ReadPayload(buf []byte, r io.Reader) (int64, error) { nn, err := io.ReadFull(r, buf) if err != nil { @@ -1072,7 +1053,7 @@ func (m *GetSignaturesMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1163,7 +1144,7 @@ func (m *SignaturesMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1250,7 +1231,7 @@ func (m *GetBlockMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1345,7 +1326,7 @@ func (m *BlockMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1365,7 +1346,7 @@ func MakeHeader(contentID uint8, payload []byte) (Header, error) { if err != nil { return Header{}, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) return h, nil } @@ -1428,7 +1409,7 @@ func (m *ScoreMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1495,7 +1476,7 @@ func (m *TransactionMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1525,8 +1506,8 @@ func (m *TransactionMessage) UnmarshalBinary(data []byte) error { return err } - if !bytes.Equal(dig[:4], h.PayloadCsum[:]) { - return fmt.Errorf("invalid checksum: expected %x, found %x", dig[:4], h.PayloadCsum[:]) + if !bytes.Equal(dig[:4], h.PayloadChecksum[:]) { + return fmt.Errorf("invalid checksum: expected %x, found %x", dig[:4], h.PayloadChecksum[:]) } return nil } @@ -1583,7 +1564,7 @@ func (m *CheckPointMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1667,7 +1648,7 @@ func (m *PBBlockMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1736,7 +1717,7 @@ func (m *PBTransactionMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1766,8 +1747,8 @@ func (m *PBTransactionMessage) UnmarshalBinary(data []byte) error { return err } - if !bytes.Equal(dig[:4], h.PayloadCsum[:]) { - return fmt.Errorf("invalid checksum: expected %x, found %x", dig[:4], h.PayloadCsum[:]) + if !bytes.Equal(dig[:4], h.PayloadChecksum[:]) { + return fmt.Errorf("invalid checksum: expected %x, found %x", dig[:4], h.PayloadChecksum[:]) } return nil } @@ -1868,7 +1849,7 @@ func (m *GetBlockIdsMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -1964,7 +1945,7 @@ func (m *BlockIdsMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadCsum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:4]) hdr, err := h.MarshalBinary() if err != nil { @@ -2040,15 +2021,15 @@ func (m *BlockIdsMessage) WriteTo(w io.Writer) (int64, error) { type BulkMessage []Message -func (BulkMessage) ReadFrom(r io.Reader) (n int64, err error) { +func (BulkMessage) ReadFrom(_ io.Reader) (n int64, err error) { panic("implement me") } -func (BulkMessage) WriteTo(w io.Writer) (n int64, err error) { +func (BulkMessage) WriteTo(_ io.Writer) (n int64, err error) { panic("implement me") } -func (BulkMessage) UnmarshalBinary(data []byte) error { +func (BulkMessage) UnmarshalBinary(_ []byte) error { panic("implement me") } diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index 84e1ac050..c84d2f9f1 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -162,7 +162,7 @@ func (m *TransactionMessage) Equal(d comparable) bool { var tests = []protocolMarshallingTest{ { &GetPeersMessage{}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000009 12345678 01 00000000 ", }, { @@ -174,52 +174,52 @@ var tests = []protocolMarshallingTest{ {net.IPv4(0x34, 0x33, 0x5c, 0xb6), 0x1acf}, }, }, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000039 12345678 02 0000002c 0b9ebfaf 00000005 8e5d2579 00001ad4 344d6fdb 00001acf 341c42d9 00001acf 341e2f43 00001acf 34335cb6 00001acf", }, { &PeersMessage{[]PeerInfo{{net.IPv4(1, 2, 3, 4), 0x8888}}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000019 12345678 02 0000000c 648fa8c8 00000001 01020304 00008888", }, { &GetSignaturesMessage{[]crypto.Signature{{0x01}}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000051 12345678 14 00000044 5474fb17 00000001 01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000", }, { &SignaturesMessage{[]crypto.Signature{{0x13}}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000051 12345678 15 00000044 5e0c8bee 00000001 13000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000", }, { &GetBlockMessage{NewBlockIDFromSignature(crypto.Signature{0x15, 0x12})}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "0000004d 12345678 16 00000040 01d5a895 15120000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000", }, { &BlockMessage{[]byte{0x66, 0x42}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "0000000f 12345678 17 00000002 c2426c62 6642", }, { &ScoreMessage{[]byte{0x66, 0x42}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "0000000f 12345678 18 00000002 c2426c62 6642", }, { &ScoreMessage{[]byte{0x01, 0x47, 0x02, 0x0e, 0x5b, 0x00, 0x75, 0x7a, 0xbe}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000016 12345678 18 00000009 74580717 01 47 02 0e 5b 00 75 7a be", }, { &TransactionMessage{[]byte{0x66, 0x42}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "0000000f 12345678 19 00000002 c2426c62 6642", }, { &CheckPointMessage{[]CheckpointItem{{0xdeadbeef, crypto.Signature{0x10, 0x11}}}}, - //P. Len | Magic | ContentID | Payload Length | PayloadCsum | Payload + //P. Len | Magic | ContentID | Payload Length | PayloadChecksum | Payload "00000059 12345678 64 0000004c fcb6b02a 00000001 00000000 deadbeef 10110000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000", }, } diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 7175b3223..49d25dcf0 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -82,33 +82,33 @@ func costV3(id int) int { return _catalogue_V3[id] } -var _functions_V4 [225]rideFunction +var _functions_V4 [226]rideFunction func init() { - _functions_V4 = [225]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V4 = [226]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, sub, gt, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, log, simplifiedIssue, fullIssue, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, listRemoveByIndex, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, sizeList, getList, median, max, min, intToBytes, stringToBytes, booleanToBytes, intToString, booleanToString, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V4 = "!!=-011001001100410051006100710081011021031041040104110421043105105010511052105310610601061106210710701081080109109010911100110111021103110412001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V4 = "!!=-0110010011004100510061007100810110210310410401041104210431051050105110521053106106010611062107107010810801091090109111001101110211031104110512001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 265, 268, 271, 274, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 585, 602, 619, 636, 653, 670, 687, 704, 721, 749, 769, 790, 811, 831, 838, 843, 852, 867, 878, 890, 894, 897, 904, 919, 930, 934, 939, 947, 955, 961, 973, 976, 981, 988, 1002, 1006, 1010, 1016, 1022, 1029, 1036, 1043, 1050, 1056, 1062, 1072, 1083, 1087, 1089, 1109, 1126, 1134, 1149, 1158, 1172, 1179, 1188, 1198, 1208, 1217, 1226, 1239, 1248, 1262, 1267, 1272, 1283, 1302} +var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 269, 272, 275, 278, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 488, 491, 494, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 589, 606, 623, 640, 657, 674, 691, 708, 725, 753, 773, 794, 815, 835, 842, 847, 856, 871, 882, 894, 898, 901, 908, 923, 934, 938, 943, 951, 959, 965, 977, 980, 985, 992, 1006, 1010, 1014, 1020, 1026, 1033, 1040, 1047, 1054, 1060, 1066, 1076, 1087, 1091, 1093, 1113, 1130, 1138, 1153, 1162, 1176, 1183, 1192, 1202, 1212, 1221, 1230, 1243, 1252, 1266, 1271, 1276, 1287, 1306} func functionNameV4(i int) string { - if i < 0 || i > 224 { + if i < 0 || i > 225 { return "" } return _names_V4[_index_V4[i]:_index_V4[i+1]] } func functionV4(id int) rideFunction { - if id < 0 || id > 224 { + if id < 0 || id > 225 { return nil } return _functions_V4[id] } func checkFunctionV4(name string) (uint16, bool) { - for i := 0; i <= 224; i++ { + for i := 0; i <= 225; i++ { if _names_V4[_index_V4[i]:_index_V4[i+1]] == name { return uint16(i), true } @@ -116,39 +116,39 @@ func checkFunctionV4(name string) (uint16, bool) { return 0, false } func costV4(id int) int { - if id < 0 || id > 224 { + if id < 0 || id > 225 { return -1 } return _catalogue_V4[id] } -var _functions_V5 [265]rideFunction +var _functions_V5 [266]rideFunction func init() { - _functions_V5 = [265]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, fractionIntRounds, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_V5 = [266]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, listRemoveByIndex, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitString, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeString, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, throw, sizeBytes, takeBytes, dropBytes, concatBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, concatStrings, takeString, dropString, sizeString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetPair, attachedPayment, checkedBytesDataEntry, checkedBooleanDataEntry, burn, createBuy, createCeiling, dataTransaction, checkedDeleteEntry, createDown, createFloor, createHalfDown, createHalfEven, createHalfUp, checkedIntDataEntry, leaseCancel, createMd5, createNoAlg, reissue, scriptTransfer, createSell, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorship, checkedStringDataEntry, unit, createUp, addressFromPublicKey, addressFromString, contains, containsElement, dropRightString, dropRightBytes, extract, fractionIntRounds, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} } -var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 14, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 17, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} -var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 14, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "fraction": 17, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 14, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 17, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} +var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 14, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "fraction": 17, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} -const _names_V5 = "!!=-01100100110041005100610071008100910110210201021103104104010411042104310510501051105210531054105510561057105810610601061106210710701081080108110910901091109210931100110111021103110411811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractfractiongetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" +const _names_V5 = "!!=-011001001100410051006100710081009101102102010211031041040104110421043105105010511052105310541055105610571058106106010611062107107010810801081109109010911092109311001101110211031104110511811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractfractiongetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" -var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 187, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 315, 318, 321, 324, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 534, 537, 540, 543, 546, 549, 552, 555, 558, 561, 564, 567, 570, 573, 576, 579, 582, 585, 588, 591, 594, 597, 600, 603, 606, 609, 612, 615, 618, 621, 624, 627, 630, 633, 636, 639, 642, 645, 648, 651, 654, 657, 660, 663, 666, 669, 672, 675, 678, 681, 698, 715, 732, 749, 766, 783, 800, 817, 834, 851, 868, 885, 902, 930, 950, 971, 992, 1012, 1019, 1024, 1033, 1048, 1059, 1071, 1075, 1078, 1085, 1100, 1111, 1115, 1120, 1128, 1136, 1142, 1154, 1165, 1168, 1173, 1180, 1194, 1198, 1202, 1208, 1214, 1221, 1228, 1235, 1242, 1248, 1254, 1264, 1275, 1279, 1281, 1301, 1318, 1326, 1341, 1350, 1364, 1371, 1379, 1388, 1398, 1408, 1417, 1426, 1439, 1448, 1462, 1467, 1472, 1483, 1502} +var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 191, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 318, 319, 322, 325, 328, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 595, 598, 601, 604, 607, 610, 613, 616, 619, 622, 625, 628, 631, 634, 637, 640, 643, 646, 649, 652, 655, 658, 661, 664, 667, 670, 673, 676, 679, 682, 685, 702, 719, 736, 753, 770, 787, 804, 821, 838, 855, 872, 889, 906, 934, 954, 975, 996, 1016, 1023, 1028, 1037, 1052, 1063, 1075, 1079, 1082, 1089, 1104, 1115, 1119, 1124, 1132, 1140, 1146, 1158, 1169, 1172, 1177, 1184, 1198, 1202, 1206, 1212, 1218, 1225, 1232, 1239, 1246, 1252, 1258, 1268, 1279, 1283, 1285, 1305, 1322, 1330, 1345, 1354, 1368, 1375, 1383, 1392, 1402, 1412, 1421, 1430, 1443, 1452, 1466, 1471, 1476, 1487, 1506} func functionNameV5(i int) string { - if i < 0 || i > 264 { + if i < 0 || i > 265 { return "" } return _names_V5[_index_V5[i]:_index_V5[i+1]] } func functionV5(id int) rideFunction { - if id < 0 || id > 264 { + if id < 0 || id > 265 { return nil } return _functions_V5[id] } func checkFunctionV5(name string) (uint16, bool) { - for i := 0; i <= 264; i++ { + for i := 0; i <= 265; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { return uint16(i), true } @@ -156,7 +156,7 @@ func checkFunctionV5(name string) (uint16, bool) { return 0, false } func costV5(id int) int { - if id < 0 || id > 264 { + if id < 0 || id > 265 { return -1 } return _catalogue_V5[id] diff --git a/pkg/ride/functions_list.go b/pkg/ride/functions_list.go index a6ef1a99f..8ae3097cd 100644 --- a/pkg/ride/functions_list.go +++ b/pkg/ride/functions_list.go @@ -466,6 +466,27 @@ func containsElement(_ Environment, args ...rideType) (rideType, error) { return rideBoolean(false), nil } +func listRemoveByIndex(_ Environment, args ...rideType) (rideType, error) { + list, i, err := listAndIntArgs(args) + if err != nil { + return nil, errors.Wrap(err, "listRemoveByIndex") + } + l := len(list) + if l == 0 { + return nil, errors.New("listRemoveByIndex: can't remove an element from empty list") + } + if i < 0 { + return nil, errors.Errorf("listRemoveByIndex: negative index value %d", i) + } + if i >= l { + return nil, errors.Errorf("listRemoveByIndex: index out of bounds") + } + r := make(rideList, l-1) + copy(r, list[:i]) + copy(r[i:], list[i+1:]) + return r, nil +} + func findItem(list rideList, key rideString, entryType, valueType string) (rideType, error) { for _, item := range list { o, ok := item.(rideObject) diff --git a/pkg/ride/functions_list_test.go b/pkg/ride/functions_list_test.go new file mode 100644 index 000000000..aa3ee458b --- /dev/null +++ b/pkg/ride/functions_list_test.go @@ -0,0 +1,37 @@ +package ride + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestListRemoveByIndex(t *testing.T) { + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideList{rideInt(1), rideInt(2), rideInt(3)}, rideInt(0)}, false, rideList{rideInt(2), rideInt(3)}}, + {[]rideType{rideList{rideInt(1), rideInt(2), rideInt(3)}, rideInt(1)}, false, rideList{rideInt(1), rideInt(3)}}, + {[]rideType{rideList{rideInt(1), rideInt(2), rideInt(3)}, rideInt(2)}, false, rideList{rideInt(1), rideInt(2)}}, + {[]rideType{rideList{rideInt(1), rideString("two"), rideBoolean(true)}, rideInt(2)}, false, rideList{rideInt(1), rideString("two")}}, + {[]rideType{rideString("abc"), rideInt(0)}, true, nil}, + {[]rideType{rideList{}, rideInt(0)}, true, nil}, + {[]rideType{rideList{rideString("a")}, rideInt(-1)}, true, nil}, + {[]rideType{rideList{rideString("a")}, rideInt(1)}, true, nil}, + {[]rideType{rideUnit{}}, true, nil}, + {[]rideType{rideInt(1), rideString("x")}, true, nil}, + {[]rideType{rideInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + } { + r, err := listRemoveByIndex(nil, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 5bc0d2906..7ad8e08ad 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -8,6 +8,7 @@ import ( "crypto/x509" "github.com/wavesplatform/gowaves/pkg/util/common" + "github.com/mr-tron/base58" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" @@ -818,6 +819,8 @@ func addressToString(_ Environment, args ...rideType) (rideType, error) { return nil, errors.Errorf("addressToString: recipient is not an Address '%s'", args[0].instanceOf()) } return rideString(a.Address.String()), nil + case rideAddressLike: + return rideString(base58.Encode(a)), nil default: return nil, errors.Errorf("addressToString: invalid argument type '%s'", args[0].instanceOf()) } diff --git a/pkg/ride/functions_test.go b/pkg/ride/functions_test.go index 301ee3374..972d059e5 100644 --- a/pkg/ride/functions_test.go +++ b/pkg/ride/functions_test.go @@ -11,7 +11,7 @@ func TestNames(t *testing.T) { assert.Equal(t, "!", functionNameV2(0)) assert.Equal(t, "!=", functionNameV3(1)) assert.Equal(t, "wavesBalance", functionNameV2(67)) - assert.Equal(t, "Down", functionNameV4(182)) + assert.Equal(t, "DeleteEntry", functionNameV4(182)) } func TestCheckFunction(t *testing.T) { diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index 3dd25c5c6..c4cebebd6 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -324,6 +324,7 @@ func functionsV4() map[string]string { m["1102"] = "concatList" m["1103"] = "indexOfList" m["1104"] = "lastIndexOfList" + m["1105"] = "listRemoveByIndex" m["1209"] = "makeString" for i, l := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} { m[strconv.Itoa(2400+i)] = fmt.Sprintf("bls12Groth16Verify_%d", l) @@ -407,6 +408,7 @@ func catalogueV4() map[string]int { m["1102"] = 4 m["1103"] = 5 m["1104"] = 5 + m["1105"] = 7 m["1200"] = 7 m["1201"] = 1 m["1202"] = 1 diff --git a/pkg/services/services.go b/pkg/services/services.go index 4915c61d7..928180488 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -10,7 +10,9 @@ import ( ) type BlocksApplier interface { + BlockExists(state state.State, block *proto.Block) (bool, error) Apply(state state.State, block []*proto.Block) (proto.Height, error) + ApplyMicro(state state.State, block *proto.Block) (proto.Height, error) } type MicroBlockCache interface { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 99a18462a..05aca5539 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -1,6 +1,8 @@ package state import ( + "fmt" + "github.com/mr-tron/base58/base58" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/errs" @@ -104,11 +106,11 @@ func newTxAppender( func (a *txAppender) checkDuplicateTxIdsImpl(id []byte, recentIds map[string]struct{}) error { // Check recent. if _, ok := recentIds[string(id)]; ok { - return errors.Errorf("transaction with ID %v already in state", id) + return proto.NewInfoMsg(errors.Errorf("transaction with ID %s already in state", base58.Encode(id))) } // Check DB. if _, _, err := a.rw.readTransaction(id); err == nil { - return errors.Errorf("transaction with ID %v already in state", id) + return proto.NewInfoMsg(errors.Errorf("transaction with ID %s already in state", base58.Encode(id))) } return nil } @@ -268,7 +270,7 @@ func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { return nil } -func (a *txAppender) needToCheckOrdersSigs(transaction proto.Transaction, initialisation bool) (bool, bool, error) { +func (a *txAppender) needToCheckOrdersSignatures(transaction proto.Transaction, initialisation bool) (bool, bool, error) { tx, ok := transaction.(proto.Exchange) if !ok { return false, false, nil @@ -342,7 +344,7 @@ func (a *txAppender) verifyTxSigAndData(tx proto.Transaction, params *appendTxPa // Detect what signatures must be checked for this transaction. // For transaction with SmartAccount we don't check signature. checkTxSig := !accountHasVerifierScript - checkOrder1, checkOrder2, err := a.needToCheckOrdersSigs(tx, params.initialisation) + checkOrder1, checkOrder2, err := a.needToCheckOrdersSignatures(tx, params.initialisation) if err != nil { return err } @@ -417,7 +419,11 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro fallibleInfo := &fallibleValidationParams{*params, accountHasVerifierScript} applicationRes, err = a.handleFallible(tx, fallibleInfo) if err != nil { - return errs.Extend(err, "fallible validation failed") + msg := "fallible validation failed" + if txID, err2 := tx.GetID(a.settings.AddressSchemeCharacter); err2 == nil { + msg = fmt.Sprintf("fallible validation failed for transaction '%s'", base58.Encode(txID)) + } + return errs.Extend(err, msg) } // Exchange and Invoke balances are validated in UTX when acceptFailed is false. // When acceptFailed is true, balances are validated inside handleFallible(). @@ -717,7 +723,11 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare validatingUtx: true, initialisation: false, } - return a.appendTx(tx, appendTxArgs) + err = a.appendTx(tx, appendTxArgs) + if err != nil { + return proto.NewInfoMsg(err) + } + return nil } func (a *txAppender) reset() { diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index ee7918379..275b7e7ed 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -9,6 +9,7 @@ import ( "path/filepath" "testing" + "github.com/mr-tron/base58" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/importer" @@ -29,9 +30,9 @@ type testCase struct { } func bigFromStr(s string) *big.Int { - var big big.Int - big.SetString(s, 10) - return &big + var i big.Int + i.SetString(s, 10) + return &i } func TestGenesisConfig(t *testing.T) { @@ -292,13 +293,19 @@ func TestStateManager_SavePeers(t *testing.T) { if err != nil { t.Fatalf("Failed to create temp dir for data: %v\n", err) } - defer os.RemoveAll(dataDir) + defer func() { + err = os.RemoveAll(dataDir) + require.NoError(t, err) + }() manager, err := newStateManager(dataDir, DefaultTestingStateParams(), settings.MainNetSettings) if err != nil { t.Fatalf("Failed to create state manager: %v.\n", err) } - defer manager.Close() + defer func() { + err := manager.Close() + require.NoError(t, err) + }() peers, err := manager.Peers() require.NoError(t, err) @@ -378,9 +385,9 @@ func TestDisallowDuplicateTxIds(t *testing.T) { tx := existingGenesisTx(t) txID, err := tx.GetID(settings.MainNetSettings.AddressSchemeCharacter) assert.NoError(t, err, "tx.GetID() failed") - expectedErrStr := fmt.Sprintf("check duplicate tx ids: transaction with ID %v already in state", txID) + expectedErrStr := fmt.Sprintf("check duplicate tx ids: transaction with ID %s already in state", base58.Encode(txID)) err = manager.ValidateNextTx(tx, 1460678400000, 1460678400000, 3, true) - assert.Error(t, err, "duplicate transacton ID was accepted by state") + assert.Error(t, err, "duplicate transaction ID was accepted by state") assert.EqualError(t, err, expectedErrStr) } @@ -418,13 +425,19 @@ func TestStateManager_Mutex(t *testing.T) { if err != nil { t.Fatalf("Failed to create temp dir for data: %v\n", err) } - defer os.RemoveAll(dataDir) + defer func() { + err := os.RemoveAll(dataDir) + require.NoError(t, err) + }() manager, err := newStateManager(dataDir, DefaultTestingStateParams(), settings.MainNetSettings) if err != nil { t.Fatalf("Failed to create state manager: %v.\n", err) } - defer manager.Close() + defer func() { + err := manager.Close() + require.NoError(t, err) + }() mu := manager.Mutex() mu.Lock().Unlock() From f208d76f533e3dd60bbb3a75dd4449dc9fdcbfb3 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Fri, 14 May 2021 15:13:44 +0300 Subject: [PATCH 34/52] Changed returning value if result was false (#463) * Changed returning value if result was false * Changed returning value for invoke and reentrantInvoke, added more precise log of script limits --- pkg/ride/functions_proto.go | 4 ++-- pkg/state/appender.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 7ad8e08ad..640f09127 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -177,7 +177,7 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { return res.UserResult(), nil } - return nil, errors.Errorf("result of Invoke is false") + return rideThrow("result of reentrantInvoke function is false"), nil } func invoke(env Environment, args ...rideType) (rideType, error) { @@ -338,7 +338,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { return res.UserResult(), nil } - return nil, errors.Errorf("result of Invoke is false") + return rideThrow("result of invoke function is false"), nil } func hashScriptAtAddress(env Environment, args ...rideType) (rideType, error) { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 05aca5539..09a4dc62e 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -259,7 +259,7 @@ func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { } maxBlockComplexity := NewMaxScriptsComplexityInBlock().GetMaxScriptsComplexityInBlock(rideV5Activated) if a.sc.getTotalComplexity() > uint64(maxBlockComplexity) { - return errors.New("complexity limit per block is exceeded") + return errors.Errorf("complexity limit per block is exceeded. total complexity of script is %d, max allowed complexity is %d", int(a.sc.getTotalComplexity()), maxBlockComplexity) } return nil } else if smartAccountsActivated { From 4ede786a4aa577276acca93e22f786b438b6cf84 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 17 May 2021 11:17:55 +0300 Subject: [PATCH 35/52] Changed error to warning in scipt complexity func (#464) * Changed error to warning in scipt complexity func * todo --- pkg/state/appender.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 09a4dc62e..2efa08f5a 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -259,7 +259,8 @@ func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { } maxBlockComplexity := NewMaxScriptsComplexityInBlock().GetMaxScriptsComplexityInBlock(rideV5Activated) if a.sc.getTotalComplexity() > uint64(maxBlockComplexity) { - return errors.Errorf("complexity limit per block is exceeded. total complexity of script is %d, max allowed complexity is %d", int(a.sc.getTotalComplexity()), maxBlockComplexity) + // TODO this is definitely an error, should return it + zap.S().Warnf("complexity limit per block is exceeded. total complexity of script is %d, max allowed complexity is %d", int(a.sc.getTotalComplexity()), maxBlockComplexity) } return nil } else if smartAccountsActivated { From 25555d7e9bc266794c7013e55815203ce43bce2d Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 17 May 2021 15:34:37 +0300 Subject: [PATCH 36/52] Added tests for different versions of script (#465) --- pkg/ride/tree_evaluation_test.go | 320 +++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index b67442bc9..9e4d59787 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -3552,6 +3552,326 @@ func TestMixedReentrantInvokeAndInvoke(t *testing.T) { tearDownDappFromDapp() } +func TestPaymentsDifferentScriptVersion4(t *testing.T) { + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let exchangeRate = 5 + + @Callable(i) + func test() = if ((i.payments[0].assetId != unit)) + then throw("unexpected asset") + else { + let res = invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "testActions",[(i.payments[0].amount * exchangeRate)], [AttachedPayment(unit, 1)]) + if res == res + then + nil + else + throw("Bad returned value") + } + */ + + /* script 2 + {-# STDLIB_VERSION 4 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func testActions(a: Int) = { + [ + IntegerEntry("int", 1) + ] + } + */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAgUAAAAEdW5pdAAAAAAAAAAAAQUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMFAAAAA3JlcwUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAAdCpXM" + secondScript = "AAIEAAAAAAAAAAcIAhIDCgEBAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAABAAAAAWEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQUAAAADbmlsAAAAAM41XKE=" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}}, + } + + smartState := smartStateDappFromDapp + + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9999} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable + intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + + tearDownDappFromDapp() + +} + +func TestPaymentsDifferentScriptVersion3(t *testing.T) { + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let exchangeRate = 5 + + @Callable(i) + func test() = if ((i.payments[0].assetId != unit)) + then throw("unexpected asset") + else { + let res = invoke(Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna'), "testActions",[(i.payments[0].amount * exchangeRate)], [AttachedPayment(unit, 1)]) + if res == res + then + nil + else + throw("Bad returned value") + } + */ + + /* script 2 + {-# STDLIB_VERSION 3 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func testActions(a: Int) = { + + WriteSet( + [DataEntry("int", 1)] + ) + + } + */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + recipientCallable := proto.NewRecipientFromAddress(addressCallable) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "AAIFAAAAAAAAAAQIAhIAAAAAAQAAAAAMZXhjaGFuZ2VSYXRlAAAAAAAAAAAFAAAAAQAAAAFpAQAAAAR0ZXN0AAAAAAMJAQAAAAIhPQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQFAAAABHVuaXQJAAACAAAAAQIAAAAQdW5leHBlY3RlZCBhc3NldAQAAAADcmVzCQAD/AAAAAQJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVdJsioL51Kb50MIIvwpqY4PL2gvI9DKCssCAAAAC3Rlc3RBY3Rpb25zCQAETAAAAAIJAABoAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BQAAAAxleGNoYW5nZVJhdGUFAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAgUAAAAEdW5pdAAAAAAAAAAAAQUAAAADbmlsAwkAAAAAAAACBQAAAANyZXMFAAAAA3JlcwUAAAADbmlsCQAAAgAAAAECAAAAEkJhZCByZXR1cm5lZCB2YWx1ZQAAAAAdCpXM" + secondScript = "AAIDAAAAAAAAAAcIARIDCgEBAAAAAAAAAAEAAAABaQEAAAALdGVzdEFjdGlvbnMAAAABAAAAAWEJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQUAAAADbmlsAAAAAJvCz7w=" + + id = bytes.Repeat([]byte{0}, 32) + + expectedDataEntryWrites := []*proto.DataEntryScriptAction{ + {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, + } + + expectedTransferWrites := []*proto.TransferScriptAction{ + {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}}, + } + + smartState := smartStateDappFromDapp + + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + res, err := CallFunction(env, tree, "test", proto.Arguments{}) + + require.NoError(t, err) + r, ok := res.(DAppResult) + require.True(t, ok) + require.True(t, r.res) + + sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + + expectedActionsResult := &proto.ScriptResult{ + DataEntries: expectedDataEntryWrites, + Transfers: expectedTransferWrites, + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + } + + assert.Equal(t, expectedActionsResult, sr) + + expectedDiffResult := initWrappedState(smartState(), env).diff + + balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9999} + balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} + balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} + expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain + expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender + expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable + intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} + expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + + assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) + assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + + tearDownDappFromDapp() + +} + func TestHashScriptFunc(t *testing.T) { /* {-# STDLIB_VERSION 5 #-} From 6cd5b85f91fd1c5def5edf2481b89939b3a582f8 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 18 May 2021 15:22:41 +0300 Subject: [PATCH 37/52] Check that only dapp can call 'invoke' (#466) * Check that only dapp can call 'invoke' * Check on estimation of invocation functions added to EstimatorV3. Invocation functions are excluded from evaluation scope for expression scripts and verifiers. Co-authored-by: Alexey Kiselev --- pkg/ride/environment.go | 2 +- pkg/ride/functions_proto.go | 9 +-- pkg/ride/runtime.go | 2 +- pkg/ride/runtime_moq_test.go | 86 +++++++++++------------ pkg/ride/tree_estimation_test.go | 31 +++++++++ pkg/ride/tree_estimatorV3.go | 33 +++++---- pkg/ride/tree_evaluation_test.go | 115 ++++++++++++++++++++++++++++++- pkg/ride/tree_evaluator.go | 31 +++++---- 8 files changed, 232 insertions(+), 77 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 55fa6e998..3c341099e 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1249,7 +1249,7 @@ func (e *EvaluationEnvironment) invocation() rideObject { return e.inv } -func (e *EvaluationEnvironment) SetInvocation(inv rideObject) { +func (e *EvaluationEnvironment) setInvocation(inv rideObject) { e.inv = inv } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 640f09127..78ff70fbc 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -6,6 +6,7 @@ import ( "crypto/rsa" sh256 "crypto/sha256" "crypto/x509" + "github.com/wavesplatform/gowaves/pkg/util/common" "github.com/mr-tron/base58" @@ -91,7 +92,7 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { } invocationParam["callerPublicKey"] = rideBytes(common.Dup(callerPublicKey.Bytes())) invocationParam["payments"] = payments - env.SetInvocation(invocationParam) + env.setInvocation(invocationParam) for _, value := range payments { payment, ok := value.(rideObject) @@ -169,7 +170,7 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { } env.setNewDAppAddress(proto.Address(callerAddress)) - env.SetInvocation(oldInvocationParam) + env.setInvocation(oldInvocationParam) if res.UserResult() == nil { return rideUnit{}, nil @@ -247,7 +248,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { } invocationParam["callerPublicKey"] = rideBytes(common.Dup(callerPublicKey.Bytes())) invocationParam["payments"] = payments - env.SetInvocation(invocationParam) + env.setInvocation(invocationParam) for _, value := range payments { payment, ok := value.(rideObject) @@ -330,7 +331,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { } env.setNewDAppAddress(proto.Address(callerAddress)) - env.SetInvocation(oldInvocationParam) + env.setInvocation(oldInvocationParam) if res.UserResult() == nil { return rideUnit{}, nil diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index 4806e86e2..2e0fad17b 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -370,7 +370,7 @@ type Environment interface { setNewDAppAddress(address proto.Address) checkMessageLength(int) bool invocation() rideObject // Invocation object made of invoke transaction - SetInvocation(inv rideObject) + setInvocation(inv rideObject) } type rideConstructor func(Environment) rideType diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index ef676e8f4..ff26e2e2c 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -19,9 +19,6 @@ var _ Environment = &MockRideEnvironment{} // // // make and configure a mocked Environment // mockedEnvironment := &MockRideEnvironment{ -// SetInvocationFunc: func(inv rideObject) { -// panic("mock out the SetInvocation method") -// }, // blockFunc: func() rideObject { // panic("mock out the block method") // }, @@ -37,6 +34,9 @@ var _ Environment = &MockRideEnvironment{} // schemeFunc: func() byte { // panic("mock out the scheme method") // }, +// setInvocationFunc: func(inv rideObject) { +// panic("mock out the setInvocation method") +// }, // setNewDAppAddressFunc: func(address proto.Address) { // panic("mock out the setNewDAppAddress method") // }, @@ -62,9 +62,6 @@ var _ Environment = &MockRideEnvironment{} // // } type MockRideEnvironment struct { - // SetInvocationFunc mocks the SetInvocation method. - SetInvocationFunc func(inv rideObject) - // blockFunc mocks the block method. blockFunc func() rideObject @@ -80,6 +77,9 @@ type MockRideEnvironment struct { // schemeFunc mocks the scheme method. schemeFunc func() byte + // setInvocationFunc mocks the setInvocation method. + setInvocationFunc func(inv rideObject) + // setNewDAppAddressFunc mocks the setNewDAppAddress method. setNewDAppAddressFunc func(address proto.Address) @@ -100,11 +100,6 @@ type MockRideEnvironment struct { // calls tracks calls to the methods. calls struct { - // SetInvocation holds details about calls to the SetInvocation method. - SetInvocation []struct { - // Inv is the inv argument value. - Inv rideObject - } // block holds details about calls to the block method. block []struct { } @@ -122,6 +117,11 @@ type MockRideEnvironment struct { // scheme holds details about calls to the scheme method. scheme []struct { } + // setInvocation holds details about calls to the setInvocation method. + setInvocation []struct { + // Inv is the inv argument value. + Inv rideObject + } // setNewDAppAddress holds details about calls to the setNewDAppAddress method. setNewDAppAddress []struct { // Address is the address argument value. @@ -143,12 +143,12 @@ type MockRideEnvironment struct { txID []struct { } } - lockSetInvocation sync.RWMutex lockblock sync.RWMutex lockcheckMessageLength sync.RWMutex lockheight sync.RWMutex lockinvocation sync.RWMutex lockscheme sync.RWMutex + locksetInvocation sync.RWMutex locksetNewDAppAddress sync.RWMutex lockstate sync.RWMutex lockthis sync.RWMutex @@ -157,37 +157,6 @@ type MockRideEnvironment struct { locktxID sync.RWMutex } -// SetInvocation calls SetInvocationFunc. -func (mock *MockRideEnvironment) SetInvocation(inv rideObject) { - if mock.SetInvocationFunc == nil { - panic("MockRideEnvironment.SetInvocationFunc: method is nil but Environment.SetInvocation was just called") - } - callInfo := struct { - Inv rideObject - }{ - Inv: inv, - } - mock.lockSetInvocation.Lock() - mock.calls.SetInvocation = append(mock.calls.SetInvocation, callInfo) - mock.lockSetInvocation.Unlock() - mock.SetInvocationFunc(inv) -} - -// SetInvocationCalls gets all the calls that were made to SetInvocation. -// Check the length with: -// len(mockedEnvironment.SetInvocationCalls()) -func (mock *MockRideEnvironment) SetInvocationCalls() []struct { - Inv rideObject -} { - var calls []struct { - Inv rideObject - } - mock.lockSetInvocation.RLock() - calls = mock.calls.SetInvocation - mock.lockSetInvocation.RUnlock() - return calls -} - // block calls blockFunc. func (mock *MockRideEnvironment) block() rideObject { if mock.blockFunc == nil { @@ -323,6 +292,37 @@ func (mock *MockRideEnvironment) schemeCalls() []struct { return calls } +// setInvocation calls setInvocationFunc. +func (mock *MockRideEnvironment) setInvocation(inv rideObject) { + if mock.setInvocationFunc == nil { + panic("MockRideEnvironment.setInvocationFunc: method is nil but Environment.setInvocation was just called") + } + callInfo := struct { + Inv rideObject + }{ + Inv: inv, + } + mock.locksetInvocation.Lock() + mock.calls.setInvocation = append(mock.calls.setInvocation, callInfo) + mock.locksetInvocation.Unlock() + mock.setInvocationFunc(inv) +} + +// setInvocationCalls gets all the calls that were made to setInvocation. +// Check the length with: +// len(mockedEnvironment.setInvocationCalls()) +func (mock *MockRideEnvironment) setInvocationCalls() []struct { + Inv rideObject +} { + var calls []struct { + Inv rideObject + } + mock.locksetInvocation.RLock() + calls = mock.calls.setInvocation + mock.locksetInvocation.RUnlock() + return calls +} + // setNewDAppAddress calls setNewDAppAddressFunc. func (mock *MockRideEnvironment) setNewDAppAddress(address proto.Address) { if mock.setNewDAppAddressFunc == nil { diff --git a/pkg/ride/tree_estimation_test.go b/pkg/ride/tree_estimation_test.go index 2a92a2f13..da4f4fdbd 100644 --- a/pkg/ride/tree_estimation_test.go +++ b/pkg/ride/tree_estimation_test.go @@ -232,3 +232,34 @@ func TestStackOverflowOnV2(t *testing.T) { fmt.Println(test.comment, ":", time.Since(start)) } } + +func TestFailOnInvocationInExpression(t *testing.T) { + /* + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE EXPRESSION #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let dapp = Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna') + + match tx { + case t: InvokeScriptTransaction => { + let result = match invoke(dapp, "foo", [5], [AttachedPayment(unit, 10)]) { + case i: Int => i + case _ => throw("Wrong result type") + } + if result == 5 then true else throw("Wrong result '" + result.toString() + "'") + } + case _ => throw("Wrong tx type") + } + */ + source := "BQQAAAAEZGFwcAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBAAAAAF0BQAAAAckbWF0Y2gwBAAAAAZyZXN1bHQEAAAAByRtYXRjaDEJAAP8AAAABAUAAAAEZGFwcAIAAAADZm9vCQAETAAAAAIAAAAAAAAAAAUFAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAgUAAAAEdW5pdAAAAAAAAAAACgUAAAADbmlsAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAANJbnQEAAAAAWkFAAAAByRtYXRjaDEFAAAAAWkJAAACAAAAAQIAAAARV3JvbmcgcmVzdWx0IHR5cGUDCQAAAAAAAAIFAAAABnJlc3VsdAAAAAAAAAAABQYJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAADldyb25nIHJlc3VsdCAnCQABpAAAAAEFAAAABnJlc3VsdAIAAAABJwkAAAIAAAABAgAAAA1Xcm9uZyB0eCB0eXBlUP0hpw==" + src, err := base64.StdEncoding.DecodeString(source) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + _, err = EstimateTree(tree, 3) + require.Error(t, err) +} diff --git a/pkg/ride/tree_estimatorV3.go b/pkg/ride/tree_estimatorV3.go index 1137ab596..f842cd2e6 100644 --- a/pkg/ride/tree_estimatorV3.go +++ b/pkg/ride/tree_estimatorV3.go @@ -67,8 +67,11 @@ func (s *estimationScopeV3) setFunction(id string, cost int, usages []string) { s.functions.set(id, cost, usages) } -func (s *estimationScopeV3) function(id string) (int, []string, error) { +func (s *estimationScopeV3) function(id string, enableInvocation bool) (int, []string, error) { if c, ok := s.builtin[id]; ok { + if (id == "1020" || id == "1021") && !enableInvocation { + return 0, nil, errors.Errorf("function '%s' not found", id) + } return c, nil, nil } return s.functions.get(id) @@ -139,7 +142,7 @@ func newTreeEstimatorV3(tree *Tree) (*treeEstimatorV3, error) { func (e *treeEstimatorV3) estimate() (int, int, map[string]int, error) { if !e.tree.IsDApp() { e.scope.submerge() - c, err := e.walk(e.tree.Verifier) + c, err := e.walk(e.tree.Verifier, false) if err != nil { return 0, 0, nil, err } @@ -154,7 +157,7 @@ func (e *treeEstimatorV3) estimate() (int, int, map[string]int, error) { return 0, 0, nil, errors.New("invalid callable declaration") } e.scope.submerge() - c, err := e.walk(e.wrapFunction(function)) + c, err := e.walk(e.wrapFunction(function), true) if err != nil { return 0, 0, nil, err } @@ -171,7 +174,7 @@ func (e *treeEstimatorV3) estimate() (int, int, map[string]int, error) { return 0, 0, nil, errors.New("invalid verifier declaration") } e.scope.submerge() - c, err := e.walk(e.wrapFunction(verifier)) + c, err := e.walk(e.wrapFunction(verifier), false) if err != nil { return 0, 0, nil, err } @@ -199,24 +202,24 @@ func (e *treeEstimatorV3) wrapFunction(node *FunctionDeclarationNode) Node { return block } -func (e *treeEstimatorV3) walk(node Node) (int, error) { +func (e *treeEstimatorV3) walk(node Node, enableInvocation bool) (int, error) { switch n := node.(type) { case *LongNode, *BytesNode, *BooleanNode, *StringNode: return 1, nil case *ConditionalNode: - ce, err := e.walk(n.Condition) + ce, err := e.walk(n.Condition, enableInvocation) if err != nil { return 0, errors.Wrap(err, "failed to estimate the condition of if") } cs := e.scope.save() - le, err := e.walk(n.TrueExpression) + le, err := e.walk(n.TrueExpression, enableInvocation) if err != nil { return 0, errors.Wrap(err, "failed to estimate the true branch of if") } ls := e.scope.save() e.scope.restore(cs) - re, err := e.walk(n.FalseExpression) + re, err := e.walk(n.FalseExpression, enableInvocation) if err != nil { return 0, errors.Wrap(err, "failed to estimate the false branch of if") } @@ -230,13 +233,13 @@ func (e *treeEstimatorV3) walk(node Node) (int, error) { id := n.Name overlapped := e.scope.used(id) e.scope.remove(id) - c, err := e.walk(n.Block) + c, err := e.walk(n.Block, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate block after declaration of variable '%s'", id) } if e.scope.used(id) { tmp := e.scope.save() - le, err := e.walk(n.Expression) + le, err := e.walk(n.Expression, enableInvocation) if err != nil { return 0, errors.Wrap(err, "failed to estimate let expression") } @@ -258,14 +261,14 @@ func (e *treeEstimatorV3) walk(node Node) (int, error) { id := n.Name tmp := e.scope.save() e.scope.submerge() - fc, err := e.walk(n.Body) + fc, err := e.walk(n.Body, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate cost of function '%s'", id) } bodyUsages := e.scope.emerge() e.scope.restore(tmp) e.scope.setFunction(id, fc, bodyUsages) - bc, err := e.walk(n.Block) + bc, err := e.walk(n.Block, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate block after declaration of function '%s'", id) } @@ -273,7 +276,7 @@ func (e *treeEstimatorV3) walk(node Node) (int, error) { case *FunctionCallNode: id := n.Name - fc, bu, err := e.scope.function(id) + fc, bu, err := e.scope.function(id, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate the call of function '%s'", id) } @@ -283,7 +286,7 @@ func (e *treeEstimatorV3) walk(node Node) (int, error) { ac := 0 for i, a := range n.Arguments { tmp := e.scope.save() - c, err := e.walk(a) + c, err := e.walk(a, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate parameter %d of function call '%s'", i, id) } @@ -293,7 +296,7 @@ func (e *treeEstimatorV3) walk(node Node) (int, error) { return fc + ac, nil case *PropertyNode: - c, err := e.walk(n.Object) + c, err := e.walk(n.Object, enableInvocation) if err != nil { return 0, errors.Wrapf(err, "failed to estimate getter '%s'", n.Name) } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 9e4d59787..af6e92abd 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -996,7 +996,7 @@ func WrappedStateFunc() types.SmartState { } var envDappFromDapp = &MockRideEnvironment{ - SetInvocationFunc: func(invocation rideObject) { + setInvocationFunc: func(invocation rideObject) { inv = invocation }, schemeFunc: func() byte { @@ -3552,6 +3552,119 @@ func TestMixedReentrantInvokeAndInvoke(t *testing.T) { tearDownDappFromDapp() } +func TestExpressionScriptFailInvoke(t *testing.T) { + + /* script 1 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE EXPRESSION #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let dapp = Address(base58'3P8eZVKS7a4troGckytxaefLAi9w7P5aMna') + + match tx { + case t: InvokeScriptTransaction => { + let result = match invoke(dapp, "foo", [5], [AttachedPayment(unit, 10)]) { + case i: Int => i + case _ => throw("Wrong result type") + } + if result == 5 then true else throw("Wrong result '" + result.toString() + "'") + } + case _ => throw("Wrong tx type") + } + */ + + /* script 2 + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(inv) + func foo(amount: Int) = ([ + IntegerEntry("result", amount), + ScriptTransfer(inv.caller, amount, unit) + ], amount) + */ + + txID, err := crypto.NewDigestFromBase58("46R51i3ATxvYbrLJVWpAG3hZuznXtgEobRW6XSZ9MP6f") + require.NoError(t, err) + proof, err := crypto.NewSignatureFromBase58("5MriXpPgobRfNHqYx3vSjrZkDdzDrRF6krgvJp1FRvo2qTyk1KB913Nk1H2hWyKPDzL6pV1y8AWREHdQMGStCBuF") + require.NoError(t, err) + proofs := proto.NewProofs() + proofs.Proofs = []proto.B58Bytes{proof[:]} + require.NoError(t, err) + sender, err := crypto.NewPublicKeyFromBase58("APg7QwJSx6naBUPnGYM2vvsJxQcpYabcbzkNJoMUXLai") + require.NoError(t, err) + senderAddress, err := proto.NewAddressFromPublicKey(proto.MainNetScheme, sender) + require.NoError(t, err) + addr, err = proto.NewAddressFromString("3PFpqr7wTCBu68sSqU7vVv9pttYRjQjGFbv") + require.NoError(t, err) + recipient := proto.NewRecipientFromAddress(addr) + addrPK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addr) + require.NoError(t, err) + + addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") + require.NoError(t, err) + addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) + require.NoError(t, err) + + arguments := proto.Arguments{} + arguments.Append(&proto.StringArgument{Value: "B9spbWQ1rk7YqJUFjW8mLHw6cRcngyh7G9YgRuyFtLv6"}) + + call := proto.FunctionCall{ + Default: false, + Name: "cancel", + Arguments: arguments, + } + tx = &proto.InvokeScriptWithProofs{ + Type: proto.InvokeScriptTransaction, + Version: 1, + ID: &txID, + Proofs: proofs, + ChainID: proto.MainNetScheme, + SenderPK: sender, + ScriptRecipient: recipient, + FunctionCall: call, + Payments: proto.ScriptPayments{proto.ScriptPayment{ + Amount: 10000, + Asset: proto.OptionalAsset{}, + }}, + FeeAsset: proto.OptionalAsset{}, + Fee: 900000, + Timestamp: 1564703444249, + } + + inv, _ = invocationToObject(4, proto.MainNetScheme, tx) + + firstScript = "BQQAAAAEZGFwcAkBAAAAB0FkZHJlc3MAAAABAQAAABoBV0myKgvnUpvnQwgi/Cmpjg8vaC8j0MoKywQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBAAAAAF0BQAAAAckbWF0Y2gwBAAAAAZyZXN1bHQEAAAAByRtYXRjaDEJAAP8AAAABAUAAAAEZGFwcAIAAAADZm9vCQAETAAAAAIAAAAAAAAAAAUFAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAgUAAAAEdW5pdAAAAAAAAAAACgUAAAADbmlsAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAANJbnQEAAAAAWkFAAAAByRtYXRjaDEFAAAAAWkJAAACAAAAAQIAAAARV3JvbmcgcmVzdWx0IHR5cGUDCQAAAAAAAAIFAAAABnJlc3VsdAAAAAAAAAAABQYJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAADldyb25nIHJlc3VsdCAnCQABpAAAAAEFAAAABnJlc3VsdAIAAAABJwkAAAIAAAABAgAAAA1Xcm9uZyB0eCB0eXBlUP0hpw==" + secondScript = "AAIFAAAAAAAAAAcIAhIDCgEBAAAAAAAAAAEAAAADaW52AQAAAANmb28AAAABAAAABmFtb3VudAkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAAZyZXN1bHQFAAAABmFtb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAADaW52AAAABmNhbGxlcgUAAAAGYW1vdW50BQAAAAR1bml0BQAAAANuaWwFAAAABmFtb3VudAAAAAD070Yd" + + id = bytes.Repeat([]byte{0}, 32) + + smartState := smartStateDappFromDapp + + thisAddress = addr + env := envDappFromDapp + + NewWrappedSt := initWrappedState(smartState(), env) + wrappedSt = *NewWrappedSt + + err = AddWavesToSender(senderAddress, 10000, proto.OptionalAsset{}) + require.NoError(t, err) + err = AddExternalPayments(tx.Payments, tx.SenderPK) + require.NoError(t, err) + + src, err := base64.StdEncoding.DecodeString(firstScript) + require.NoError(t, err) + + tree, err := Parse(src) + require.NoError(t, err) + assert.NotNil(t, tree) + + _, err = CallVerifier(env, tree) + require.Error(t, err) + tearDownDappFromDapp() +} + func TestPaymentsDifferentScriptVersion4(t *testing.T) { /* script 1 {-# STDLIB_VERSION 5 #-} diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index eb2e44b04..eb08ff0f9 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -115,7 +115,7 @@ func (s *evaluationScope) userFunction(id string) (*FunctionDeclarationNode, int return nil, 0, errors.Errorf("user function '%s' is not found", id) } -func newEvaluationScope(v int, env Environment) (evaluationScope, error) { +func newEvaluationScope(v int, env Environment, enableInvocation bool) (evaluationScope, error) { constants, err := selectConstantNames(v) if err != nil { return evaluationScope{}, err @@ -136,7 +136,7 @@ func newEvaluationScope(v int, env Environment) (evaluationScope, error) { } cs[n] = esConstant{c: constantProvider(int(id))} } - functions, err := selectFunctionNames(v) + functions, err := selectFunctionNames(v, enableInvocation) if err != nil { return evaluationScope{}, err } @@ -181,24 +181,31 @@ func selectConstantNames(v int) ([]string, error) { } } -func keys(m map[string]int) []string { +func keys(m map[string]int, enableInvocation bool) []string { keys := make([]string, 0, len(m)) for k := range m { - keys = append(keys, k) + switch k { + case "1020", "1021": // invoke and reentrantInvoke function are disabled for expression calls + if enableInvocation { + keys = append(keys, k) + } + default: + keys = append(keys, k) + } } return keys } -func selectFunctionNames(v int) ([]string, error) { +func selectFunctionNames(v int, enableInvocation bool) ([]string, error) { switch v { case 1, 2: - return keys(CatalogueV2), nil + return keys(CatalogueV2, enableInvocation), nil case 3: - return keys(CatalogueV3), nil + return keys(CatalogueV3, enableInvocation), nil case 4: - return keys(CatalogueV4), nil + return keys(CatalogueV4, enableInvocation), nil case 5: - return keys(CatalogueV5), nil + return keys(CatalogueV5, enableInvocation), nil default: return nil, errors.Errorf("unsupported library version %d", v) } @@ -435,7 +442,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { } func treeVerifierEvaluator(env Environment, tree *Tree) (*treeEvaluator, error) { - s, err := newEvaluationScope(tree.LibVersion, env) + s, err := newEvaluationScope(tree.LibVersion, env, false) // Invocation is disabled for expression calls if err != nil { return nil, errors.Wrap(err, "failed to create scope") } @@ -470,7 +477,7 @@ func treeVerifierEvaluator(env Environment, tree *Tree) (*treeEvaluator, error) } func treeFunctionEvaluatorForInvokeDAppFromDApp(env Environment, tree *Tree, name string, args []rideType) (*treeEvaluator, error) { - s, err := newEvaluationScope(tree.LibVersion, env) + s, err := newEvaluationScope(tree.LibVersion, env, true) if err != nil { return nil, errors.Wrap(err, "failed to create scope") } @@ -504,7 +511,7 @@ func treeFunctionEvaluatorForInvokeDAppFromDApp(env Environment, tree *Tree, nam } func treeFunctionEvaluator(env Environment, tree *Tree, name string, args proto.Arguments) (*treeEvaluator, error) { - s, err := newEvaluationScope(tree.LibVersion, env) + s, err := newEvaluationScope(tree.LibVersion, env, true) if err != nil { return nil, errors.Wrap(err, "failed to create scope") } From ec372dcc0654481b33bfd1c4946aa4f674634e24 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 24 May 2021 14:26:35 +0300 Subject: [PATCH 38/52] Added tests (#468) * Added tests * Returned old takeString back * new function returned back * Fixed fmt check * Added one more test * Changed go version in actions * Changed version back * Test on evaluation of expression that lookups string for invalid UTF-8 character added. * Test on RIDE's split function with invalid UTF-8 character added. * Added check on feature in takeString function * The implementation of takeString moved to EvaluationEnvironment * Fixed a mistake * Correct version of protobuf-schemas submodule restored. * Moved check of activation of RideV5 to the state. Co-authored-by: Alexey Kiselev --- pkg/ride/environment.go | 62 +++++++++++++++++++----------- pkg/ride/functions_proto_test.go | 1 + pkg/ride/functions_strings.go | 41 ++++++++++---------- pkg/ride/functions_strings_test.go | 30 ++++++++++++++- pkg/ride/runtime.go | 1 + pkg/ride/runtime_moq_test.go | 49 +++++++++++++++++++++++ pkg/ride/tree_evaluation_test.go | 13 ++++++- pkg/state/appender.go | 6 +++ pkg/state/invoke_applier.go | 2 +- pkg/state/script_caller.go | 10 +++-- 10 files changed, 164 insertions(+), 51 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 3c341099e..d94b4d93a 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1037,16 +1037,17 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme } type EvaluationEnvironment struct { - sch proto.Scheme - st types.SmartState - h rideInt - tx rideObject - id rideType - th rideType - time uint64 - b rideObject - check func(int) bool - inv rideObject + sch proto.Scheme + st types.SmartState + h rideInt + tx rideObject + id rideType + th rideType + time uint64 + b rideObject + check func(int) bool + takeStr func(s string, n int) rideString + inv rideObject } func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*EvaluationEnvironment, error) { @@ -1056,10 +1057,11 @@ func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*EvaluationEnv } return &EvaluationEnvironment{ - sch: scheme, - st: state, - h: rideInt(height), - check: func(int) bool { return true }, + sch: scheme, + st: state, + h: rideInt(height), + check: func(int) bool { return true }, + takeStr: func(s string, n int) rideString { return "" }, }, nil } @@ -1107,18 +1109,28 @@ func NewEnvironmentWithWrappedState(env *EvaluationEnvironment, payments proto.S } return &EvaluationEnvironment{ - sch: env.sch, - st: st, - h: env.h, - tx: env.tx, - id: env.id, - th: env.th, - b: env.b, - check: env.check, - inv: env.inv, + sch: env.sch, + st: st, + h: env.h, + tx: env.tx, + id: env.id, + th: env.th, + b: env.b, + check: env.check, + takeStr: env.takeStr, + inv: env.inv, }, nil } +func (e *EvaluationEnvironment) ChooseTakeString(isRideV5 bool) error { + if !isRideV5 { + e.takeStr = takeRideStringWrong + return nil + } + e.takeStr = takeRideString + return nil +} + func (e *EvaluationEnvironment) ChooseSizeCheck(v int) { if v > 2 { e.check = func(l int) bool { @@ -1245,6 +1257,10 @@ func (e *EvaluationEnvironment) checkMessageLength(l int) bool { return e.check(l) } +func (e *EvaluationEnvironment) takeString(s string, n int) rideString { + return e.takeStr(s, n) +} + func (e *EvaluationEnvironment) invocation() rideObject { return e.inv } diff --git a/pkg/ride/functions_proto_test.go b/pkg/ride/functions_proto_test.go index 1044b1a47..bb0587b30 100644 --- a/pkg/ride/functions_proto_test.go +++ b/pkg/ride/functions_proto_test.go @@ -23,6 +23,7 @@ var ( v3check = func(size int) bool { return size <= maxMessageLength } + v5takeString = takeRideString ) func TestAddressFromString(t *testing.T) { diff --git a/pkg/ride/functions_strings.go b/pkg/ride/functions_strings.go index c38f87220..0e14d83ce 100644 --- a/pkg/ride/functions_strings.go +++ b/pkg/ride/functions_strings.go @@ -112,12 +112,12 @@ func concatStrings(_ Environment, args ...rideType) (rideType, error) { return rideString(out), nil } -func takeString(_ Environment, args ...rideType) (rideType, error) { +func takeString(env Environment, args ...rideType) (rideType, error) { s, n, err := stringAndIntArgs(args) if err != nil { return nil, errors.Wrap(err, "takeString") } - return takeRideString(s, n), nil + return env.takeString(s, n), nil } func dropString(_ Environment, args ...rideType) (rideType, error) { @@ -308,26 +308,27 @@ func runesDrop(s string, n int) string { return res } -// TODO: This is the correct implementation of takeString function that handles runes in UTF-8 string correct -//func runesTake(s string, n int) string { -// out := make([]rune, n) -// copy(out, []rune(s)[:n]) -// return string(out) -//} -// -//func takeRideString(s string, n int) rideString { -// l := utf8.RuneCountInString(s) -// t := n -// if t > l { -// t = l -// } -// if t < 0 { -// t = 0 -// } -// return rideString(runesTake(s, t)) -//} +// This is the CORRECT implementation of takeString function that handles runes in UTF-8 string correct +func runesTake(s string, n int) string { + out := make([]rune, n) + copy(out, []rune(s)[:n]) + return string(out) +} func takeRideString(s string, n int) rideString { + l := utf8.RuneCountInString(s) + t := n + if t > l { + t = l + } + if t < 0 { + t = 0 + } + return rideString(runesTake(s, t)) +} + +// This is the WRONG implementation of takeString function that handles runes in UTF-8 string INCORRECT +func takeRideStringWrong(s string, n int) rideString { b := utf16.Encode([]rune(s)) l := len(b) t := n diff --git a/pkg/ride/functions_strings_test.go b/pkg/ride/functions_strings_test.go index df75ba07b..298bc31b4 100644 --- a/pkg/ride/functions_strings_test.go +++ b/pkg/ride/functions_strings_test.go @@ -37,6 +37,10 @@ func TestConcatStrings(t *testing.T) { } func TestTakeString(t *testing.T) { + env := &MockRideEnvironment{ + takeStringFunc: v5takeString, + } + for _, test := range []struct { args []rideType fail bool @@ -53,9 +57,11 @@ func TestTakeString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, - {[]rideType{rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶🔶🔶\n\nCeli, child of the first light. One of the main characters of the story, she is the first to see the vision of Cloudscape and its inhabitants from the Earth's dimension after the great destruction.\n\nDragorion - avatars sung into being by Eneria to bring sleep to the people of Cloudscape. They speak in dreams as lullabies, symphonies, hymns, arias and melodies. ~Legendarium\n\n©️Art of Monztre\n"), rideInt(50)}, false, rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶?")}, + {[]rideType{rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶🔶🔶\n\nCeli, child of the first light. One of the main characters of the story, she is the first to see the vision of Cloudscape and its inhabitants from the Earth's dimension after the great destruction.\n\nDragorion - avatars sung into being by Eneria to bring sleep to the people of Cloudscape. They speak in dreams as lullabies, symphonies, hymns, arias and melodies. ~Legendarium\n\n©️Art of Monztre\n"), rideInt(50)}, false, rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶🔶🔶\n\n")}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬x"), rideInt(2)}, false, rideString("x冬")}, // the result is `x?` but it should be `x冬` } { - r, err := takeString(nil, test.args...) + r, err := takeString(env, test.args...) if test.fail { assert.Error(t, err) } else { @@ -82,6 +88,8 @@ func TestDropString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬x"), rideInt(2)}, false, rideString("x")}, } { r, err := dropString(nil, test.args...) if test.fail { @@ -108,6 +116,8 @@ func TestSizeString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬x")}, false, rideInt(3)}, } { r, err := sizeString(nil, test.args...) if test.fail { @@ -133,6 +143,11 @@ func TestIndexOfSubstring(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬xqweqwe"), rideString("we")}, false, rideInt(4)}, // unicode indexOf + {[]rideType{takeRideString("世界x冬x", 4), takeRideString("冬", 1)}, false, rideInt(3)}, // unicode indexOf + {[]rideType{rideString("x冬xqweqwe"), rideString("ww")}, false, rideUnit{}}, // unicode indexOf (not present) + {[]rideType{rideString(""), rideString("x冬x")}, false, rideUnit{}}, // unicode indexOf from empty string } { r, err := indexOfSubstring(nil, test.args...) if test.fail { @@ -142,6 +157,7 @@ func TestIndexOfSubstring(t *testing.T) { assert.Equal(t, test.r, r) } } + } func TestIndexOfSubstringWithOffset(t *testing.T) { @@ -161,6 +177,10 @@ func TestIndexOfSubstringWithOffset(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬xqweqwe"), rideString("x冬xqw"), rideInt(0)}, false, rideInt(0)}, // unicode indexOf with zero offset + {[]rideType{rideString("冬weqwe"), rideString("we"), rideInt(2)}, false, rideInt(4)}, // unicode indexOf with start offset + {[]rideType{rideString(""), rideString("x冬x"), rideInt(1)}, false, rideUnit{}}, // unicode indexOf from empty string with offset } { r, err := indexOfSubstringWithOffset(nil, test.args...) if test.fail { @@ -216,6 +236,8 @@ func TestDropRightString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬x"), rideInt(2)}, false, rideString("x")}, } { r, err := dropRightString(nil, test.args...) if test.fail { @@ -245,6 +267,8 @@ func TestTakeRightString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("x冬x"), rideInt(2)}, false, rideString("冬x")}, } { r, err := takeRightString(nil, test.args...) if test.fail { @@ -274,6 +298,8 @@ func TestSplitString(t *testing.T) { {[]rideType{rideInt(1), rideString("x")}, true, nil}, {[]rideType{rideInt(1)}, true, nil}, {[]rideType{}, true, nil}, + // scala tests from https://github.com/wavesplatform/Waves/pull/3367 + {[]rideType{rideString("strx冬x1;🤦;🤦strx冬x2;🤦strx冬x3"), rideString(";🤦")}, false, rideList{rideString("strx冬x1"), rideString(""), rideString("strx冬x2"), rideString("strx冬x3")}}, } { r, err := splitString(nil, test.args...) if test.fail { diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index 2e0fad17b..9a0f1fe1b 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -369,6 +369,7 @@ type Environment interface { timestamp() uint64 setNewDAppAddress(address proto.Address) checkMessageLength(int) bool + takeString(s string, n int) rideString invocation() rideObject // Invocation object made of invoke transaction setInvocation(inv rideObject) } diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index ff26e2e2c..da7bf8bd0 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -43,6 +43,9 @@ var _ Environment = &MockRideEnvironment{} // stateFunc: func() types.SmartState { // panic("mock out the state method") // }, +// takeStringFunc: func(s string, n int) rideString { +// panic("mock out the takeString method") +// }, // thisFunc: func() rideType { // panic("mock out the this method") // }, @@ -86,6 +89,9 @@ type MockRideEnvironment struct { // stateFunc mocks the state method. stateFunc func() types.SmartState + // takeStringFunc mocks the takeString method. + takeStringFunc func(s string, n int) rideString + // thisFunc mocks the this method. thisFunc func() rideType @@ -130,6 +136,13 @@ type MockRideEnvironment struct { // state holds details about calls to the state method. state []struct { } + // takeString holds details about calls to the takeString method. + takeString []struct { + // S is the s argument value. + S string + // N is the n argument value. + N int + } // this holds details about calls to the this method. this []struct { } @@ -151,6 +164,7 @@ type MockRideEnvironment struct { locksetInvocation sync.RWMutex locksetNewDAppAddress sync.RWMutex lockstate sync.RWMutex + locktakeString sync.RWMutex lockthis sync.RWMutex locktimestamp sync.RWMutex locktransaction sync.RWMutex @@ -380,6 +394,41 @@ func (mock *MockRideEnvironment) stateCalls() []struct { return calls } +// takeString calls takeStringFunc. +func (mock *MockRideEnvironment) takeString(s string, n int) rideString { + if mock.takeStringFunc == nil { + panic("MockRideEnvironment.takeStringFunc: method is nil but Environment.takeString was just called") + } + callInfo := struct { + S string + N int + }{ + S: s, + N: n, + } + mock.locktakeString.Lock() + mock.calls.takeString = append(mock.calls.takeString, callInfo) + mock.locktakeString.Unlock() + return mock.takeStringFunc(s, n) +} + +// takeStringCalls gets all the calls that were made to takeString. +// Check the length with: +// len(mockedEnvironment.takeStringCalls()) +func (mock *MockRideEnvironment) takeStringCalls() []struct { + S string + N int +} { + var calls []struct { + S string + N int + } + mock.locktakeString.RLock() + calls = mock.calls.takeString + mock.locktakeString.RUnlock() + return calls +} + // this calls thisFunc. func (mock *MockRideEnvironment) this() rideType { if mock.thisFunc == nil { diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index af6e92abd..ea0f89c07 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -114,6 +114,7 @@ func TestFunctionsEvaluation(t *testing.T) { } return obj }, + takeStringFunc: v5takeString, stateFunc: func() types.SmartState { return &MockSmartState{ RetrieveNewestIntegerEntryFunc: func(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { @@ -170,6 +171,7 @@ func TestFunctionsEvaluation(t *testing.T) { } return obj }, + takeStringFunc: v5takeString, } envWithExchangeTX := &MockRideEnvironment{ transactionFunc: func() rideObject { @@ -179,6 +181,7 @@ func TestFunctionsEvaluation(t *testing.T) { } return obj }, + takeStringFunc: v5takeString, } for _, test := range []struct { name string @@ -323,6 +326,8 @@ func TestFunctionsEvaluation(t *testing.T) { {`LASTINDEXOFN`, `lastIndexOf("cafe bebe dead beef cafe bebe", "bebe", 10) == 5`, `AwkAAAAAAAACCQAEuAAAAAMCAAAAHWNhZmUgYmViZSBkZWFkIGJlZWYgY2FmZSBiZWJlAgAAAARiZWJlAAAAAAAAAAAKAAAAAAAAAAAFrGUCxA==`, env, true, false}, {`LASTINDEXOFN`, `lastIndexOf("cafe bebe dead beef cafe bebe", "dead", 13) == 10`, `AwkAAAAAAAACCQAEuAAAAAMCAAAAHWNhZmUgYmViZSBkZWFkIGJlZWYgY2FmZSBiZWJlAgAAAARkZWFkAAAAAAAAAAANAAAAAAAAAAAKepNV2A==`, env, true, false}, {`LASTINDEXOFN`, `lastIndexOf("cafe bebe dead beef cafe bebe", "dead", 11) == 10`, `AwkAAAAAAAACCQAEuAAAAAMCAAAAHWNhZmUgYmViZSBkZWFkIGJlZWYgY2FmZSBiZWJlAgAAAARkZWFkAAAAAAAAAAALAAAAAAAAAAAKcxKwfA==`, env, true, false}, + {`CONTAINS on incorrect UTF-8 character`, `"x冬x".contains("\ud87e")`, `BAkBAAAACGNvbnRhaW5zAAAAAgIAAAAGePCvoJp4AgAAAAE/5/PEZA==`, env, false, false}, + {`SPLIT on incorrect UTF-8 character`, `"冬x🤦冬".split("\ud87e") == ["冬x🤦冬"]`, `BAkAAAAAAAACCQAEtQAAAAICAAAADfCvoJp48J+kpvCvoJoCAAAAAT8JAARMAAAAAgIAAAAN8K+gmnjwn6Sm8K+gmgUAAAADbmlsLyxljg==`, env, true, false}, } { src, err := base64.StdEncoding.DecodeString(test.script) require.NoError(t, err, test.name) @@ -5445,6 +5450,7 @@ func TestDropElementDApp(t *testing.T) { blockFunc: func() rideObject { return blockInfoToObject(blockInfo) }, + takeStringFunc: v5takeString, stateFunc: func() types.SmartState { return &MockSmartState{ AddingBlockHeightFunc: func() (uint64, error) { @@ -6048,15 +6054,18 @@ func TestAssetInfoV3V4(t *testing.T) { } func TestJSONParsing(t *testing.T) { + env := &MockRideEnvironment{ + takeStringFunc: v5takeString, + } + code := "AwoBAAAADmdldFZhbHVlU3RyaW5nAAAAAQAAAARqc29uCQABLwAAAAIJAAEwAAAAAgUAAAAEanNvbgAAAAAAAAAAAQkBAAAABXZhbHVlAAAAAQkABLMAAAACCQABMAAAAAIFAAAABGpzb24AAAAAAAAAAAECAAAAASIKAQAAAAhnZXRWYWx1ZQAAAAIAAAAEanNvbgAAAANrZXkEAAAACGtleUluZGV4CQEAAAAFdmFsdWUAAAABCQAEswAAAAIFAAAABGpzb24JAAEsAAAAAgkAASwAAAACAgAAAAEiBQAAAANrZXkCAAAAAiI6BAAAAARkYXRhCQABMAAAAAIFAAAABGpzb24JAABkAAAAAgkAAGQAAAACBQAAAAhrZXlJbmRleAkAATEAAAABBQAAAANrZXkAAAAAAAAAAAMJAQAAAA5nZXRWYWx1ZVN0cmluZwAAAAEFAAAABGRhdGEEAAAACWFkZHJlc3NlcwIAAAFgeyJ0aXRsZSI6Ikjhu6NwIMSR4buTbmcgbXVhIGLDoW4gxJHhuqV0IChyZWFsLWVzdGF0ZSBjb250cmFjdCkiLCJ0aW1lc3RhbXAiOjE1OTE2MDg5NDQzNTQsImhhc2giOiJkOGYwOWFjYmRlYTIwMTc5MTUyY2Q5N2RiNDNmNmJjZjhjYjYxMTE1YmE3YzNmZWU3NDk4MWU0ZjRiNTBlNGEwIiwiY3JlYXRvciI6IiIsImFkZHJlc3MxIjoiM015Yjg1REd2N3hqNFhaRlpBTDRHSHVHRG1aU0czQ0NVdlciLCJhZGRyZXNzMiI6IiIsImFkZHJlc3MzIjoiIiwiYWRkcmVzczQiOiIiLCJhZGRyZXNzNSI6IiIsImFkZHJlc3M2IjoiIiwiaXBmcyI6IlFtVEtCbUg5aW4yRU50NkFRcnZwUHpvYWFtMnozcWRFZUhRU1k5M3JkOEpqSFkifQkAAAAAAAACCQEAAAAIZ2V0VmFsdWUAAAACBQAAAAlhZGRyZXNzZXMCAAAACGFkZHJlc3MxAgAAACMzTXliODVER3Y3eGo0WFpGWkFMNEdIdUdEbVpTRzNDQ1V2V6k+k0o=" src, err := base64.StdEncoding.DecodeString(code) require.NoError(t, err) - tree, err := Parse(src) require.NoError(t, err) assert.NotNil(t, tree) - res, err := CallVerifier(nil, tree) + res, err := CallVerifier(env, tree) require.NoError(t, err) r, ok := res.(ScriptResult) require.True(t, ok) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 2efa08f5a..9a7f34122 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -379,6 +379,7 @@ type appendTxParams struct { block *proto.BlockHeader acceptFailed bool blockV5Activated bool + rideV5Activated bool validatingUtx bool initialisation bool } @@ -511,6 +512,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return err + } // Check and append transactions. for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ @@ -520,6 +525,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { block: params.block, acceptFailed: blockV5Activated, blockV5Activated: blockV5Activated, + rideV5Activated: rideV5Activated, validatingUtx: false, initialisation: params.initialisation, } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 15860a705..f0bee67cc 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -662,7 +662,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf return nil, err } // Call script function. - ok, scriptActions, err := ia.sc.invokeFunction(tree, tx, info.blockInfo, *scriptAddr, info.initialisation) + ok, scriptActions, err := ia.sc.invokeFunction(tree, tx, info, *scriptAddr) if !ok { // When ok is false, it means that we could not even start invocation. // We just return error in such case. diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index aa1c53082..27516ae3a 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -188,13 +188,13 @@ func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Dige return a.callAssetScriptCommon(env, assetID, lastBlockInfo, initialisation, acceptFailed) } -func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWithProofs, lastBlockInfo *proto.BlockInfo, scriptAddress proto.Address, initialisation bool) (bool, []proto.ScriptAction, error) { +func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWithProofs, info *fallibleValidationParams, scriptAddress proto.Address) (bool, []proto.ScriptAction, error) { env, err := ride.NewEnvironment(a.settings.AddressSchemeCharacter, a.state) if err != nil { return false, nil, errors.Wrap(err, "failed to create RIDE environment") } env.SetThisFromAddress(scriptAddress) - env.SetLastBlock(lastBlockInfo) + env.SetLastBlock(info.blockInfo) env.SetTimestamp(tx.Timestamp) err = env.SetTransaction(tx) if err != nil { @@ -206,6 +206,10 @@ func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWit } env.ChooseSizeCheck(tree.LibVersion) + err = env.ChooseTakeString(info.rideV5Activated) + if err != nil { + return false, nil, errors.Wrap(err, "failed to choose takeString") + } // Since V5 we have to create environment with wrapped state to which we put attached payments if tree.LibVersion >= 5 { env, err = ride.NewEnvironmentWithWrappedState(env, tx.Payments, tx.SenderPK) @@ -226,7 +230,7 @@ func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWit if err != nil { return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(scriptAddress, ev, !initialisation) + est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(scriptAddress, ev, !info.initialisation) if err != nil { return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) } From 642c395c0020df3268563ec66e1ab11430d40dc6 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 25 May 2021 13:52:43 +0300 Subject: [PATCH 39/52] Merge master to version 0.9 (#470) * Costs of RIDE functions transactionHeightByID and blockInfoByHeight reduced for version 4 of standard library (#406) * Fixed empty senderPublicKey field while asset scritp execution. Fixed an issue then half empty TransferScriptAction produced on invalid asset. (#407) * Fixed calculation of size dependant part of fee of protobuf version of DataTransaction (#409) * RIDE function takeString works with string as UTF-16 string (#418) * Switchable bloom filter. (#424) * Switchable bloom filter. * Fix tests. * Proofs validation added to protobuf and json unmarshaling (#429) * Added error loggs handling (#433) * Added errors handling * Changed function name * Deleted useless struct * Changed errors' logs for shutting down * Changed func name and renamed back a few logs * RIDE function to remove element of list by index implemented and tested. (#435) * Fix microblock signature (#430) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Added block state cache (#434) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Added block state cache * Changed the condition of rollback * Changed position of condition of rollback * Adding block states receiving microblocks * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Block cache cleaning moved to key block application functions. * Functions to check that block already exists added to FSM's block applier. * Cache size debug messages added. Fixed block ID to get from cache. Co-authored-by: Alexey Kiselev * Move error logging to debug (#437) * Log level of errors on appending transaction to UTX set to DEBUG * Network connection errrors moved to DEBUG level * More network log messages moved to DEBUG level. Fixed an issue with invalid blocks added to blocks cache. Naming fixed. * Error on state changing while mining micro block moved to DEBUG level. Handling of micro-block mining task added to Sync FSM. * RIDE function addressToString now accepts invalid address (#444) * Fix block info vrf (#469) * Typo in BlockInfo's field name fixed. VRF calcuation in function blockInfoByHeight replaced by retrieval of hit source at given height. * Function ProtoBlockHitSource doesn't return error but empty slice of bytes. * WIP: Fixed VRF calculation for RIDE, but it fails to retriev actual hit sources for now. * New way to store and precalculate hit sources implemented. BlockVRF is reading not commited hit sources now. * Refactoring of duplicate functions. * Seed peers ports updated. * Fixed error handling * One more error handling fix * Code fixed after merge, test added on incorrect string function. Co-authored-by: Frozen Co-authored-by: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> --- pkg/consensus/blocks_validation.go | 138 +++++++++++++---------------- pkg/consensus/pos_calculator.go | 14 ++- pkg/miner/features.go | 4 +- pkg/node/state_fsm/fsm_idle.go | 7 +- pkg/node/state_fsm/fsm_ng.go | 7 +- pkg/node/state_fsm/fsm_sync.go | 11 +-- pkg/proto/scripting_test.go | 21 +++++ pkg/ride/converters.go | 4 +- pkg/ride/functions_proto.go | 2 +- pkg/ride/functions_strings_test.go | 34 ++++++- pkg/state/appender.go | 2 +- pkg/state/hit_sources.go | 31 ++++--- pkg/state/state.go | 69 ++++++++------- pkg/types/types.go | 4 +- 14 files changed, 202 insertions(+), 146 deletions(-) diff --git a/pkg/consensus/blocks_validation.go b/pkg/consensus/blocks_validation.go index cc348d5e2..3a2165143 100644 --- a/pkg/consensus/blocks_validation.go +++ b/pkg/consensus/blocks_validation.go @@ -39,48 +39,45 @@ func isInvalidMainNetBlock(blockID proto.BlockID, height uint64) bool { type stateInfoProvider interface { BlockchainSettings() (*settings.BlockchainSettings, error) HeaderByHeight(height uint64) (*proto.BlockHeader, error) - HitSourceAtHeight(height uint64) ([]byte, error) - SaveHitSources(startHeight uint64, hs [][]byte) error + NewestHitSourceAtHeight(height uint64) ([]byte, error) NewestEffectiveBalance(addr proto.Recipient, startHeight, endHeight uint64) (uint64, error) NewestIsActiveAtHeight(featureID int16, height proto.Height) (bool, error) } -type ConsensusValidator struct { +type Validator struct { state stateInfoProvider settings *settings.BlockchainSettings startHeight uint64 // Headers to validate. - headers []proto.BlockHeader - hitSources [][]byte - ntpTime types.Time + headers []proto.BlockHeader + ntpTime types.Time } -func NewConsensusValidator(state stateInfoProvider, tm types.Time) (*ConsensusValidator, error) { +func NewValidator(state stateInfoProvider, tm types.Time) (*Validator, error) { s, err := state.BlockchainSettings() if err != nil { return nil, errors.Errorf("failed to get blockchain settings: %v\n", err) } - return &ConsensusValidator{ + return &Validator{ state: state, settings: s, ntpTime: tm, }, nil - } -func (cv *ConsensusValidator) smallerMinimalGeneratingBalanceActivated(height uint64) (bool, error) { +func (cv *Validator) smallerMinimalGeneratingBalanceActivated(height uint64) (bool, error) { return cv.state.NewestIsActiveAtHeight(int16(settings.SmallerMinimalGeneratingBalance), height) } -func (cv *ConsensusValidator) fairPosActivated(height uint64) (bool, error) { +func (cv *Validator) fairPosActivated(height uint64) (bool, error) { return cv.state.NewestIsActiveAtHeight(int16(settings.FairPoS), height) } -func (cv *ConsensusValidator) blockV5Activated(height uint64) (bool, error) { +func (cv *Validator) blockV5Activated(height uint64) (bool, error) { return cv.state.NewestIsActiveAtHeight(int16(settings.BlockV5), height) } -func (cv *ConsensusValidator) posAlgo(height uint64) (PosCalculator, error) { +func (cv *Validator) posAlgo(height uint64) (PosCalculator, error) { fair, err := cv.fairPosActivated(height) if err != nil { return nil, err @@ -98,7 +95,7 @@ func (cv *ConsensusValidator) posAlgo(height uint64) (PosCalculator, error) { return &NxtPosCalculator{}, nil } -func (cv *ConsensusValidator) generationSignatureProvider(height uint64) (GenerationSignatureProvider, error) { +func (cv *Validator) generationSignatureProvider(height uint64) (GenerationSignatureProvider, error) { vrf, err := cv.state.NewestIsActiveAtHeight(int16(settings.BlockV5), height) if err != nil { return nil, err @@ -109,24 +106,36 @@ func (cv *ConsensusValidator) generationSignatureProvider(height uint64) (Genera return &NXTGenerationSignatureProvider{}, nil } -func (cv *ConsensusValidator) headerByHeight(height uint64) (*proto.BlockHeader, error) { +func (cv *Validator) headerByHeight(height uint64) (*proto.BlockHeader, error) { if height <= cv.startHeight { return cv.state.HeaderByHeight(height) } return &cv.headers[height-cv.startHeight-1], nil } -func (cv *ConsensusValidator) hitSourceByHeight(height uint64) ([]byte, error) { - if height <= cv.startHeight { - return cv.state.HitSourceAtHeight(height) +func (cv *Validator) RangeForGeneratingBalanceByHeight(height uint64) (uint64, uint64) { + depth := uint64(firstDepth) + if height >= cv.settings.GenerationBalanceDepthFrom50To1000AfterHeight { + depth = secondDepth + } + bottomLimit := height - depth + 1 + if height < depth { + bottomLimit = 1 + } + return bottomLimit, height +} + +func (cv *Validator) GenerateHitSource(height uint64, header proto.BlockHeader) ([]byte, error) { + hs, _, _, _, err := cv.generateAndCheckNextHitSource(height, &header) + if err != nil { + return nil, err } - return cv.hitSources[height-cv.startHeight-1], nil + return hs, nil } -func (cv *ConsensusValidator) ValidateHeaders(headers []proto.BlockHeader, startHeight uint64) error { +func (cv *Validator) ValidateHeaders(headers []proto.BlockHeader, startHeight uint64) error { cv.startHeight = startHeight cv.headers = headers - cv.hitSources = make([][]byte, 0, len(headers)) for i, header := range headers { height := startHeight + uint64(i) parent, err := cv.headerByHeight(height) @@ -153,13 +162,10 @@ func (cv *ConsensusValidator) ValidateHeaders(headers []proto.BlockHeader, start return errors.Wrap(err, "block version validation failed") } } - if err := cv.state.SaveHitSources(cv.startHeight, cv.hitSources); err != nil { - return errors.Wrap(err, "failed to update hit source") - } return nil } -func (cv *ConsensusValidator) validateEffectiveBalance(header *proto.BlockHeader, balance, height uint64) error { +func (cv *Validator) validateEffectiveBalance(header *proto.BlockHeader, balance, height uint64) error { if header.Timestamp < cv.settings.MinimalGeneratingBalanceCheckAfterTime { return nil } @@ -179,19 +185,7 @@ func (cv *ConsensusValidator) validateEffectiveBalance(header *proto.BlockHeader return nil } -func (cv *ConsensusValidator) RangeForGeneratingBalanceByHeight(height uint64) (uint64, uint64) { - depth := uint64(firstDepth) - if height >= cv.settings.GenerationBalanceDepthFrom50To1000AfterHeight { - depth = secondDepth - } - bottomLimit := height - depth + 1 - if height < depth { - bottomLimit = 1 - } - return bottomLimit, height -} - -func (cv *ConsensusValidator) generatingBalance(height uint64, addr proto.Address) (uint64, error) { +func (cv *Validator) generatingBalance(height uint64, addr proto.Address) (uint64, error) { start, end := cv.RangeForGeneratingBalanceByHeight(height) balance, err := cv.state.NewestEffectiveBalance(proto.NewRecipientFromAddress(addr), start, end) if err != nil { @@ -200,7 +194,7 @@ func (cv *ConsensusValidator) generatingBalance(height uint64, addr proto.Addres return balance, nil } -func (cv *ConsensusValidator) minerGeneratingBalance(height uint64, header *proto.BlockHeader) (uint64, error) { +func (cv *Validator) minerGeneratingBalance(height uint64, header *proto.BlockHeader) (uint64, error) { minerAddr, err := proto.NewAddressFromPublicKey(cv.settings.AddressSchemeCharacter, header.GenPublicKey) if err != nil { return 0, err @@ -208,7 +202,7 @@ func (cv *ConsensusValidator) minerGeneratingBalance(height uint64, header *prot return cv.generatingBalance(height, minerAddr) } -func (cv *ConsensusValidator) validBlockVersionAtHeight(blockchainHeight uint64) (proto.BlockVersion, error) { +func (cv *Validator) validBlockVersionAtHeight(blockchainHeight uint64) (proto.BlockVersion, error) { blockRewardActivated, err := cv.state.NewestIsActiveAtHeight(int16(settings.BlockReward), blockchainHeight) if err != nil { return proto.GenesisBlockVersion, errors.Wrap(err, "IsActiveAtHeight failed") @@ -230,7 +224,7 @@ func (cv *ConsensusValidator) validBlockVersionAtHeight(blockchainHeight uint64) return proto.GenesisBlockVersion, nil } -func (cv *ConsensusValidator) validateBlockVersion(block *proto.BlockHeader, blockchainHeight uint64) error { +func (cv *Validator) validateBlockVersion(block *proto.BlockHeader, blockchainHeight uint64) error { validVersion, err := cv.validBlockVersionAtHeight(blockchainHeight) if err != nil { return err @@ -244,7 +238,7 @@ func (cv *ConsensusValidator) validateBlockVersion(block *proto.BlockHeader, blo return nil } -func (cv *ConsensusValidator) checkTargetLimit(height, target uint64) error { +func (cv *Validator) checkTargetLimit(height, target uint64) error { fair, err := cv.fairPosActivated(height) if err != nil { return err @@ -258,7 +252,7 @@ func (cv *ConsensusValidator) checkTargetLimit(height, target uint64) error { return nil } -func (cv *ConsensusValidator) validateBaseTarget(height uint64, header, parent, greatGrandParent *proto.BlockHeader) error { +func (cv *Validator) validateBaseTarget(height uint64, header, parent, greatGrandParent *proto.BlockHeader) error { if err := cv.checkTargetLimit(height, header.BaseTarget); err != nil { return err } @@ -287,59 +281,57 @@ func (cv *ConsensusValidator) validateBaseTarget(height uint64, header, parent, return nil } -func (cv *ConsensusValidator) validateGeneratorSignatureAndBlockDelay(height uint64, header *proto.BlockHeader) error { +func (cv *Validator) generateAndCheckNextHitSource(height uint64, header *proto.BlockHeader) ([]byte, PosCalculator, GenerationSignatureProvider, bool, error) { pos, err := cv.posAlgo(height) if err != nil { - return errors.Wrapf(err, "failed to validate generation signature") + return nil, nil, nil, false, errors.Wrapf(err, "failed to generate hit source") } - gsp, err := cv.generationSignatureProvider(height + 1) if err != nil { - return errors.Wrap(err, "failed to get generation signature provider") + return nil, nil, nil, false, errors.Wrap(err, "failed to generate hit source") } - vrf, err := cv.state.NewestIsActiveAtHeight(int16(settings.BlockV5), height+1) if err != nil { - return errors.Wrapf(err, "failed to validate generation signature") + return nil, nil, nil, false, errors.Wrap(err, "failed to generate hit source") } - - var hitSource []byte if vrf { - p := pos.HeightForHit(height) - refGenSig, err := cv.hitSourceByHeight(p) + refGenSig, err := cv.state.NewestHitSourceAtHeight(pos.HeightForHit(height)) if err != nil { - return errors.Wrap(err, "failed to validate generation signature") + return nil, nil, nil, false, errors.Wrap(err, "failed to generate hit source") } - var ok bool - ok, hitSource, err = gsp.VerifyGenerationSignature(header.GenPublicKey, refGenSig, header.GenSignature) + ok, hs, err := gsp.VerifyGenerationSignature(header.GenPublicKey, refGenSig, header.GenSignature) if err != nil { - return errors.Wrapf(err, "failed to verify generator signature") + return nil, nil, nil, false, errors.Wrap(err, "failed to validate hit source") } if !ok { - return errors.Errorf("invalid generation signature '%s' of block '%s' at %d (ref gen-sig '%s'), with vrf", + return nil, nil, nil, false, errors.Errorf("invalid hit source '%s' of block '%s' at height %d (ref gen-sig '%s'), with vrf", header.GenSignature.String(), header.ID.String(), height, base58.Encode(refGenSig)) } - cv.hitSources = append(cv.hitSources, hitSource) - + return hs, pos, gsp, vrf, nil } else { - - refHeader, err := cv.headerByHeight(height) + refGenSig, err := cv.state.NewestHitSourceAtHeight(height) if err != nil { - return errors.Wrap(err, "failed to validate generation signature") + return nil, nil, nil, false, errors.Wrap(err, "failed to generate hit source") } - refGenSig := refHeader.GenSignature - ok, gs, err := gsp.VerifyGenerationSignature(header.GenPublicKey, refGenSig, header.GenSignature) + ok, hs, err := gsp.VerifyGenerationSignature(header.GenPublicKey, refGenSig, header.GenSignature) if err != nil { - return errors.Wrapf(err, "failed to verify generator signature") + return nil, nil, nil, false, errors.Wrap(err, "failed to validate hit source") } if !ok { - return errors.Errorf("invalid generation signature '%s' of block '%s' at %d (ref gen-sig '%s'), without vrf", + return nil, nil, nil, false, errors.Errorf("invalid hit source '%s' of block '%s' at height %d (ref gen-sig '%s'), without vrf", header.GenSignature.String(), header.ID.String(), height, base58.Encode(refGenSig)) } + return hs, pos, gsp, vrf, nil + } +} - cv.hitSources = append(cv.hitSources, gs) - - prevHitSource, err := cv.hitSourceByHeight(pos.HeightForHit(height)) +func (cv *Validator) validateGeneratorSignatureAndBlockDelay(height uint64, header *proto.BlockHeader) error { + hitSource, pos, gsp, isVRF, err := cv.generateAndCheckNextHitSource(height, header) + if err != nil { + return errors.Wrap(err, "failed to validate generation signature") + } + if !isVRF { + prevHitSource, err := cv.state.NewestHitSourceAtHeight(pos.HeightForHit(height)) if err != nil { return errors.Wrap(err, "failed to validate generation signature") } @@ -347,13 +339,10 @@ func (cv *ConsensusValidator) validateGeneratorSignatureAndBlockDelay(height uin if err != nil { return errors.Wrap(err, "failed to validate generation signature") } - } - if cv.settings.Type == settings.MainNet && isInvalidMainNetBlock(header.BlockID(), height) { return nil } - parent, err := cv.headerByHeight(height) if err != nil { return errors.Errorf("failed to get parent by height: %v\n", err) @@ -378,11 +367,10 @@ func (cv *ConsensusValidator) validateGeneratorSignatureAndBlockDelay(height uin return errors.Errorf("block '%s' at %d: invalid block timestamp %d: less than min valid timestamp %d (hit source %s)", header.ID, height, header.Timestamp, minTimestamp, base58.Encode(hitSource)) } - return nil } -func (cv *ConsensusValidator) validateBlockTimestamp(header *proto.BlockHeader) error { +func (cv *Validator) validateBlockTimestamp(header *proto.BlockHeader) error { currentTimestamp := proto.NewTimestampFromTime(cv.ntpTime.Now()) if int64(header.Timestamp)-int64(currentTimestamp) > maxTimeDrift { return errors.Errorf( diff --git a/pkg/consensus/pos_calculator.go b/pkg/consensus/pos_calculator.go index d94411415..f2c2ea750 100644 --- a/pkg/consensus/pos_calculator.go +++ b/pkg/consensus/pos_calculator.go @@ -68,17 +68,13 @@ type GenerationSignatureProvider interface { type NXTGenerationSignatureProvider struct { } -// Only generator's public key is used then building NXT generation signature. +// GenerationSignature builds NXT generation signature using only generator's public key. func (p *NXTGenerationSignatureProvider) GenerationSignature(key [crypto.KeySize]byte, msg []byte) ([]byte, error) { return p.signature(key, msg) } func (p *NXTGenerationSignatureProvider) HitSource(key [crypto.KeySize]byte, msg []byte) ([]byte, error) { - hs, err := p.signature(key, msg) - if err != nil { - return nil, err - } - return hs, nil + return p.signature(key, msg) } func (p *NXTGenerationSignatureProvider) signature(key [crypto.KeySize]byte, msg []byte) ([]byte, error) { @@ -124,7 +120,7 @@ func (p *VRFGenerationSignatureProvider) HitSource(key [crypto.KeySize]byte, msg return vrf, nil } -// Verify checks that provided signature is valid against given generator's public key and message. +// VerifyGenerationSignature checks that provided signature is valid against given generator's public key and message. func (p *VRFGenerationSignatureProvider) VerifyGenerationSignature(pk crypto.PublicKey, msg, sig []byte) (bool, []byte, error) { ok, hs, err := crypto.VerifyVRF(pk, msg[:], sig[:]) if err != nil { @@ -221,9 +217,9 @@ func heightForHit(height uint64) uint64 { func calculateBaseTarget( targetBlockDelaySeconds uint64, - confirmedHeight uint64, + _ uint64, confirmedTarget uint64, - confirmedTimestamp uint64, + _ uint64, greatGrandParentTimestamp uint64, applyingBlockTimestamp uint64, delayDelta uint64, diff --git a/pkg/miner/features.go b/pkg/miner/features.go index 4c26711cb..10229cb87 100644 --- a/pkg/miner/features.go +++ b/pkg/miner/features.go @@ -22,9 +22,9 @@ func ParseVoteFeatures(s string) (Features, error) { if s == "" { return Features{}, nil } - splitted := strings.Split(s, ",") + split := strings.Split(s, ",") var out Features - for _, val := range splitted { + for _, val := range split { f, err := parseFeature(val) if err != nil { return nil, err diff --git a/pkg/node/state_fsm/fsm_idle.go b/pkg/node/state_fsm/fsm_idle.go index 562182e99..835451b2e 100644 --- a/pkg/node/state_fsm/fsm_idle.go +++ b/pkg/node/state_fsm/fsm_idle.go @@ -20,10 +20,11 @@ type IdleFsm struct { func (a *IdleFsm) Transaction(p peer.Peer, t proto.Transaction) (FSM, Async, error) { err := a.baseInfo.utx.Add(t) - if err == nil { - a.baseInfo.BroadcastTransaction(t, p) + if err != nil { + return a, nil, proto.NewInfoMsg(err) } - return a, nil, err + a.baseInfo.BroadcastTransaction(t, p) + return a, nil, nil } func (a *IdleFsm) Halt() (FSM, Async, error) { diff --git a/pkg/node/state_fsm/fsm_ng.go b/pkg/node/state_fsm/fsm_ng.go index 21f080f28..46f4b3ae7 100644 --- a/pkg/node/state_fsm/fsm_ng.go +++ b/pkg/node/state_fsm/fsm_ng.go @@ -20,10 +20,11 @@ type NGFsm struct { func (a *NGFsm) Transaction(p peer.Peer, t proto.Transaction) (FSM, Async, error) { err := a.utx.Add(t) - if err == nil { - a.BroadcastTransaction(t, p) + if err != nil { + return a, nil, proto.NewInfoMsg(err) } - return a, nil, err + a.BroadcastTransaction(t, p) + return a, nil, nil } func (a *NGFsm) Task(task AsyncTask) (FSM, Async, error) { diff --git a/pkg/node/state_fsm/fsm_sync.go b/pkg/node/state_fsm/fsm_sync.go index 156176106..84267f895 100644 --- a/pkg/node/state_fsm/fsm_sync.go +++ b/pkg/node/state_fsm/fsm_sync.go @@ -40,18 +40,19 @@ type SyncFsm struct { func (a *SyncFsm) Transaction(p Peer, t proto.Transaction) (FSM, Async, error) { err := a.baseInfo.utx.Add(t) - if err == nil { - a.baseInfo.BroadcastTransaction(t, p) + if err != nil { + return a, nil, proto.NewInfoMsg(err) } - return a, nil, err + a.baseInfo.BroadcastTransaction(t, p) + return a, nil, nil } -// MicroBlock ignores new microblock message. +// MicroBlock ignores new microblocks while syncing. func (a *SyncFsm) MicroBlock(_ Peer, _ *proto.MicroBlock) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } -// MicroBlockInv ignores new microblock message. +// MicroBlockInv ignores microblock requests while syncing. func (a *SyncFsm) MicroBlockInv(_ Peer, _ *proto.MicroBlockInv) (FSM, Async, error) { return a.baseInfo.d.Noop(a) } diff --git a/pkg/proto/scripting_test.go b/pkg/proto/scripting_test.go index f3924b0fd..81c27f6c2 100644 --- a/pkg/proto/scripting_test.go +++ b/pkg/proto/scripting_test.go @@ -267,3 +267,24 @@ func mustRecipientFromString(s string) Recipient { } return r } + +func TestAssetIDGeneration(t *testing.T) { + for _, test := range []struct { + name string + description string + decimals int64 + quantity int64 + reissuable bool + nonce int64 + txID string + assetID string + }{ + {"DUCK-AAAAAAAA-GB", "{\"genotype\": \"DUCK-AAAAAAAA-GB\", \"crossbreeding\": true}", 0, 1, false, 2578353, "BBcyb47NB9cbGKXNPakxKGxmdABLzhxRNsztd9hTad6", "4JzEW8LnTXuZ117iqdFXjuNBx3GG5mUvmZhnZ8V3yty7"}, + {"DUCK-AAAAAAAA-GB", "{\"genotype\": \"DUCK-AAAAAAAA-GB\", \"crossbreeding\": true}", 0, 1, false, 2578353, "BBcyb47NB9cbGKXNPakxKGxmdABLzhxRNsztd9hTad6", "4JzEW8LnTXuZ117iqdFXjuNBx3GG5mUvmZhnZ8V3yty7"}, + {"DUCK-BBBBBBBB-GR", "{\"genotype\": \"DUCK-BBBBBBBB-GR\", \"crossbreeding\": true}", 0, 1, false, 2578301, "AA33kjey1MbsQY29NB9Fy9mMcX2oFaxapsnpBk5sVhxU", "7tuYcoFnBLub562Ddsqb3s7iM9edjA9jn6zePvffLV9j"}, + } { + txID := crypto.MustDigestFromBase58(test.txID) + assetID := GenerateIssueScriptActionID(test.name, test.description, test.decimals, test.quantity, test.reissuable, test.nonce, txID) + assert.Equal(t, test.assetID, assetID.String()) + } +} diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index 18ebb3dd9..68bc21769 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -95,7 +95,7 @@ func blockInfoToObject(info *proto.BlockInfo) rideObject { r["generationSignature"] = rideBytes(common.Dup(info.GenerationSignature.Bytes())) r["generator"] = rideBytes(common.Dup(info.Generator.Bytes())) r["generatorPublicKey"] = rideBytes(common.Dup(info.GeneratorPublicKey.Bytes())) - r["vfr"] = rideUnit{} + r["vrf"] = rideUnit{} if len(info.VRF) > 0 { r["vrf"] = rideBytes(common.Dup(info.VRF.Bytes())) } @@ -115,7 +115,7 @@ func blockHeaderToObject(scheme byte, header *proto.BlockHeader, vrf []byte) (ri r["generationSignature"] = rideBytes(common.Dup(header.GenSignature.Bytes())) r["generator"] = rideAddress(address) r["generatorPublicKey"] = rideBytes(common.Dup(header.GenPublicKey.Bytes())) - r["vfr"] = rideUnit{} + r["vrf"] = rideUnit{} if len(vrf) > 0 { r["vrf"] = rideBytes(common.Dup(vrf)) } diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 78ff70fbc..93cfeee42 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -778,7 +778,7 @@ func blockInfoByHeight(env Environment, args ...rideType) (rideType, error) { if err != nil { return nil, errors.Wrap(err, "blockInfoByHeight") } - vrf, err := env.state().BlockVRF(header, height) + vrf, err := env.state().BlockVRF(header, height-1) if err != nil { return nil, errors.Wrap(err, "blockInfoByHeight") } diff --git a/pkg/ride/functions_strings_test.go b/pkg/ride/functions_strings_test.go index 298bc31b4..8912e6da8 100644 --- a/pkg/ride/functions_strings_test.go +++ b/pkg/ride/functions_strings_test.go @@ -40,7 +40,6 @@ func TestTakeString(t *testing.T) { env := &MockRideEnvironment{ takeStringFunc: v5takeString, } - for _, test := range []struct { args []rideType fail bool @@ -71,6 +70,38 @@ func TestTakeString(t *testing.T) { } } +func TestIncorrectTakeString(t *testing.T) { + env := &MockRideEnvironment{ + takeStringFunc: takeRideStringWrong, + } + for _, test := range []struct { + args []rideType + fail bool + r rideType + }{ + {[]rideType{rideString("abc"), rideInt(2)}, false, rideString("ab")}, + {[]rideType{rideString("abc"), rideInt(4)}, false, rideString("abc")}, + {[]rideType{rideString("abc"), rideInt(0)}, false, rideString("")}, + {[]rideType{rideString("abc"), rideInt(-4)}, false, rideString("")}, + {[]rideType{rideString(""), rideInt(0)}, false, rideString("")}, + {[]rideType{rideString(""), rideInt(3)}, false, rideString("")}, + {[]rideType{rideString("abc")}, true, nil}, + {[]rideType{rideUnit{}}, true, nil}, + {[]rideType{rideInt(1), rideString("x")}, true, nil}, + {[]rideType{rideInt(1)}, true, nil}, + {[]rideType{}, true, nil}, + {[]rideType{rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶🔶🔶\n\nCeli, child of the first light. One of the main characters of the story, she is the first to see the vision of Cloudscape and its inhabitants from the Earth's dimension after the great destruction.\n\nDragorion - avatars sung into being by Eneria to bring sleep to the people of Cloudscape. They speak in dreams as lullabies, symphonies, hymns, arias and melodies. ~Legendarium\n\n©️Art of Monztre\n"), rideInt(50)}, false, rideString("DRAGORION : Cradle of Many Strings\n[MYTHIC]🔶🔶🔶?")}, + } { + r, err := takeString(env, test.args...) + if test.fail { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, test.r, r) + } + } +} + func TestDropString(t *testing.T) { for _, test := range []struct { args []rideType @@ -157,7 +188,6 @@ func TestIndexOfSubstring(t *testing.T) { assert.Equal(t, test.r, r) } } - } func TestIndexOfSubstringWithOffset(t *testing.T) { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 9a7f34122..da4181475 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -173,7 +173,7 @@ func (a *txAppender) currentBlockInfo() (*proto.BlockInfo, error) { if err != nil { return nil, err } - hs, err := a.state.BlockVRF(curHeader, height) + hs, err := a.state.BlockVRF(curHeader, height-1) if err != nil { return nil, err } diff --git a/pkg/state/hit_sources.go b/pkg/state/hit_sources.go index a1fdd603d..dcde7a96e 100644 --- a/pkg/state/hit_sources.go +++ b/pkg/state/hit_sources.go @@ -1,26 +1,25 @@ package state +import ( + "github.com/wavesplatform/gowaves/pkg/proto" +) + const hitSourceSize = 32 type hitSources struct { hs *historyStorage - rw *blockReadWriter } -func newHitSources(hs *historyStorage, rw *blockReadWriter) *hitSources { - return &hitSources{hs, rw} +func newHitSources(hs *historyStorage) *hitSources { + return &hitSources{hs: hs} } -func (hss *hitSources) saveHitSource(hs []byte, height uint64) error { +func (hss *hitSources) appendBlockHitSource(block *proto.Block, blockHeight uint64, hs []byte) error { if len(hs) != hitSourceSize { return errInvalidDataSize } - blockID, err := hss.rw.newestBlockIDByHeight(height) - if err != nil { - return err - } - key := hitSourceKey{height: height} - return hss.hs.addNewEntry(hitSource, key.bytes(), hs, blockID) + key := hitSourceKey{height: blockHeight} + return hss.hs.addNewEntry(hitSource, key.bytes(), hs, block.BlockID()) } func (hss *hitSources) hitSource(height uint64, filter bool) ([]byte, error) { @@ -34,3 +33,15 @@ func (hss *hitSources) hitSource(height uint64, filter bool) ([]byte, error) { } return hs, nil } + +func (hss *hitSources) newestHitSource(height uint64, filter bool) ([]byte, error) { + key := hitSourceKey{height: height} + hs, err := hss.hs.newestTopEntryData(key.bytes(), filter) + if err != nil { + return nil, err + } + if len(hs) != hitSourceSize { + return nil, errInvalidDataSize + } + return hs, nil +} diff --git a/pkg/state/state.go b/pkg/state/state.go index c50f15e8e..3a92a4848 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -89,7 +89,7 @@ func newBlockchainEntitiesStorage(hs *historyStorage, sets *settings.BlockchainS newScriptsComplexity(hs), newInvokeResults(hs), newStateHashes(hs), - newHitSources(hs, rw), + newHitSources(hs), calcHashes, }, nil } @@ -344,8 +344,8 @@ type stateManager struct { // BlockchainSettings: general info about the blockchain type, constants etc. settings *settings.BlockchainSettings - // ConsensusValidator: validator for block headers. - cv *consensus.ConsensusValidator + // Validator: validator for block headers. + cv *consensus.Validator // Appender implements validation/diff management functionality. appender *txAppender atx *addressTransactions @@ -446,7 +446,7 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc return nil, wrapErr(Other, err) } state.appender = appender - cv, err := consensus.NewConsensusValidator(state, params.Time) + cv, err := consensus.NewValidator(state, params.Time) if err != nil { return nil, wrapErr(Other, err) } @@ -531,7 +531,7 @@ func (s *stateManager) addGenesisBlock() error { if err := s.addNewBlock(&s.genesis, nil, true, chans, 0); err != nil { return err } - if err := s.stor.hitSources.saveHitSource(s.genesis.GenSignature, 1); err != nil { + if err := s.stor.hitSources.appendBlockHitSource(&s.genesis, 1, s.genesis.GenSignature); err != nil { return err } close(chans.tasksChan) @@ -624,18 +624,22 @@ func (s *stateManager) TopBlock() *proto.Block { } func (s *stateManager) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) { - var vrf []byte = nil - if blockHeader.Version >= proto.ProtobufBlockVersion { - pos := &consensus.FairPosCalculatorV2{} // BlockV5 and FairPoSV2 are activated at the same time - gsp := &consensus.VRFGenerationSignatureProvider{} - hitSourceHeader, err := s.NewestHeaderByHeight(pos.HeightForHit(height)) - if err != nil { - return nil, err - } - _, vrf, err = gsp.VerifyGenerationSignature(blockHeader.GenPublicKey, hitSourceHeader.GenSignature.Bytes(), blockHeader.GenSignature) - if err != nil { - return nil, err - } + if blockHeader.Version < proto.ProtobufBlockVersion { + return nil, nil + } + pos := &consensus.FairPosCalculatorV2{} + p := pos.HeightForHit(height) + refHitSource, err := s.NewestHitSourceAtHeight(p) + if err != nil { + return nil, err + } + gsp := &consensus.VRFGenerationSignatureProvider{} + ok, vrf, err := gsp.VerifyGenerationSignature(blockHeader.GenPublicKey, refHitSource, blockHeader.GenSignature) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("invalid VRF") } return vrf, nil } @@ -1344,6 +1348,13 @@ func (s *stateManager) addBlocks(initialisation bool) (*proto.Block, error) { return nil, verifyError case chans.tasksChan <- task: } + hs, err := s.cv.GenerateHitSource(curHeight, block.BlockHeader) + if err != nil { + return nil, err + } + if err := s.stor.hitSources.appendBlockHitSource(block, curHeight+1, hs); err != nil { + return nil, err + } // Save block to storage, check its transactions, create and save balance diffs for its transactions. if err := s.addNewBlock(block, lastAppliedBlock, initialisation, chans, curHeight); err != nil { return nil, err @@ -1475,24 +1486,20 @@ func (s *stateManager) HitSourceAtHeight(height uint64) ([]byte, error) { return nil, wrapErr(RetrievalError, err) } if height < 1 || height > maxHeight { - return nil, wrapErr(InvalidInputError, - errors.Errorf("HitSourceAtHeight: height %d out of valid range [%d, %d]", height, 1, maxHeight)) + return nil, wrapErr(InvalidInputError, errors.Errorf("HitSourceAtHeight: height %d out of valid range [1, %d]", height, maxHeight)) } - hs, err := s.stor.hitSources.hitSource(height, true) + return s.stor.hitSources.hitSource(height, true) +} + +func (s *stateManager) NewestHitSourceAtHeight(height uint64) ([]byte, error) { + maxHeight, err := s.NewestHeight() if err != nil { return nil, wrapErr(RetrievalError, err) } - return hs, nil -} - -func (s *stateManager) SaveHitSources(startHeight uint64, hitSources [][]byte) error { - for i, hs := range hitSources { - err := s.stor.hitSources.saveHitSource(hs, uint64(i+1)+startHeight) - if err != nil { - return err - } + if height < 1 || height > maxHeight { + return nil, wrapErr(InvalidInputError, errors.Errorf("NewestHitSourceAtHeight: height %d out of valid range [1, %d]", height, maxHeight)) } - return nil + return s.stor.hitSources.newestHitSource(height, true) } func (s *stateManager) CurrentScore() (*big.Int, error) { @@ -1560,7 +1567,7 @@ func (s *stateManager) ResetValidationList() { } } -// For UTX validation. +// ValidateNextTx function must be used for UTX validation only. func (s *stateManager) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, v proto.BlockVersion, acceptFailed bool) error { if err := s.appender.validateNextTx(tx, currentTimestamp, parentTimestamp, v, acceptFailed); err != nil { return err diff --git a/pkg/types/types.go b/pkg/types/types.go index f4b559da0..2bb533c05 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -12,7 +12,7 @@ type Scheduler interface { Reschedule() } -// Abstract handler that called when event happens +// Handler is an abstract function that called when an event happens. type Handler interface { Handle() } @@ -33,7 +33,7 @@ type TransactionWithBytes struct { B []byte } -// state for smart contracts +// SmartState is a part of state used by smart contracts. type SmartState interface { NewestScriptPKByAddr(addr proto.Address) (crypto.PublicKey, error) AddingBlockHeight() (uint64, error) From 4c9c4dd6af59a3904a585ba782a1e2eb42f6e73f Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 25 May 2021 15:43:22 +0300 Subject: [PATCH 40/52] Initializatin of RIDE environment with string function fixed. (#471) --- pkg/ride/environment.go | 9 ++- pkg/state/appender.go | 22 +++---- pkg/state/common_test.go | 4 +- pkg/state/diff_applier_test.go | 6 +- pkg/state/invoke_applier.go | 16 ++--- pkg/state/script_caller.go | 38 ++++++----- pkg/state/transaction_checker_test.go | 2 +- pkg/state/transaction_differ_test.go | 90 +++++++++++++-------------- 8 files changed, 101 insertions(+), 86 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index d94b4d93a..f39bda900 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -440,6 +440,11 @@ func (ws *WrappedState) validateAsset(action proto.ScriptAction, asset proto.Opt } localEnv.SetThisFromAssetInfo(assetInfo) } + + if err := localEnv.ChooseTakeString(true); err != nil { + return false, errors.Wrap(err, "failed to initialize local environment") + } + r, err := CallVerifier(localEnv, tree) if err != nil { return false, errors.Wrapf(err, "failed to call script on asset '%s'", asset.String()) @@ -1060,8 +1065,8 @@ func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*EvaluationEnv sch: scheme, st: state, h: rideInt(height), - check: func(int) bool { return true }, - takeStr: func(s string, n int) rideString { return "" }, + check: func(int) bool { return true }, // By default, for versions below 2 there was no check, always ok. + takeStr: func(s string, n int) rideString { panic("function 'takeStr' was not initialized") }, }, nil } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index da4181475..c28ab3bca 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -210,17 +210,17 @@ func (a *txAppender) checkTxFees(tx proto.Transaction, info *fallibleValidationP } // This function is used for script validation of transaction that can't fail. -func (a *txAppender) checkTransactionScripts(tx proto.Transaction, accountScripted bool, checkerInfo *checkerInfo, blockInfo *proto.BlockInfo) (uint64, error) { +func (a *txAppender) checkTransactionScripts(tx proto.Transaction, accountScripted bool, params *appendTxParams) (uint64, error) { scriptsRuns := uint64(0) if accountScripted { // Check script. - if err := a.sc.callAccountScriptWithTx(tx, blockInfo, checkerInfo.initialisation); err != nil { + if err := a.sc.callAccountScriptWithTx(tx, params); err != nil { return 0, errs.Extend(err, "callAccountScriptWithTx") } scriptsRuns++ } // Check against state. - txSmartAssets, err := a.txHandler.checkTx(tx, checkerInfo) + txSmartAssets, err := a.txHandler.checkTx(tx, params.checkerInfo) if err != nil { return 0, err } @@ -230,7 +230,7 @@ func (a *txAppender) checkTransactionScripts(tx proto.Transaction, accountScript } for _, smartAsset := range txSmartAssets { // Check smart asset's script. - _, err := a.sc.callAssetScript(tx, smartAsset, blockInfo, checkerInfo.initialisation, false) + _, err := a.sc.callAssetScript(tx, smartAsset, params) if err != nil { return 0, errs.Extend(err, "callAssetScript") } @@ -418,7 +418,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro case proto.InvokeScriptTransaction, proto.ExchangeTransaction: // Invoke and Exchange transactions should be handled differently. // They may fail, and will be saved to blockchain anyway. - fallibleInfo := &fallibleValidationParams{*params, accountHasVerifierScript} + fallibleInfo := &fallibleValidationParams{params, accountHasVerifierScript} applicationRes, err = a.handleFallible(tx, fallibleInfo) if err != nil { msg := "fallible validation failed" @@ -432,7 +432,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro needToValidateBalanceDiff = params.validatingUtx && !params.acceptFailed default: // Execute transaction's scripts, check against state. - txScriptsRuns, err := a.checkTransactionScripts(tx, accountHasVerifierScript, params.checkerInfo, params.blockInfo) + txScriptsRuns, err := a.checkTransactionScripts(tx, accountHasVerifierScript, params) if err != nil { return err } @@ -553,7 +553,7 @@ func (a *txAppender) moveChangesToHistoryStorage(initialisation bool) error { } type fallibleValidationParams struct { - appendTxParams + *appendTxParams senderScripted bool } @@ -600,7 +600,7 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati // At first, we call accounts and orders scripts which must not fail. if info.senderScripted { // Check script on account. - err := a.sc.callAccountScriptWithTx(tx, info.blockInfo, info.initialisation) + err := a.sc.callAccountScriptWithTx(tx, info.appendTxParams) if err != nil { return nil, err } @@ -624,13 +624,13 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati return nil, err } if o1Scripted { - if err := a.sc.callAccountScriptWithOrder(o1, info.blockInfo, info.initialisation); err != nil { + if err := a.sc.callAccountScriptWithOrder(o1, info.blockInfo, info.rideV5Activated, info.initialisation); err != nil { return nil, errors.Wrap(err, "script failure on first order") } scriptsRuns++ } if o2Scripted { - if err := a.sc.callAccountScriptWithOrder(o2, info.blockInfo, info.initialisation); err != nil { + if err := a.sc.callAccountScriptWithOrder(o2, info.blockInfo, info.rideV5Activated, info.initialisation); err != nil { return nil, errors.Wrap(err, "script failure on second order") } scriptsRuns++ @@ -659,7 +659,7 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati } // Check smart assets' scripts. for _, smartAsset := range txSmartAssets { - res, err := a.sc.callAssetScript(tx, smartAsset, info.blockInfo, info.initialisation, info.acceptFailed) + res, err := a.sc.callAssetScript(tx, smartAsset, info.appendTxParams) if err != nil && !info.acceptFailed { return nil, err } diff --git a/pkg/state/common_test.go b/pkg/state/common_test.go index c23877b06..88c1cf397 100644 --- a/pkg/state/common_test.go +++ b/pkg/state/common_test.go @@ -79,7 +79,7 @@ func defaultBlockInfo() *proto.BlockInfo { } } -func defaultDifferInfo(t *testing.T) *differInfo { +func defaultDifferInfo() *differInfo { return &differInfo{false, defaultBlockInfo()} } @@ -97,7 +97,7 @@ func defaultAppendTxParams(t *testing.T) *appendTxParams { func defaultFallibleValidationParams(t *testing.T) *fallibleValidationParams { appendTxPrms := defaultAppendTxParams(t) return &fallibleValidationParams{ - appendTxParams: *appendTxPrms, + appendTxParams: appendTxPrms, senderScripted: false, } } diff --git a/pkg/state/diff_applier_test.go b/pkg/state/diff_applier_test.go index fac8ac454..2c3c63a02 100644 --- a/pkg/state/diff_applier_test.go +++ b/pkg/state/diff_applier_test.go @@ -71,7 +71,7 @@ func TestDiffApplierWithWaves(t *testing.T) { to.stor.flush(t) profile, err = to.stor.entities.balances.wavesBalance(testGlobal.senderInfo.addr, true) assert.NoError(t, err, "wavesBalance() failed") - assert.Equal(t, diff.leaseIn, int64(profile.leaseIn)) + assert.Equal(t, diff.leaseIn, profile.leaseIn) // Test that leasing leased money leads to error. diff = balanceDiff{leaseOut: 101, blockID: blockID0} changes = []balanceChanges{ @@ -133,13 +133,13 @@ func TestTransferOverspend(t *testing.T) { to.stor.addBlock(t, blockID0) // Create overspend transfer to self. tx := createTransferWithSig(t) - info := defaultDifferInfo(t) + info := defaultDifferInfo() info.blockInfo.Timestamp = settings.MainNetSettings.CheckTempNegativeAfterTime - 1 tx.Timestamp = info.blockInfo.Timestamp tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) // Set balance equal to tx Fee. err := to.stor.entities.balances.setAssetBalance(testGlobal.senderInfo.addr, testGlobal.asset0.assetID, tx.Fee, blockID0) - assert.NoError(t, err, "setAssetBalacne() failed") + assert.NoError(t, err, "setAssetBalance() failed") to.stor.flush(t) // Sending to self more than possess before settings.MainNetSettings.CheckTempNegativeAfterTime is fine. diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index f0bee67cc..130e9d350 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -279,7 +279,7 @@ func (ia *invokeApplier) senderCredentialsFromScriptAction(a proto.ScriptAction, func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, info *addlInvokeInfo) (proto.TxFailureReason, txBalanceChanges, error) { // Check smart asset scripts on payments. for _, smartAsset := range info.paymentSmartAssets { - r, err := ia.sc.callAssetScript(tx, smartAsset, info.blockInfo, info.initialisation, info.acceptFailed) + r, err := ia.sc.callAssetScript(tx, smartAsset, info.fallibleValidationParams.appendTxParams) if err != nil { return proto.DAppError, info.failedChanges, errors.Errorf("failed to call asset %s script on payment: %v", smartAsset.String(), err) } @@ -353,7 +353,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to convert transfer to full script transfer") } // Call asset script if transferring smart asset. - res, err := ia.sc.callAssetScriptWithScriptTransfer(fullTr, a.Asset.ID, info.blockInfo, info.initialisation, info.acceptFailed) + res, err := ia.sc.callAssetScriptWithScriptTransfer(fullTr, a.Asset.ID, info.appendTxParams) if err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to call asset script on transfer set") } @@ -427,7 +427,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if math.MaxInt64-a.Quantity < assetInfo.quantity.Int64() && info.block.Timestamp >= ia.settings.ReissueBugWindowTimeEnd { return proto.DAppError, info.failedChanges, errors.New("asset total value overflow") } - ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) + ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, *tx.ID, tx.Timestamp, info.appendTxParams) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -475,7 +475,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if assetInfo.quantity.Cmp(quantityDiff) == -1 { return proto.DAppError, info.failedChanges, errs.NewAccountBalanceError("trying to burn more assets than exist at all") } - ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, info.blockInfo, *tx.ID, tx.Timestamp, info.initialisation, info.acceptFailed) + ok, res, err := ia.validateActionSmartAsset(a.AssetID, a, senderPK, *tx.ID, tx.Timestamp, info.appendTxParams) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -616,7 +616,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf info.acceptFailed = info.blockV5Activated && info.acceptFailed // Check sender script, if any. if info.senderScripted { - if err := ia.sc.callAccountScriptWithTx(tx, info.blockInfo, info.initialisation); err != nil { + if err := ia.sc.callAccountScriptWithTx(tx, info.appendTxParams); err != nil { // Never accept invokes with failed script on transaction sender. return nil, err } @@ -781,8 +781,8 @@ func (ia *invokeApplier) checkFullFee(tx *proto.InvokeScriptWithProofs, scriptRu } func (ia *invokeApplier) validateActionSmartAsset(asset crypto.Digest, action proto.ScriptAction, callerPK crypto.PublicKey, - blockInfo *proto.BlockInfo, txID crypto.Digest, txTimestamp uint64, initialisation, acceptFailed bool) (bool, ride.RideResult, error) { - isSmartAsset := ia.stor.scriptsStorage.newestIsSmartAsset(asset, !initialisation) + txID crypto.Digest, txTimestamp uint64, params *appendTxParams) (bool, ride.RideResult, error) { + isSmartAsset := ia.stor.scriptsStorage.newestIsSmartAsset(asset, !params.initialisation) if !isSmartAsset { return true, nil, nil } @@ -794,7 +794,7 @@ func (ia *invokeApplier) validateActionSmartAsset(asset crypto.Digest, action pr if err != nil { return false, nil, err } - res, err := ia.sc.callAssetScriptCommon(env, asset, blockInfo, initialisation, acceptFailed) + res, err := ia.sc.callAssetScriptCommon(env, asset, params) if err != nil { return false, nil, err } diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index 27516ae3a..3717f84d0 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -33,7 +33,7 @@ func newScriptCaller( }, nil } -func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockInfo *proto.BlockInfo, initialisation bool) error { +func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockInfo *proto.BlockInfo, isRideV5 bool, initialisation bool) error { sender, err := proto.NewAddressFromPublicKey(a.settings.AddressSchemeCharacter, order.GetSenderPK()) if err != nil { return err @@ -53,6 +53,9 @@ func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockIn env.SetThisFromAddress(sender) env.SetLastBlock(lastBlockInfo) env.ChooseSizeCheck(tree.LibVersion) + if err := env.ChooseTakeString(isRideV5); err != nil { + return errors.Wrap(err, "failed to initialize environment") + } err = env.SetTransactionFromOrder(order) if err != nil { return errors.Wrap(err, "failed to convert order") @@ -80,12 +83,12 @@ func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockIn return nil } -func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, lastBlockInfo *proto.BlockInfo, initialisation bool) error { +func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, params *appendTxParams) error { senderAddr, err := proto.NewAddressFromPublicKey(a.settings.AddressSchemeCharacter, tx.GetSenderPK()) if err != nil { return err } - tree, err := a.stor.scriptsStorage.newestScriptByAddr(senderAddr, !initialisation) + tree, err := a.stor.scriptsStorage.newestScriptByAddr(senderAddr, !params.initialisation) if err != nil { return err } @@ -97,8 +100,12 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, lastBlockIn if err != nil { return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) } + env.ChooseSizeCheck(tree.LibVersion) + if err := env.ChooseTakeString(params.rideV5Activated); err != nil { + return errors.Wrap(err, "failed to initialize environment") + } env.SetThisFromAddress(senderAddr) - env.SetLastBlock(lastBlockInfo) + env.SetLastBlock(params.blockInfo) err = env.SetTransaction(tx) if err != nil { return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) @@ -118,7 +125,7 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, lastBlockIn if err != nil { return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, ev, !initialisation) + est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, ev, !params.initialisation) if err != nil { return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) } @@ -126,12 +133,15 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, lastBlockIn return nil } -func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, assetID crypto.Digest, lastBlockInfo *proto.BlockInfo, initialisation bool, acceptFailed bool) (ride.RideResult, error) { - tree, err := a.stor.scriptsStorage.newestScriptByAsset(assetID, !initialisation) +func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { + tree, err := a.stor.scriptsStorage.newestScriptByAsset(assetID, !params.initialisation) if err != nil { return nil, err } env.ChooseSizeCheck(tree.LibVersion) + if err := env.ChooseTakeString(params.rideV5Activated); err != nil { + return nil, errors.Wrap(err, "failed to initialize environment") + } switch tree.LibVersion { case 4, 5: assetInfo, err := a.state.NewestFullAssetInfo(assetID) @@ -146,12 +156,12 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, as } env.SetThisFromAssetInfo(assetInfo) } - env.SetLastBlock(lastBlockInfo) + env.SetLastBlock(params.blockInfo) r, err := ride.CallVerifier(env, tree) if err != nil { return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) } - if !r.Result() && !acceptFailed { + if !r.Result() && !params.acceptFailed { return nil, errs.NewTransactionNotAllowedByScript(r.UserError(), assetID.Bytes()) } // Increase complexity. @@ -159,7 +169,7 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, as if err != nil { return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, ev, !initialisation) + est, err := a.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, ev, !params.initialisation) if err != nil { return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) } @@ -167,16 +177,16 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, as return r, nil } -func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTransfer, assetID crypto.Digest, lastBlockInfo *proto.BlockInfo, initialisation bool, acceptFailed bool) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTransfer, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { env, err := ride.NewEnvironment(a.settings.AddressSchemeCharacter, a.state) if err != nil { return nil, err } env.SetTransactionFromScriptTransfer(tr) - return a.callAssetScriptCommon(env, assetID, lastBlockInfo, initialisation, acceptFailed) + return a.callAssetScriptCommon(env, assetID, params) } -func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Digest, lastBlockInfo *proto.BlockInfo, initialisation bool, acceptFailed bool) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { env, err := ride.NewEnvironment(a.settings.AddressSchemeCharacter, a.state) if err != nil { return nil, err @@ -185,7 +195,7 @@ func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Dige if err != nil { return nil, err } - return a.callAssetScriptCommon(env, assetID, lastBlockInfo, initialisation, acceptFailed) + return a.callAssetScriptCommon(env, assetID, params) } func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWithProofs, info *fallibleValidationParams, scriptAddress proto.Address) (bool, []proto.ScriptAction, error) { diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 52f3aec90..52c8bb129 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -49,7 +49,7 @@ func TestCheckGenesis(t *testing.T) { assert.NoError(t, err, "failed to clean test data dirs") }() - tx := createGenesis(t) + tx := createGenesis() info := defaultCheckerInfo(t) _, err := to.tc.checkGenesis(tx, info) info.blockID = proto.NewBlockIDFromSignature(genSig) diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index b45ced18f..cc36945e4 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -41,7 +41,7 @@ func createDifferTestObjects(t *testing.T) (*differTestObjects, []string) { return &differTestObjects{stor, td, tp}, path } -func createGenesis(t *testing.T) *proto.Genesis { +func createGenesis() *proto.Genesis { return proto.NewUnsignedGenesis(testGlobal.recipientInfo.addr, defaultAmount, defaultTimestamp) } @@ -55,8 +55,8 @@ func TestCreateDiffGenesis(t *testing.T) { assert.NoError(t, err, "failed to clean test data dirs") }() - tx := createGenesis(t) - ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo(t)) + tx := createGenesis() + ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffGenesis() failed") correctDiff := txDiff{testGlobal.recipientInfo.wavesKey: newBalanceDiff(int64(tx.Amount), 0, 0, false)} assert.Equal(t, correctDiff, ch.diff) @@ -84,7 +84,7 @@ func TestCreateDiffPayment(t *testing.T) { }() tx := createPayment(t) - ch, err := to.td.createDiffPayment(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffPayment(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffPayment() failed") correctDiff := txDiff{ @@ -121,7 +121,7 @@ func TestCreateDiffTransferWithSig(t *testing.T) { assetId := tx.FeeAsset.ID to.stor.createAsset(t, assetId) - ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") correctDiff := txDiff{ @@ -137,11 +137,11 @@ func TestCreateDiffTransferWithSig(t *testing.T) { assert.Equal(t, correctAddrs, ch.addrs) to.stor.activateSponsorship(t) - _, err = to.td.createDiffTransferWithSig(tx, defaultDifferInfo(t)) + _, err = to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.Error(t, err, "createDiffTransferWithSig() did not fail with unsponsored asset") err = to.stor.entities.sponsoredAssets.sponsorAsset(assetId, 10, blockID0) assert.NoError(t, err, "sponsorAsset() failed") - ch, err = to.td.createDiffTransferWithSig(tx, defaultDifferInfo(t)) + ch, err = to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed with valid sponsored asset") feeInWaves, err := to.stor.entities.sponsoredAssets.sponsoredAssetToWaves(assetId, tx.Fee) @@ -183,7 +183,7 @@ func TestCreateDiffTransferWithProofs(t *testing.T) { assetId := tx.FeeAsset.ID to.stor.createAsset(t, assetId) - ch, err := to.td.createDiffTransferWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffTransferWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithProofs() failed") correctDiff := txDiff{ @@ -199,11 +199,11 @@ func TestCreateDiffTransferWithProofs(t *testing.T) { assert.Equal(t, correctAddrs, ch.addrs) to.stor.activateSponsorship(t) - _, err = to.td.createDiffTransferWithProofs(tx, defaultDifferInfo(t)) + _, err = to.td.createDiffTransferWithProofs(tx, defaultDifferInfo()) assert.Error(t, err, "createDiffTransferWithProofs() did not fail with unsponsored asset") err = to.stor.entities.sponsoredAssets.sponsorAsset(assetId, 10, blockID0) assert.NoError(t, err, "sponsorAsset() failed") - ch, err = to.td.createDiffTransferWithProofs(tx, defaultDifferInfo(t)) + ch, err = to.td.createDiffTransferWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithProofs() failed with valid sponsored asset") feeInWaves, err := to.stor.entities.sponsoredAssets.sponsoredAssetToWaves(assetId, tx.Fee) @@ -249,7 +249,7 @@ func TestCreateDiffIssueWithSig(t *testing.T) { }() tx := createIssueWithSig(t, 1000) - ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") correctDiff := txDiff{ @@ -289,7 +289,7 @@ func TestCreateDiffIssueWithProofs(t *testing.T) { }() tx := createIssueWithProofs(t, 1000) - ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithProofs() failed") correctDiff := txDiff{ @@ -322,7 +322,7 @@ func TestCreateDiffReissueWithSig(t *testing.T) { }() tx := createReissueWithSig(t, 1000) - ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") correctDiff := txDiff{ @@ -355,7 +355,7 @@ func TestCreateDiffReissueWithProofs(t *testing.T) { }() tx := createReissueWithProofs(t, 1000) - ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithProofs() failed") correctDiff := txDiff{ @@ -388,7 +388,7 @@ func TestCreateDiffBurnWithSig(t *testing.T) { }() tx := createBurnWithSig(t) - ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") correctDiff := txDiff{ @@ -421,7 +421,7 @@ func TestCreateDiffBurnWithProofs(t *testing.T) { }() tx := createBurnWithProofs(t) - ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithProofs() failed") correctDiff := txDiff{ @@ -474,7 +474,7 @@ func TestCreateDiffExchangeWithSig(t *testing.T) { }() tx := createExchangeWithSig(t) - ch, err := to.td.createDiffExchange(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") price := tx.Price * tx.Amount / priceConstant @@ -534,7 +534,7 @@ func TestCreateDiffExchangeWithProofs(t *testing.T) { }() tx := createExchangeWithProofs(t) - ch, err := to.td.createDiffExchange(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") price := tx.Price * tx.Amount / priceConstant @@ -571,39 +571,39 @@ func createExchangeWithProofsWithOrdersV3(t *testing.T) *proto.ExchangeWithProof } func createExchangeWithProofsWithOrdersV4(t *testing.T, price, amount uint64) *proto.ExchangeWithProofs { - bo := proto.NewUnsignedOrderV4(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, uint64(price), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + bo := proto.NewUnsignedOrderV4(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, price, amount, 0, 0, 3, *testGlobal.asset2.asset) err := bo.Sign(proto.MainNetScheme, testGlobal.senderInfo.sk) require.NoError(t, err, "bo.Sign() failed") - so := proto.NewUnsignedOrderV4(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, uint64(price), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + so := proto.NewUnsignedOrderV4(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, price, amount, 0, 0, 3, *testGlobal.asset2.asset) err = so.Sign(proto.MainNetScheme, testGlobal.recipientInfo.sk) require.NoError(t, err, "so.Sign() failed") - tx := proto.NewUnsignedExchangeWithProofs(3, bo, so, uint64(price), bo.Amount, 1, 2, defaultFee, defaultTimestamp) + tx := proto.NewUnsignedExchangeWithProofs(3, bo, so, price, bo.Amount, 1, 2, defaultFee, defaultTimestamp) err = tx.Sign(proto.MainNetScheme, testGlobal.matcherInfo.sk) require.NoError(t, err, "tx.Sign() failed") return tx } func createExchangeV3WithProofsWithMixedOrders(t *testing.T, price1, price2, amount uint64) *proto.ExchangeWithProofs { - bo := proto.NewUnsignedOrderV3(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, uint64(price1), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + bo := proto.NewUnsignedOrderV3(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, price1, amount, 0, 0, 3, *testGlobal.asset2.asset) err := bo.Sign(proto.MainNetScheme, testGlobal.senderInfo.sk) require.NoError(t, err, "bo.Sign() failed") - so := proto.NewUnsignedOrderV4(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, uint64(price2), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + so := proto.NewUnsignedOrderV4(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, price2, amount, 0, 0, 3, *testGlobal.asset2.asset) err = so.Sign(proto.MainNetScheme, testGlobal.recipientInfo.sk) require.NoError(t, err, "so.Sign() failed") - tx := proto.NewUnsignedExchangeWithProofs(3, bo, so, uint64(price2), bo.Amount, 1, 2, defaultFee, defaultTimestamp) + tx := proto.NewUnsignedExchangeWithProofs(3, bo, so, price2, bo.Amount, 1, 2, defaultFee, defaultTimestamp) err = tx.Sign(proto.MainNetScheme, testGlobal.matcherInfo.sk) require.NoError(t, err, "tx.Sign() failed") return tx } func createExchangeV2WithProofsWithOrdersV3(t *testing.T, price, amount uint64) *proto.ExchangeWithProofs { - bo := proto.NewUnsignedOrderV3(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, uint64(price), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + bo := proto.NewUnsignedOrderV3(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, price, amount, 0, 0, 3, *testGlobal.asset2.asset) err := bo.Sign(proto.MainNetScheme, testGlobal.senderInfo.sk) require.NoError(t, err, "bo.Sign() failed") - so := proto.NewUnsignedOrderV3(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, uint64(price), uint64(amount), 0, 0, 3, *testGlobal.asset2.asset) + so := proto.NewUnsignedOrderV3(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, price, amount, 0, 0, 3, *testGlobal.asset2.asset) err = so.Sign(proto.MainNetScheme, testGlobal.recipientInfo.sk) require.NoError(t, err, "so.Sign() failed") - tx := proto.NewUnsignedExchangeWithProofs(2, bo, so, uint64(price), bo.Amount, 1, 2, defaultFee, defaultTimestamp) + tx := proto.NewUnsignedExchangeWithProofs(2, bo, so, price, bo.Amount, 1, 2, defaultFee, defaultTimestamp) err = tx.Sign(proto.MainNetScheme, testGlobal.matcherInfo.sk) require.NoError(t, err, "tx.Sign() failed") return tx @@ -619,7 +619,7 @@ func TestCreateDiffExchangeWithProofsWithOrdersV3(t *testing.T) { }() tx := createExchangeWithProofsWithOrdersV3(t) - ch, err := to.td.createDiffExchange(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") price := tx.Price * tx.Amount / priceConstant @@ -702,15 +702,15 @@ func TestCreateDiffExchangeV3WithProofsWithOrdersV4(t *testing.T) { price := uint64(10 * priceConstant) tx3o4 := createExchangeWithProofsWithOrdersV4(t, 10*priceConstant, amount) - ch1, err := to.td.createDiffExchange(tx3o4, defaultDifferInfo(t)) + ch1, err := to.td.createDiffExchange(tx3o4, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") tx2o3 := createExchangeV2WithProofsWithOrdersV3(t, 10*priceConstant*priceConstant, amount) - ch2, err := to.td.createDiffExchange(tx2o3, defaultDifferInfo(t)) + ch2, err := to.td.createDiffExchange(tx2o3, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") tx3mo := createExchangeV3WithProofsWithMixedOrders(t, 10*priceConstant*priceConstant, 10*priceConstant, amount) - ch3, err := to.td.createDiffExchange(tx3mo, defaultDifferInfo(t)) + ch3, err := to.td.createDiffExchange(tx3mo, defaultDifferInfo()) assert.NoError(t, err, "createDiffExchange() failed") priceAmount := price * amount @@ -757,7 +757,7 @@ func TestCreateDiffLeaseWithSig(t *testing.T) { }() tx := createLeaseWithSig(t) - ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffLeaseWithSig() failed") correctDiff := txDiff{ @@ -791,7 +791,7 @@ func TestCreateDiffLeaseWithProofs(t *testing.T) { }() tx := createLeaseWithProofs(t) - ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffLeaseWithProofs() failed") correctDiff := txDiff{ @@ -831,7 +831,7 @@ func TestCreateDiffLeaseCancelWithSig(t *testing.T) { assert.NoError(t, err, "performLeaseWithSig failed") tx := createLeaseCancelWithSig(t, *leaseTx.ID) - ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffLeaseCancelWithSig() failed") correctDiff := txDiff{ @@ -871,7 +871,7 @@ func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { assert.NoError(t, err, "performLeaseWithProofs failed") tx := createLeaseCancelWithProofs(t, *leaseTx.ID) - ch, err := to.td.createDiffLeaseCancelWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffLeaseCancelWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffLeaseCancelWithProofs() failed") correctDiff := txDiff{ @@ -909,7 +909,7 @@ func TestCreateDiffCreateAliasWithSig(t *testing.T) { }() tx := createCreateAliasWithSig(t) - ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffCreateAliasWithSig failed") correctDiff := txDiff{ @@ -945,7 +945,7 @@ func TestCreateDiffCreateAliasWithProofs(t *testing.T) { }() tx := createCreateAliasWithProofs(t) - ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffCreateAliasWithProofs failed") correctDiff := txDiff{ @@ -990,7 +990,7 @@ func TestCreateDiffMassTransferWithProofs(t *testing.T) { entriesNum := 66 entries := generateMassTransferEntries(t, entriesNum) tx := createMassTransferWithProofs(t, entries) - ch, err := to.td.createDiffMassTransferWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffMassTransferWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffMassTransferWithProofs failed") correctDiff := txDiff{ @@ -1035,7 +1035,7 @@ func TestCreateDiffDataWithProofs(t *testing.T) { }() tx := createDataWithProofs(t, 1) - ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffDataWithProofs failed") correctDiff := txDiff{ @@ -1067,7 +1067,7 @@ func TestCreateDiffSponsorshipWithProofs(t *testing.T) { }() tx := createSponsorshipWithProofs(t, 1000) - ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffSponsorshipWithProofs failed") correctDiff := txDiff{ @@ -1101,7 +1101,7 @@ func TestCreateDiffSetScriptWithProofs(t *testing.T) { }() tx := createSetScriptWithProofs(t) - ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffSetScriptWithProofs failed") correctDiff := txDiff{ @@ -1135,7 +1135,7 @@ func TestCreateDiffSetAssetScriptWithProofs(t *testing.T) { }() tx := createSetAssetScriptWithProofs(t) - ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffSetAssetScriptWithProofs failed") correctDiff := txDiff{ @@ -1193,11 +1193,11 @@ func TestCreateDiffInvokeScriptWithProofs(t *testing.T) { to.stor.createAsset(t, assetId) to.stor.activateSponsorship(t) - _, err := to.td.createDiffInvokeScriptWithProofs(tx, defaultDifferInfo(t)) + _, err := to.td.createDiffInvokeScriptWithProofs(tx, defaultDifferInfo()) assert.Error(t, err, "createDiffInvokeScriptWithProofs() did not fail with unsponsored asset") err = to.stor.entities.sponsoredAssets.sponsorAsset(assetId, 10, blockID0) assert.NoError(t, err, "sponsorAsset() failed") - ch, err := to.td.createDiffInvokeScriptWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffInvokeScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffInvokeScriptWithProofs() failed with valid sponsored asset") feeInWaves, err := to.stor.entities.sponsoredAssets.sponsoredAssetToWaves(assetId, tx.Fee) @@ -1243,7 +1243,7 @@ func TestCreateDiffUpdateAssetInfoWithProofs(t *testing.T) { }() tx := createUpdateAssetInfoWithProofs(t) - ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo(t)) + ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffUpdateAssetInfoWithProofs() failed") correctDiff := txDiff{ From 4c1d44e9f7ccd4cd5eff06c7c4b19289b43678a9 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 27 May 2021 17:48:17 +0300 Subject: [PATCH 41/52] fixed verifier (#476) * fixed verifier * Fixed style * Verifier complexity check moved up by call stack. Erasure of asset's script extra fee added to invoke fee validation. Co-authored-by: Alexey Kiselev --- pkg/state/fee_validation.go | 5 +---- pkg/state/invoke_applier.go | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index be6f4f122..280990a2b 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -2,6 +2,7 @@ package state import ( "fmt" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -189,14 +190,10 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams, isRideV5Acti // check complexity of script for free verifier if complexity <= 200 complexity := 0 if accountScripted && isRideV5Activated { - treeEstimation, err := params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, estimatorVersion, !params.initialisation) if err != nil { return nil, errors.Errorf("failed to get complexity by addr from store, %v", err) } - if treeEstimation == nil { - return nil, errors.Errorf("failed to get complexity by addr from store: estimation tree is empty") - } complexity = treeEstimation.Verifier } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 130e9d350..d98a20b35 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -676,10 +676,25 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), actions: scriptActions, changes: failedChanges} return ia.handleInvocationResult(tx, info, res) } - actionScriptRuns := ia.countActionScriptRuns(scriptActions, info.initialisation) - scriptRuns := uint64(len(paymentSmartAssets)) + actionScriptRuns + var scriptRuns uint64 = 0 + // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. + if info.rideV5Activated { + actionScriptRuns := ia.countActionScriptRuns(scriptActions, info.initialisation) + scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns + } if info.senderScripted { - scriptRuns += 1 + // Since activation of RideV5 (16) feature we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit + if info.rideV5Activated { + treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr(*scriptAddr, info.checkerInfo.estimatorVersion(), !info.initialisation) + if err != nil { + return nil, errors.Wrap(err, "invoke failed to get verifier complexity") + } + if treeEstimation.Verifier > FreeVerifierComplexity { + scriptRuns++ + } + } else { + scriptRuns++ + } } var res *invocationResult code, changes, err := ia.fallibleValidation(tx, &addlInvokeInfo{ From 82a4df8102d1f19cd463a8a15b1252e3124b4985 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 27 May 2021 18:40:24 +0300 Subject: [PATCH 42/52] Fix evaluation complexity 2 (#477) * changed complexity of callable script * Added implementation of chain complexity calculation * Added mock function for checking complexity in tests * Fixed calculation of complexity * WIP: Calculate evaluation complexity properly * Evaluator's call stack doesn't push a calculated value on top but updates it at the original position. Evaluation complexity calculation fixed. * Check logic simplified. * Verifier complexity limits separated by script version. * Correct script limits calculation. Co-authored-by: esuwu --- pkg/ride/constraints.go | 3 + pkg/ride/environment.go | 21 +++++-- pkg/ride/functions.go | 24 +++++++ pkg/ride/functions_proto.go | 16 +++-- pkg/ride/generate/main.go | 59 ++++++++++++----- pkg/ride/program.go | 6 +- pkg/ride/result.go | 33 ++++++---- pkg/ride/selectors.go | 15 +++++ pkg/ride/tree_evaluation.go | 11 +++- pkg/ride/tree_evaluation_test.go | 50 +++++++++++++++ pkg/ride/tree_evaluator.go | 105 ++++++++++++++++++------------- pkg/ride/vm.go | 2 +- pkg/state/constraints.go | 7 +++ pkg/state/invoke_applier.go | 4 +- pkg/state/script_caller.go | 6 +- pkg/state/state.go | 2 +- pkg/state/transaction_checker.go | 52 ++++++++++----- 17 files changed, 309 insertions(+), 107 deletions(-) create mode 100644 pkg/ride/constraints.go diff --git a/pkg/ride/constraints.go b/pkg/ride/constraints.go new file mode 100644 index 000000000..813ee9541 --- /dev/null +++ b/pkg/ride/constraints.go @@ -0,0 +1,3 @@ +package ride + +const MaxChainInvokeComplexity = 26000 diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index f39bda900..96bdba3e2 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -11,12 +11,13 @@ import ( ) type WrappedState struct { - diff diffState - cle rideAddress - scheme proto.Scheme - invokeCount uint64 - act []proto.ScriptAction - blackList []proto.Address + diff diffState + cle rideAddress + scheme proto.Scheme + invokeCount uint64 + act []proto.ScriptAction + blackList []proto.Address + totalComplexity int } func newWrappedState(env *EvaluationEnvironment) *WrappedState { @@ -43,6 +44,13 @@ func (ws *WrappedState) appendActions(actions []proto.ScriptAction) { ws.act = append(ws.act, actions...) } +func (ws *WrappedState) checkTotalComplexity() (int, bool) { + if ws.totalComplexity > MaxChainInvokeComplexity { + return ws.totalComplexity, false + } + return ws.totalComplexity, true +} + func (ws *WrappedState) callee() proto.Address { return proto.Address(ws.cle) } @@ -1038,6 +1046,7 @@ func (ws *WrappedState) ApplyToState(actions []proto.ScriptAction, env Environme default: } } + return actions, nil } diff --git a/pkg/ride/functions.go b/pkg/ride/functions.go index 49d25dcf0..ffabd8d2a 100644 --- a/pkg/ride/functions.go +++ b/pkg/ride/functions.go @@ -9,8 +9,11 @@ func init() { } var _catalogue_V2 = [...]int{11, 26, 9, 1, 1, 1, 100, 100, 100, 1, 1, 1, 1, 10, 10, 10, 10, 1, 100, 100, 100, 100, 1, 100, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 100, 10, 10, 10, 10, 10, 10, 10, 1, 1, 2, 2, 9, 82, 124, 19, 19, 13, 30, 30, 30, 30, 35, 19, 19, 2, 109} + var CatalogueV2 = map[string]int{"!": 11, "!=": 26, "-": 9, "0": 1, "1": 1, "100": 1, "1000": 100, "1001": 100, "1003": 100, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 100, "1051": 100, "1052": 100, "1053": 100, "106": 1, "1060": 100, "107": 1, "2": 1, "200": 1, "201": 1, "202": 1, "203": 10, "300": 10, "303": 1, "304": 1, "305": 1, "400": 2, "401": 2, "410": 1, "411": 1, "412": 1, "420": 1, "421": 1, "500": 100, "501": 10, "502": 10, "503": 10, "600": 10, "601": 10, "602": 10, "603": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "DataEntry": 2, "DataTransaction": 9, "addressFromPublicKey": 82, "addressFromString": 124, "dropRight": 19, "dropRightBytes": 19, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 35, "takeRight": 19, "takeRightBytes": 19, "throw": 2, "wavesBalance": 109} +var FreeFunctionsV2 = map[string]struct{}{"Address": {}, "Alias": {}, "AssetPair": {}, "DataEntry": {}, "DataTransaction": {}} + const _names_V2 = "!!=-011001000100110031011021031041040104110421043105105010511052105310610601072200201202203300303304305400401410411412420421500501502503600601602603AddressAliasAssetPairDataEntryDataTransactionaddressFromPublicKeyaddressFromStringdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedtakeRighttakeRightBytesthrowwavesBalance" var _index_V2 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 24, 27, 30, 33, 37, 41, 45, 49, 52, 56, 60, 64, 68, 71, 75, 78, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 155, 160, 169, 178, 193, 213, 230, 239, 253, 260, 269, 279, 289, 298, 307, 316, 330, 335, 347} @@ -21,12 +24,14 @@ func functionNameV2(i int) string { } return _names_V2[_index_V2[i]:_index_V2[i+1]] } + func functionV2(id int) rideFunction { if id < 0 || id > 67 { return nil } return _functions_V2[id] } + func checkFunctionV2(name string) (uint16, bool) { for i := 0; i <= 67; i++ { if _names_V2[_index_V2[i]:_index_V2[i+1]] == name { @@ -35,6 +40,7 @@ func checkFunctionV2(name string) (uint16, bool) { } return 0, false } + func costV2(id int) int { if id < 0 || id > 67 { return -1 @@ -49,8 +55,11 @@ func init() { } var _catalogue_V3 = [...]int{1, 1, 1, 1, 1, 1, 100, 100, 100, 100, 100, 1, 1, 1, 1, 10, 10, 10, 10, 1, 100, 100, 100, 100, 1, 100, 10, 1, 100, 100, 2, 20, 10, 10, 20, 20, 100, 20, 20, 20, 1, 1, 1, 1, 10, 10, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 100, 10, 10, 10, 300, 10, 10, 10, 10, 10, 10, 30, 10, 10, 10, 10, 100, 100, 100, 100, 124, 10, 10, 10, 10, 1, 1, 2, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 82, 124, 19, 19, 13, 30, 30, 30, 30, 1, 20, 19, 19, 1, 13, 13, 109} + var CatalogueV3 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 100, "1003": 100, "1004": 100, "1005": 100, "1006": 100, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 100, "1051": 100, "1052": 100, "1053": 100, "106": 1, "1060": 100, "1061": 10, "107": 1, "108": 100, "109": 100, "1100": 2, "1200": 20, "1201": 10, "1202": 10, "1203": 20, "1204": 20, "1205": 100, "1206": 20, "1207": 20, "1208": 20, "2": 1, "200": 1, "201": 1, "202": 1, "203": 10, "300": 10, "303": 1, "304": 1, "305": 1, "400": 2, "401": 2, "410": 1, "411": 1, "412": 1, "420": 1, "421": 1, "500": 100, "501": 10, "502": 10, "503": 10, "504": 300, "600": 10, "601": 10, "602": 10, "603": 10, "604": 10, "605": 10, "700": 30, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 100, "@extrNative(1051)": 100, "@extrNative(1052)": 100, "@extrNative(1053)": 100, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "Buy": 0, "Ceiling": 0, "DataEntry": 2, "DataTransaction": 9, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "Md5": 0, "NoAlg": 0, "ScriptResult": 2, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "TransferSet": 1, "Unit": 0, "Up": 0, "WriteSet": 1, "addressFromPublicKey": 82, "addressFromString": 124, "dropRight": 19, "dropRightBytes": 19, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 20, "takeRight": 19, "takeRightBytes": 19, "throw": 1, "value": 13, "valueOrErrorMessage": 13, "wavesBalance": 109} +var FreeFunctionsV3 = map[string]struct{}{"Address": {}, "Alias": {}, "AssetPair": {}, "DataEntry": {}, "DataTransaction": {}, "WriteSet": {}, "TransferSet": {}, "ScriptTransfer": {}, "ScriptResult": {}} + const _names_V3 = "!!=-0110010011003100410051006101102103104104010411042104310510501051105210531061060106110710810911001200120112021203120412051206120712082200201202203300303304305400401410411412420421500501502503504600601602603604605700@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairBuyCeilingDataEntryDataTransactionDownFloorHalfDownHalfEvenHalfUpMd5NoAlgScriptResultScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512TransferSetUnitUpWriteSetaddressFromPublicKeyaddressFromStringdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrErrorMessagewavesBalance" var _index_V3 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 32, 35, 38, 41, 45, 49, 53, 57, 60, 64, 68, 72, 76, 79, 83, 87, 90, 93, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 206, 209, 212, 215, 218, 235, 252, 269, 286, 303, 320, 337, 354, 382, 402, 423, 444, 464, 471, 476, 485, 488, 495, 504, 519, 523, 528, 536, 544, 550, 553, 558, 570, 584, 588, 592, 598, 604, 611, 618, 625, 632, 638, 644, 655, 659, 661, 669, 689, 706, 715, 729, 736, 745, 755, 765, 774, 783, 796, 805, 819, 824, 829, 848, 860} @@ -61,12 +70,14 @@ func functionNameV3(i int) string { } return _names_V3[_index_V3[i]:_index_V3[i+1]] } + func functionV3(id int) rideFunction { if id < 0 || id > 127 { return nil } return _functions_V3[id] } + func checkFunctionV3(name string) (uint16, bool) { for i := 0; i <= 127; i++ { if _names_V3[_index_V3[i]:_index_V3[i+1]] == name { @@ -75,6 +86,7 @@ func checkFunctionV3(name string) (uint16, bool) { } return 0, false } + func costV3(id int) int { if id < 0 || id > 127 { return -1 @@ -89,8 +101,11 @@ func init() { } var _catalogue_V4 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 1, 1, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 1, 5, 10, 1, 1, 5, 100, 10, 100, 1, 1, 1, 1, 4, 5, 5, 7, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 2, 2, 20, 3, 3, 1, 8, 1, 1, 1, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} + var CatalogueV4 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "101": 1, "102": 1, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 1, "1070": 5, "108": 100, "1080": 10, "109": 100, "1090": 1, "1091": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "410": 1, "411": 8, "412": 1, "420": 1, "421": 1, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var FreeFunctionsV4 = map[string]struct{}{"Address": {}, "Alias": {}, "AssetPair": {}, "DataEntry": {}, "DataTransaction": {}, "WriteSet": {}, "TransferSet": {}, "ScriptTransfer": {}, "ScriptResult": {}, "IntegerEntry": {}, "BooleanEntry": {}, "BinaryEntry": {}, "StringEntry": {}, "DeleteEntry": {}, "Reissue": {}, "Burn": {}, "SponsorFee": {}, "AttachedPayment": {}} + const _names_V4 = "!!=-0110010011004100510061007100810110210310410401041104210431051050105110521053106106010611062107107010810801091090109111001101110211031104110512001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305400401405406407410411412420421500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" var _index_V4 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 36, 39, 42, 45, 49, 53, 57, 61, 64, 68, 72, 76, 80, 83, 87, 91, 95, 98, 102, 105, 109, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 269, 272, 275, 278, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 488, 491, 494, 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, 527, 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 589, 606, 623, 640, 657, 674, 691, 708, 725, 753, 773, 794, 815, 835, 842, 847, 856, 871, 882, 894, 898, 901, 908, 923, 934, 938, 943, 951, 959, 965, 977, 980, 985, 992, 1006, 1010, 1014, 1020, 1026, 1033, 1040, 1047, 1054, 1060, 1066, 1076, 1087, 1091, 1093, 1113, 1130, 1138, 1153, 1162, 1176, 1183, 1192, 1202, 1212, 1221, 1230, 1243, 1252, 1266, 1271, 1276, 1287, 1306} @@ -101,12 +116,14 @@ func functionNameV4(i int) string { } return _names_V4[_index_V4[i]:_index_V4[i+1]] } + func functionV4(id int) rideFunction { if id < 0 || id > 225 { return nil } return _functions_V4[id] } + func checkFunctionV4(name string) (uint16, bool) { for i := 0; i <= 225; i++ { if _names_V4[_index_V4[i]:_index_V4[i+1]] == name { @@ -115,6 +132,7 @@ func checkFunctionV4(name string) (uint16, bool) { } return 0, false } + func costV4(id int) int { if id < 0 || id > 225 { return -1 @@ -129,8 +147,11 @@ func init() { } var _catalogue_V5 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 10, 1, 14, 5, 100, 10, 1, 100, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 200, 200, 7, 1, 1, 3, 3, 75, 2, 3, 3, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 47, 57, 70, 102, 172, 500, 550, 625, 750, 10, 25, 50, 100, 10, 25, 50, 100, 10, 25, 50, 100, 20, 20, 20, 1, 1, 8, 8, 64, 64, 64, 128, 128, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 65, 65, 65, 160, 200, 200, 200, 200, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 2, 2, 2, 2, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 63, 124, 3, 5, 20, 6, 13, 17, 30, 30, 30, 30, 1, 2, 20, 6, 1, 2, 2, 2} + var CatalogueV5 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 10, "1062": 1, "107": 14, "1070": 5, "108": 100, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "118": 200, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 75, "1206": 2, "1207": 3, "1208": 3, "1209": 30, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 47, "2501": 57, "2502": 70, "2503": 102, "2504": 172, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 10, "2701": 25, "2702": 50, "2703": 100, "2800": 10, "2801": 25, "2802": 50, "2803": 100, "2900": 10, "2901": 25, "2902": 50, "2903": 100, "300": 20, "303": 20, "304": 20, "305": 1, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 128, "317": 128, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 65, "423": 65, "424": 65, "425": 160, "500": 200, "501": 200, "502": 200, "503": 200, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "AssetPair": 2, "AttachedPayment": 2, "BinaryEntry": 2, "BooleanEntry": 2, "Burn": 2, "Buy": 0, "Ceiling": 0, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "Floor": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "LeaseCancel": 1, "Md5": 0, "NoAlg": 0, "Reissue": 3, "ScriptTransfer": 3, "Sell": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "StringEntry": 2, "Unit": 0, "Up": 0, "addressFromPublicKey": 63, "addressFromString": 124, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "extract": 13, "fraction": 17, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var FreeFunctionsV5 = map[string]struct{}{"Address": {}, "Alias": {}, "AssetPair": {}, "DataEntry": {}, "DataTransaction": {}, "WriteSet": {}, "TransferSet": {}, "ScriptTransfer": {}, "ScriptResult": {}, "IntegerEntry": {}, "BooleanEntry": {}, "BinaryEntry": {}, "StringEntry": {}, "DeleteEntry": {}, "Reissue": {}, "Burn": {}, "SponsorFee": {}, "AttachedPayment": {}, "LeaseCancel": {}} + const _names_V5 = "!!=-011001001100410051006100710081009101102102010211031041040104110421043105105010511052105310541055105610571058106106010611062107107010810801081109109010911092109311001101110211031104110511811912001201120212031204120512061207120812091300130113021303130413051306130713081309131013111312131313141315131613171318131913202200201202203240024012402240324042405240624072408240924102411241224132414245024512452245324542455245624572458245924602461246224632464250025012502250325042600260126022603270027012702270328002801280228032900290129022903300303304305310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetPairAttachedPaymentBinaryEntryBooleanEntryBurnBuyCeilingDataTransactionDeleteEntryDownFloorHalfDownHalfEvenHalfUpIntegerEntryLeaseCancelMd5NoAlgReissueScriptTransferSellSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeStringEntryUnitUpaddressFromPublicKeyaddressFromStringcontainscontainsElementdropRightdropRightBytesextractfractiongetBinarygetBooleangetIntegergetStringisDefinedparseIntValuetakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" var _index_V5 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 130, 134, 137, 141, 145, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 191, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 318, 319, 322, 325, 328, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 423, 427, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 519, 523, 527, 531, 535, 538, 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, 583, 586, 589, 592, 595, 598, 601, 604, 607, 610, 613, 616, 619, 622, 625, 628, 631, 634, 637, 640, 643, 646, 649, 652, 655, 658, 661, 664, 667, 670, 673, 676, 679, 682, 685, 702, 719, 736, 753, 770, 787, 804, 821, 838, 855, 872, 889, 906, 934, 954, 975, 996, 1016, 1023, 1028, 1037, 1052, 1063, 1075, 1079, 1082, 1089, 1104, 1115, 1119, 1124, 1132, 1140, 1146, 1158, 1169, 1172, 1177, 1184, 1198, 1202, 1206, 1212, 1218, 1225, 1232, 1239, 1246, 1252, 1258, 1268, 1279, 1283, 1285, 1305, 1322, 1330, 1345, 1354, 1368, 1375, 1383, 1392, 1402, 1412, 1421, 1430, 1443, 1452, 1466, 1471, 1476, 1487, 1506} @@ -141,12 +162,14 @@ func functionNameV5(i int) string { } return _names_V5[_index_V5[i]:_index_V5[i+1]] } + func functionV5(id int) rideFunction { if id < 0 || id > 265 { return nil } return _functions_V5[id] } + func checkFunctionV5(name string) (uint16, bool) { for i := 0; i <= 265; i++ { if _names_V5[_index_V5[i]:_index_V5[i+1]] == name { @@ -155,6 +178,7 @@ func checkFunctionV5(name string) (uint16, bool) { } return 0, false } + func costV5(id int) int { if id < 0 || id > 265 { return -1 diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 93cfeee42..b8d37aaed 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -156,7 +156,7 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { res, err := invokeFunctionFromDApp(env, recipient, fnName, listArg) if err != nil { - return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + return nil, errors.Wrapf(err, "failed to get Result from invokeFunctionFromDApp") } if res.Result() { @@ -172,10 +172,12 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { env.setNewDAppAddress(proto.Address(callerAddress)) env.setInvocation(oldInvocationParam) - if res.UserResult() == nil { + ws.totalComplexity += res.Complexity() + + if res.userResult() == nil { return rideUnit{}, nil } - return res.UserResult(), nil + return res.userResult(), nil } return rideThrow("result of reentrantInvoke function is false"), nil @@ -317,7 +319,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { ws.blackList = ws.blackList[:len(ws.blackList)-1] // pop if err != nil { - return nil, errors.Wrapf(err, "failed to get RideResult from invokeFunctionFromDApp") + return nil, errors.Wrapf(err, "failed to get Result from invokeFunctionFromDApp") } if res.Result() { @@ -333,10 +335,12 @@ func invoke(env Environment, args ...rideType) (rideType, error) { env.setNewDAppAddress(proto.Address(callerAddress)) env.setInvocation(oldInvocationParam) - if res.UserResult() == nil { + ws.totalComplexity += res.Complexity() + + if res.userResult() == nil { return rideUnit{}, nil } - return res.UserResult(), nil + return res.userResult(), nil } return rideThrow("result of invoke function is false"), nil diff --git a/pkg/ride/generate/main.go b/pkg/ride/generate/main.go index c4cebebd6..a085f2a69 100644 --- a/pkg/ride/generate/main.go +++ b/pkg/ride/generate/main.go @@ -76,8 +76,8 @@ func functionsV2() map[string]string { m["wavesBalance"] = "wavesBalanceV3" m["Address"] = "address" m["Alias"] = "alias" - m["DataEntry"] = "dataEntry" m["AssetPair"] = "assetPair" + m["DataEntry"] = "dataEntry" m["DataTransaction"] = "dataTransaction" return m } @@ -149,12 +149,16 @@ func catalogueV2() map[string]int { m["wavesBalance"] = 109 m["Address"] = 1 m["Alias"] = 1 + m["AssetPair"] = 2 m["DataEntry"] = 2 m["DataTransaction"] = 9 - m["AssetPair"] = 2 return m } +func freeConstructorsV2() []string { + return []string{"Address", "Alias", "AssetPair", "DataEntry", "DataTransaction"} +} + func functionsV3() map[string]string { m := functionsV2() m["108"] = "pow" @@ -279,6 +283,10 @@ func catalogueV3() map[string]int { return m } +func freeConstructorsV3() []string { + return append(freeConstructorsV2(), "WriteSet", "TransferSet", "ScriptTransfer", "ScriptResult") +} + func functionsV4() map[string]string { m := functionsV3() // Remove obsolete constructors @@ -465,6 +473,11 @@ func catalogueV4() map[string]int { return m } +func freeConstructorsV4() []string { + return append(freeConstructorsV3(), "IntegerEntry", "BooleanEntry", "BinaryEntry", "StringEntry", + "DeleteEntry", "Reissue", "Burn", "SponsorFee", "AttachedPayment") +} + func functionsV5() map[string]string { m := functionsV4() m["118"] = "powBigInt" @@ -558,6 +571,10 @@ func catalogueV5() map[string]int { return m } +func freeConstructorsV5() []string { + return append(freeConstructorsV4(), "LeaseCancel") +} + type constantDescription struct { typeName string constructor string @@ -702,7 +719,7 @@ func createConstructors(sb *strings.Builder, c map[string]constantDescription) { } } -func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c map[string]int) { +func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c map[string]int, n []string) { keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) @@ -720,7 +737,7 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c } } sb.WriteString("}\n") - sb.WriteString("}\n") + sb.WriteString("}\n\n") // Create list of costs sb.WriteString(fmt.Sprintf("var _catalogue_%s = [...]int{", ver)) @@ -730,8 +747,9 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c sb.WriteString(", ") } } - sb.WriteString("}\n") + sb.WriteString("}\n\n") + // Create map of function costs sb.WriteString(fmt.Sprintf("var Catalogue%s = map[string]int{", ver)) for i, k := range keys { sb.WriteString(fmt.Sprintf("\"%s\":%d", k, c[k])) @@ -739,7 +757,17 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c sb.WriteString(", ") } } - sb.WriteString("}\n") + sb.WriteString("}\n\n") + + // Create map for evaluation zero cost constructors + sb.WriteString(fmt.Sprintf("var FreeFunctions%s = map[string]struct{}{", ver)) + for i, k := range n { + sb.WriteString(fmt.Sprintf("\"%s\":{}", k)) + if i < len(m)-1 { + sb.WriteString(", ") + } + } + sb.WriteString("}\n\n") // Create string of concatenated names of functions sb.WriteString(fmt.Sprintf("const _names_%s = \"%s\"\n", ver, strings.Join(keys, ""))) @@ -755,28 +783,31 @@ func createFunctionsList(sb *strings.Builder, ver string, m map[string]string, c } } sb.WriteString("}\n\n") + sb.WriteString(fmt.Sprintf("func functionName%s(i int) string {\n", ver)) sb.WriteString(fmt.Sprintf("if i < 0 || i > %d {\n", len(keys)-1)) sb.WriteString("return \"\"\n") sb.WriteString("}\n") - sb.WriteString(fmt.Sprintf("return _names_%s[_index_%s[i]:_index_%s[i+1]]\n}\n", ver, ver, ver)) + sb.WriteString(fmt.Sprintf("return _names_%s[_index_%s[i]:_index_%s[i+1]]\n}\n\n", ver, ver, ver)) + sb.WriteString(fmt.Sprintf("func function%s(id int) rideFunction {\n", ver)) sb.WriteString(fmt.Sprintf("if id < 0 || id > %d {\n", len(keys)-1)) sb.WriteString("return nil\n") sb.WriteString("}\n") - sb.WriteString(fmt.Sprintf("return _functions_%s[id]\n}\n", ver)) + sb.WriteString(fmt.Sprintf("return _functions_%s[id]\n}\n\n", ver)) + sb.WriteString(fmt.Sprintf("func checkFunction%s(name string) (uint16, bool) {\n", ver)) sb.WriteString(fmt.Sprintf("for i := 0; i <= %d; i++ {\n", len(keys)-1)) sb.WriteString(fmt.Sprintf("if _names_%s[_index_%s[i]:_index_%s[i+1]] == name {\n", ver, ver, ver)) sb.WriteString("return uint16(i), true\n") sb.WriteString("}\n}\n") sb.WriteString("return 0, false\n") - sb.WriteString("}\n") + sb.WriteString("}\n\n") sb.WriteString(fmt.Sprintf("func cost%s(id int) int {\n", ver)) sb.WriteString(fmt.Sprintf("if id < 0 || id > %d {\n", len(keys)-1)) sb.WriteString("return -1\n") sb.WriteString("}\n") - sb.WriteString(fmt.Sprintf("return _catalogue_%s[id]\n}\n", ver)) + sb.WriteString(fmt.Sprintf("return _catalogue_%s[id]\n}\n\n", ver)) } func createTuples(sb *strings.Builder) { @@ -845,10 +876,10 @@ func main() { sb.WriteString("// Code generated by ride/generate/main.go. DO NOT EDIT.\n") sb.WriteString("\n") sb.WriteString("package ride\n") - createFunctionsList(sb, "V2", functionsV2(), catalogueV2()) - createFunctionsList(sb, "V3", functionsV3(), catalogueV3()) - createFunctionsList(sb, "V4", functionsV4(), catalogueV4()) - createFunctionsList(sb, "V5", functionsV5(), catalogueV5()) + createFunctionsList(sb, "V2", functionsV2(), catalogueV2(), freeConstructorsV2()) + createFunctionsList(sb, "V3", functionsV3(), catalogueV3(), freeConstructorsV3()) + createFunctionsList(sb, "V4", functionsV4(), catalogueV4(), freeConstructorsV4()) + createFunctionsList(sb, "V5", functionsV5(), catalogueV5(), freeConstructorsV5()) code := sb.String() b, err := format.Source([]byte(code)) if err != nil { diff --git a/pkg/ride/program.go b/pkg/ride/program.go index 9da036fa9..be563e7db 100644 --- a/pkg/ride/program.go +++ b/pkg/ride/program.go @@ -8,7 +8,7 @@ type callable struct { } type RideScript interface { - Run(env Environment) (RideResult, error) + Run(env Environment) (Result, error) code() []byte } @@ -19,7 +19,7 @@ type SimpleScript struct { Constants []rideType } -func (s *SimpleScript) Run(env Environment) (RideResult, error) { +func (s *SimpleScript) Run(env Environment) (Result, error) { fs, err := selectFunctions(s.LibVersion) if err != nil { return nil, errors.Wrap(err, "simple script execution failed") @@ -61,7 +61,7 @@ type DAppScript struct { EntryPoints map[string]callable } -func (s *DAppScript) Run(env Environment) (RideResult, error) { +func (s *DAppScript) Run(env Environment) (Result, error) { if _, ok := s.EntryPoints[""]; !ok { return nil, errors.Errorf("no verifier") } diff --git a/pkg/ride/result.go b/pkg/ride/result.go index a7a302ab6..8c977b3c8 100644 --- a/pkg/ride/result.go +++ b/pkg/ride/result.go @@ -2,24 +2,26 @@ package ride import "github.com/wavesplatform/gowaves/pkg/proto" -type RideResult interface { +type Result interface { Result() bool UserError() string - UserResult() rideType + userResult() rideType ScriptActions() []proto.ScriptAction + Complexity() int } type ScriptResult struct { - res bool - msg string - param rideType + res bool + msg string + param rideType + complexity int } func (r ScriptResult) Result() bool { return r.res } -func (r ScriptResult) UserResult() rideType { +func (r ScriptResult) userResult() rideType { return r.param } @@ -31,18 +33,23 @@ func (r ScriptResult) ScriptActions() []proto.ScriptAction { return nil } +func (r ScriptResult) Complexity() int { + return r.complexity +} + type DAppResult struct { - res bool // true - success, false - call failed, read msg - actions []proto.ScriptAction - msg string - param rideType + res bool // true - success, false - call failed, read msg + actions []proto.ScriptAction + msg string + param rideType + complexity int } func (r DAppResult) Result() bool { return r.res } -func (r DAppResult) UserResult() rideType { +func (r DAppResult) userResult() rideType { return r.param } @@ -53,3 +60,7 @@ func (r DAppResult) UserError() string { func (r DAppResult) ScriptActions() []proto.ScriptAction { return r.actions } + +func (r DAppResult) Complexity() int { + return r.complexity +} diff --git a/pkg/ride/selectors.go b/pkg/ride/selectors.go index 049846d8a..65a82dc48 100644 --- a/pkg/ride/selectors.go +++ b/pkg/ride/selectors.go @@ -32,6 +32,21 @@ func selectFunctionChecker(v int) (func(name string) (uint16, bool), error) { } } +func selectEvaluationCostsProvider(v int) (map[string]int, map[string]struct{}, error) { + switch v { + case 1, 2: + return CatalogueV2, FreeFunctionsV2, nil + case 3: + return CatalogueV3, FreeFunctionsV3, nil + case 4: + return CatalogueV4, FreeFunctionsV4, nil + case 5: + return CatalogueV5, FreeFunctionsV5, nil + default: + return nil, nil, errors.Errorf("unsupported library version '%d'", v) + } +} + func selectFunctionNameProvider(v int) (func(int) string, error) { switch v { case 1, 2: diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index 17040c321..57a9176b9 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -5,7 +5,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -func CallVerifier(env Environment, tree *Tree) (RideResult, error) { +func CallVerifier(env Environment, tree *Tree) (Result, error) { e, err := treeVerifierEvaluator(env, tree) if err != nil { return nil, errors.Wrap(err, "failed to call verifier") @@ -13,7 +13,7 @@ func CallVerifier(env Environment, tree *Tree) (RideResult, error) { return e.evaluate() } -func invokeFunctionFromDApp(env Environment, recipient proto.Recipient, fnName rideString, listArgs rideList) (RideResult, error) { +func invokeFunctionFromDApp(env Environment, recipient proto.Recipient, fnName rideString, listArgs rideList) (Result, error) { newScript, err := env.state().GetByteTree(recipient) if err != nil { return nil, errors.Wrap(err, "failed to get script by recipient") @@ -31,7 +31,7 @@ func invokeFunctionFromDApp(env Environment, recipient proto.Recipient, fnName r return e.evaluate() } -func CallFunction(env Environment, tree *Tree, name string, args proto.Arguments) (RideResult, error) { +func CallFunction(env Environment, tree *Tree, name string, args proto.Arguments) (Result, error) { if name == "" { name = "default" } @@ -54,6 +54,11 @@ func CallFunction(env Environment, tree *Tree, name string, args proto.Arguments return nil, errors.New("wrong state") } + complexity, ok := ws.checkTotalComplexity() + if !ok { + return nil, errors.Errorf("complexity of invocation chain %d exceeds maximum allowed complexity of %d", complexity, MaxChainInvokeComplexity) + } + if ws.act == nil { return rideResult, err } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index ea0f89c07..ae2cbf478 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -349,6 +349,56 @@ func TestFunctionsEvaluation(t *testing.T) { } } +func TestComplexity(t *testing.T) { + env := &MockRideEnvironment{ + transactionFunc: testTransferObject, + stateFunc: func() types.SmartState { + return &MockSmartState{NewestTransactionByIDFunc: func(_ []byte) (proto.Transaction, error) { + return testTransferWithProofs(), nil + }} + }, + schemeFunc: func() byte { + return 'T' + }, + } + for _, test := range []struct { + comment string + source string + complexity int + }{ + {`V4: let a = 1 + 10 + 100; let b = 1000 + a + 10000; let c = a + b + 100000; c + a == 111333`, "BAQAAAABYQkAAGQAAAACCQAAZAAAAAIAAAAAAAAAAAEAAAAAAAAAAAoAAAAAAAAAAGQEAAAAAWIJAABkAAAAAgkAAGQAAAACAAAAAAAAAAPoBQAAAAFhAAAAAAAAACcQBAAAAAFjCQAAZAAAAAIJAABkAAAAAgUAAAABYQUAAAABYgAAAAAAAAGGoAkAAAAAAAACCQAAZAAAAAIFAAAAAWMFAAAAAWEAAAAAAAABsuVAqr8m", 13}, + {`V4: func f(a: Int, b: Int) = {let c = a + b; let d = a - b; c * d - 1}; f(1, 2) == -4`, "BAoBAAAAAWYAAAACAAAAAWEAAAABYgQAAAABYwkAAGQAAAACBQAAAAFhBQAAAAFiBAAAAAFkCQAAZQAAAAIFAAAAAWEFAAAAAWIJAABlAAAAAgkAAGgAAAACBQAAAAFjBQAAAAFkAAAAAAAAAAABCQAAAAAAAAIJAQAAAAFmAAAAAgAAAAAAAAAAAQAAAAAAAAAAAgD//////////Pwcs2o=", 11}, + {`V4: let x = 1 + 1 + 1; let a = 1 + 1; func f(a: Int, b: Int) = a - b + x; let b = 4; func g(a: Int, b: Int) = a * b; let expected = (a - b + x) * (b - a + x); let actual = g(f(a, b), f(b, a)); actual == expected && actual == expected && x == 3 && a == 2 && b == 4`, "BAQAAAABeAkAAGQAAAACCQAAZAAAAAIAAAAAAAAAAAEAAAAAAAAAAAEAAAAAAAAAAAEEAAAAAWEJAABkAAAAAgAAAAAAAAAAAQAAAAAAAAAAAQoBAAAAAWYAAAACAAAAAWEAAAABYgkAAGQAAAACCQAAZQAAAAIFAAAAAWEFAAAAAWIFAAAAAXgEAAAAAWIAAAAAAAAAAAQKAQAAAAFnAAAAAgAAAAFhAAAAAWIJAABoAAAAAgUAAAABYQUAAAABYgQAAAAIZXhwZWN0ZWQJAABoAAAAAgkAAGQAAAACCQAAZQAAAAIFAAAAAWEFAAAAAWIFAAAAAXgJAABkAAAAAgkAAGUAAAACBQAAAAFiBQAAAAFhBQAAAAF4BAAAAAZhY3R1YWwJAQAAAAFnAAAAAgkBAAAAAWYAAAACBQAAAAFhBQAAAAFiCQEAAAABZgAAAAIFAAAAAWIFAAAAAWEDAwMDCQAAAAAAAAIFAAAABmFjdHVhbAUAAAAIZXhwZWN0ZWQJAAAAAAAAAgUAAAAGYWN0dWFsBQAAAAhleHBlY3RlZAcJAAAAAAAAAgUAAAABeAAAAAAAAAAAAwcJAAAAAAAAAgUAAAABYQAAAAAAAAAAAgcJAAAAAAAAAgUAAAABYgAAAAAAAAAABAd/cU2j", 47}, + {`V4: let x = 1 + 1 + 1 + 1 + 1; let y = x + 1; func f(x: Int) = x + 1; func g(x: Int) = x + 1 + 1; func h(x: Int) = x + 1 + 1 + 1; f(g(h(y))) == x + x + 2`, "BAQAAAABeAkAAGQAAAACCQAAZAAAAAIJAABkAAAAAgkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABAAAAAAAAAAABAAAAAAAAAAABAAAAAAAAAAABBAAAAAF5CQAAZAAAAAIFAAAAAXgAAAAAAAAAAAEKAQAAAAFmAAAAAQAAAAF4CQAAZAAAAAIFAAAAAXgAAAAAAAAAAAEKAQAAAAFnAAAAAQAAAAF4CQAAZAAAAAIJAABkAAAAAgUAAAABeAAAAAAAAAAAAQAAAAAAAAAAAQoBAAAAAWgAAAABAAAAAXgJAABkAAAAAgkAAGQAAAACCQAAZAAAAAIFAAAAAXgAAAAAAAAAAAEAAAAAAAAAAAEAAAAAAAAAAAEJAAAAAAAAAgkBAAAAAWYAAAABCQEAAAABZwAAAAEJAQAAAAFoAAAAAQUAAAABeQkAAGQAAAACCQAAZAAAAAIFAAAAAXgFAAAAAXgAAAAAAAAAAAJBsCoy", 21}, + {`V4: let x = 1 + 1 + 1; let y = {let z = 1; z}; y + x == 4`, "BAQAAAABeAkAAGQAAAACCQAAZAAAAAIAAAAAAAAAAAEAAAAAAAAAAAEAAAAAAAAAAAEEAAAAAXkEAAAAAXoAAAAAAAAAAAEFAAAAAXoJAAAAAAAAAgkAAGQAAAACBQAAAAF5BQAAAAF4AAAAAAAAAAAECwZAYA==", 7}, + {`V4: let address = Address(base58'aaaa'); address.bytes == base58'aaaa'`, "BAQAAAAHYWRkcmVzcwkBAAAAB0FkZHJlc3MAAAABAQAAAANj+GcJAAAAAAAAAggFAAAAB2FkZHJlc3MAAAAFYnl0ZXMBAAAAA2P4Z/7QEyM=", 3}, + {`V4: let x = (1, 2, 3); x._2 == 2`, "BAQAAAABeAkABRUAAAADAAAAAAAAAAABAAAAAAAAAAACAAAAAAAAAAADCQAAAAAAAAIIBQAAAAF4AAAAAl8yAAAAAAAAAAACXAdyJg==", 4}, + {`V4: let a = 1 + 1; let b = a; func g() = {let a1 = 2 + 2 + 2; let c = a1; c + b + a1}; g() + a == 16`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZwAAAAAEAAAAAmExCQAAZAAAAAIJAABkAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgQAAAABYwUAAAACYTEJAABkAAAAAgkAAGQAAAACBQAAAAFjBQAAAAFiBQAAAAJhMQkAAAAAAAACCQAAZAAAAAIJAQAAAAFnAAAAAAUAAAABYQAAAAAAAAAAEGbAh7s=", 13}, + {`V4: let a = 1 + 1; let b = a; func g() = {let c = 2 + 2; let d = c; d + b + c}; g() + a == 12`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZwAAAAAEAAAAAWMJAABkAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgQAAAABZAUAAAABYwkAAGQAAAACCQAAZAAAAAIFAAAAAWQFAAAAAWIFAAAAAWMJAAAAAAAAAgkAAGQAAAACCQEAAAABZwAAAAAFAAAAAWEAAAAAAAAAAAxjZ1Td", 12}, + {`V4: let a = 1 + 1; let b = a; func f() = {let c = 1 + 1; c + b}; a + f() == 6`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZgAAAAAEAAAAAWMJAABkAAAAAgAAAAAAAAAAAQAAAAAAAAAAAQkAAGQAAAACBQAAAAFjBQAAAAFiCQAAAAAAAAIJAABkAAAAAgUAAAABYQkBAAAAAWYAAAAAAAAAAAAAAAAGZR1Q1A==", 9}, + {`V4: let a = 1 + 1; let b = a; func f() = {let c = 1 + 1; c + b}; f() + a == 6`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZgAAAAAEAAAAAWMJAABkAAAAAgAAAAAAAAAAAQAAAAAAAAAAAQkAAGQAAAACBQAAAAFjBQAAAAFiCQAAAAAAAAIJAABkAAAAAgkBAAAAAWYAAAAABQAAAAFhAAAAAAAAAAAGeznbzA==", 9}, + {`V4: let a = 1 + 1; let b = a; a + b == 4`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCQAAAAAAAAIJAABkAAAAAgUAAAABYQUAAAABYgAAAAAAAAAABClbyII=", 6}, + {`V4: let a = 1 + 1; let b = a; b + a == 4`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCQAAAAAAAAIJAABkAAAAAgUAAAABYgUAAAABYQAAAAAAAAAABApVv5E=", 6}, + {`V4: let a = 1 + 1; let b = a; func f() = b; a + f() == 4`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZgAAAAAFAAAAAWIJAAAAAAAAAgkAAGQAAAACBQAAAAFhCQEAAAABZgAAAAAAAAAAAAAAAASZ9mVe", 6}, + {`V4: let a = 1 + 1; let b = a; func f() = b; f() + a == 4`, "BAQAAAABYQkAAGQAAAACAAAAAAAAAAABAAAAAAAAAAABBAAAAAFiBQAAAAFhCgEAAAABZgAAAAAFAAAAAWIJAAAAAAAAAgkAAGQAAAACCQEAAAABZgAAAAAFAAAAAWEAAAAAAAAAAASvoK6u", 6}, + } { + src, err := base64.StdEncoding.DecodeString(test.source) + require.NoError(t, err, test.comment) + + tree, err := Parse(src) + require.NoError(t, err, test.comment) + assert.NotNil(t, tree, test.comment) + + res, err := CallVerifier(env, tree) + require.NoError(t, err, test.comment) + require.NotNil(t, res, test.comment) + + r, ok := res.(ScriptResult) + assert.True(t, ok, test.comment) + assert.Equal(t, test.complexity, r.Complexity(), test.comment) + } +} + func TestOverlapping(t *testing.T) { /*{-# STDLIB_VERSION 3 #-} {-# CONTENT_TYPE EXPRESSION #-} diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index eb08ff0f9..7dbd27340 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -28,6 +28,8 @@ type evaluationScope struct { system map[string]rideFunction user []esFunction cl int + costs map[string]int + free map[string]struct{} } func (s *evaluationScope) declare(n Node) error { @@ -51,6 +53,12 @@ func (s *evaluationScope) pushValue(id string, v rideType) { s.cs[len(s.cs)-1] = append(s.cs[len(s.cs)-1], esValue{id: id, value: v}) } +func (s *evaluationScope) updateValue(frame, pos int, id string, v rideType) { + if ev := s.cs[frame][pos]; ev.id == id && ev.value == nil { + s.cs[frame][pos] = esValue{id: id, value: v} + } +} + func (s *evaluationScope) popValue() { s.cs[len(s.cs)-1] = s.cs[len(s.cs)-1][:len(s.cs[len(s.cs)-1])-1] } @@ -67,29 +75,29 @@ func (s *evaluationScope) constant(id string) (rideType, bool) { return nil, false } -func lookup(s []esValue, id string) (esValue, bool) { +func lookup(s []esValue, id string) (esValue, bool, int) { for i := len(s) - 1; i >= 0; i-- { if v := s[i]; v.id == id { - return v, true + return v, true, i } } - return esValue{}, false + return esValue{}, false, 0 } -func (s *evaluationScope) value(id string) (esValue, bool) { - if p := len(s.cs) - 1; p >= 0 { - v, ok := lookup(s.cs[p], id) +func (s *evaluationScope) value(id string) (esValue, bool, int, int) { + if i := len(s.cs) - 1; i >= 0 { + v, ok, p := lookup(s.cs[i], id) if ok { - return v, true + return v, true, i, p } } for i := s.cl - 1; i >= 0; i-- { - v, ok := lookup(s.cs[i], id) + v, ok, p := lookup(s.cs[i], id) if ok { - return v, true + return v, true, i, p } } - return esValue{}, false + return esValue{}, false, 0, 0 } func (s *evaluationScope) pushUserFunction(uf *FunctionDeclarationNode) { @@ -156,11 +164,17 @@ func newEvaluationScope(v int, env Environment, enableInvocation bool) (evaluati } fs[fn] = functionProvider(int(id)) } + costs, free, err := selectEvaluationCostsProvider(v) + if err != nil { + return evaluationScope{}, err + } return evaluationScope{ constants: cs, system: fs, cs: [][]esValue{make([]esValue, 0)}, env: env, + costs: costs, + free: free, }, nil } @@ -212,15 +226,14 @@ func selectFunctionNames(v int, enableInvocation bool) ([]string, error) { } type treeEvaluator struct { - dapp bool - //limit int - //cost int - f Node - s evaluationScope - env Environment + dapp bool + complexity int + f Node + s evaluationScope + env Environment } -func (e *treeEvaluator) evaluate() (RideResult, error) { +func (e *treeEvaluator) evaluate() (Result, error) { r, err := e.walk(e.f) if err != nil { return nil, err @@ -229,30 +242,29 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { switch res := r.(type) { case rideThrow: if e.dapp { - return DAppResult{res: false, msg: string(res)}, nil + return DAppResult{res: false, msg: string(res), complexity: e.complexity}, nil } - return ScriptResult{res: false, msg: string(res)}, nil + return ScriptResult{res: false, msg: string(res), complexity: e.complexity}, nil case rideBoolean: - return ScriptResult{res: bool(res)}, nil + return ScriptResult{res: bool(res), complexity: e.complexity}, nil case rideObject: a, err := objectToActions(e.env, res) if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - return DAppResult{res: true, actions: a, msg: ""}, nil + return DAppResult{res: true, actions: a, msg: "", complexity: e.complexity}, nil case rideList: - var act []proto.ScriptAction + var actions []proto.ScriptAction for _, item := range res { a, err := convertToAction(e.env, item) if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - act = append(act, a) + actions = append(actions, a) } - - return DAppResult{res: true, actions: act}, nil + return DAppResult{res: true, actions: actions, complexity: e.complexity}, nil case tuple2: - var act []proto.ScriptAction + var actions []proto.ScriptAction switch resAct := res.el1.(type) { case rideList: for _, item := range resAct { @@ -260,14 +272,12 @@ func (e *treeEvaluator) evaluate() (RideResult, error) { if err != nil { return nil, errors.Wrap(err, "failed to convert evaluation result") } - act = append(act, a) + actions = append(actions, a) } - default: return nil, errors.Errorf("unexpected result type '%T'", r) } - - return DAppResult{res: true, actions: act, msg: "", param: res.el2}, nil + return DAppResult{res: true, actions: actions, msg: "", param: res.el2, complexity: e.complexity}, nil default: return nil, errors.Errorf("unexpected result type '%T'", r) } @@ -303,6 +313,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { if !ok { return nil, errors.Errorf("not a boolean") } + e.complexity++ if cr { return e.walk(n.TrueExpression) } else { @@ -324,7 +335,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { case *ReferenceNode: id := n.Name - v, ok := e.s.value(id) + v, ok, f, p := e.s.value(id) if !ok { if v, ok := e.s.constant(id); ok { return v, nil @@ -342,9 +353,11 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { if isThrow(r) { return r, nil } - e.s.pushValue(id, r) + e.s.updateValue(f, p, id, r) + e.complexity++ return r, nil } + e.complexity++ return v.value, nil case *FunctionDeclarationNode: @@ -364,14 +377,21 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { return r, nil case *FunctionCallNode: - id := n.Name - f, ok := e.s.system[id] + name := n.Name + f, ok := e.s.system[name] if ok { // System function + cost, ok := e.s.costs[name] + if !ok { + return nil, errors.Errorf("failed to get cost of system function '%s'", name) + } + if _, ok := e.s.free[name]; ok { // + cost = 0 + } args := make([]rideType, len(n.Arguments)) for i, arg := range n.Arguments { a, err := e.walk(arg) // materialize argument if err != nil { - return nil, errors.Wrapf(err, "failed to materialize argument %d of system function '%s'", i+1, id) + return nil, errors.Wrapf(err, "failed to materialize argument %d of system function '%s'", i+1, name) } if isThrow(a) { return a, nil @@ -380,17 +400,17 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { } r, err := f(e.env, args...) if err != nil { - return nil, errors.Wrapf(err, "failed to call system function '%s'", id) + return nil, errors.Wrapf(err, "failed to call system function '%s'", name) } - + e.complexity += cost return r, nil } - uf, cl, err := e.s.userFunction(id) + uf, cl, err := e.s.userFunction(name) if err != nil { - return nil, errors.Wrapf(err, "failed to call function '%s'", id) + return nil, errors.Wrapf(err, "failed to call function '%s'", name) } if len(n.Arguments) != len(uf.Arguments) { - return nil, errors.Errorf("mismatched arguments number of user function '%s'", id) + return nil, errors.Errorf("mismatched arguments number of user function '%s'", name) } args := make([]esValue, len(n.Arguments)) @@ -398,7 +418,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { an := uf.Arguments[i] av, err := e.walk(arg) // materialize argument if err != nil { - return nil, errors.Wrapf(err, "failed to materialize argument '%s' of user function '%s", an, id) + return nil, errors.Wrapf(err, "failed to materialize argument '%s' of user function '%s", an, name) } if isThrow(av) { return av, nil @@ -414,7 +434,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { r, err := e.walk(uf.Body) if err != nil { - return nil, errors.Wrapf(err, "failed to evaluate function '%s' body", id) + return nil, errors.Wrapf(err, "failed to evaluate function '%s' body", name) } e.s.cs = e.s.cs[:len(e.s.cs)-1] e.s.cl = tmp @@ -426,6 +446,7 @@ func (e *treeEvaluator) walk(node Node) (rideType, error) { if err != nil { return nil, errors.Wrapf(err, "failed to evaluate an object to get property '%s' on it", name) } + e.complexity++ if isThrow(obj) { return obj, nil } diff --git a/pkg/ride/vm.go b/pkg/ride/vm.go index 70bfb81a6..d2c7e4c82 100644 --- a/pkg/ride/vm.go +++ b/pkg/ride/vm.go @@ -38,7 +38,7 @@ type vm struct { functionName func(int) string } -func (m *vm) run() (RideResult, error) { +func (m *vm) run() (Result, error) { if m.stack != nil { m.stack = m.stack[0:0] } diff --git a/pkg/state/constraints.go b/pkg/state/constraints.go index 1403845fe..ed3debde1 100644 --- a/pkg/state/constraints.go +++ b/pkg/state/constraints.go @@ -17,3 +17,10 @@ func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRideV5Acti } const FreeVerifierComplexity = 200 + +const MaxVerifierScriptComplexityReduced = 2000 +const MaxVerifierScriptComplexity = 4000 + +const MaxCallableScriptComplexityV12 = 2000 +const MaxCallableScriptComplexityV34 = 4000 +const MaxCallableScriptComplexityV5 = 10000 diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index d98a20b35..4073d5f29 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -238,7 +238,7 @@ func (ia *invokeApplier) countActionScriptRuns(actions []proto.ScriptAction, ini return scriptRuns } -func errorForSmartAsset(res ride.RideResult, asset crypto.Digest) error { +func errorForSmartAsset(res ride.Result, asset crypto.Digest) error { var text string if res.UserError() != "" { text = fmt.Sprintf("Transaction is not allowed by token-script id %s: throw from asset script.", asset.String()) @@ -796,7 +796,7 @@ func (ia *invokeApplier) checkFullFee(tx *proto.InvokeScriptWithProofs, scriptRu } func (ia *invokeApplier) validateActionSmartAsset(asset crypto.Digest, action proto.ScriptAction, callerPK crypto.PublicKey, - txID crypto.Digest, txTimestamp uint64, params *appendTxParams) (bool, ride.RideResult, error) { + txID crypto.Digest, txTimestamp uint64, params *appendTxParams) (bool, ride.Result, error) { isSmartAsset := ia.stor.scriptsStorage.newestIsSmartAsset(asset, !params.initialisation) if !isSmartAsset { return true, nil, nil diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index 3717f84d0..26d8a8897 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -133,7 +133,7 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, params *app return nil } -func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, assetID crypto.Digest, params *appendTxParams) (ride.Result, error) { tree, err := a.stor.scriptsStorage.newestScriptByAsset(assetID, !params.initialisation) if err != nil { return nil, err @@ -177,7 +177,7 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, as return r, nil } -func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTransfer, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTransfer, assetID crypto.Digest, params *appendTxParams) (ride.Result, error) { env, err := ride.NewEnvironment(a.settings.AddressSchemeCharacter, a.state) if err != nil { return nil, err @@ -186,7 +186,7 @@ func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTra return a.callAssetScriptCommon(env, assetID, params) } -func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Digest, params *appendTxParams) (ride.RideResult, error) { +func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Digest, params *appendTxParams) (ride.Result, error) { env, err := ride.NewEnvironment(a.settings.AddressSchemeCharacter, a.state) if err != nil { return nil, err diff --git a/pkg/state/state.go b/pkg/state/state.go index 3a92a4848..dcc39a1a8 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1499,7 +1499,7 @@ func (s *stateManager) NewestHitSourceAtHeight(height uint64) ([]byte, error) { if height < 1 || height > maxHeight { return nil, wrapErr(InvalidInputError, errors.Errorf("NewestHitSourceAtHeight: height %d out of valid range [1, %d]", height, maxHeight)) } - return s.stor.hitSources.newestHitSource(height, true) + return s.stor.hitSources.newestHitSource(height, false) } func (s *stateManager) CurrentScore() (*big.Int, error) { diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 04a04383e..58be3db49 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -87,27 +87,49 @@ func (tc *transactionChecker) scriptActivation(libVersion int, hasBlockV2 bool) return nil } -func (tc *transactionChecker) checkScriptComplexity(tree *ride.Tree, estimation ride.TreeEstimation) error { - var maxComplexity int +func (tc *transactionChecker) checkScriptComplexity(tree *ride.Tree, estimation ride.TreeEstimation, reducedVerifierComplexity bool) error { + /* + | Script Type | Max complexity before BlockV5 | Max complexity after BlockV5 | + | ---------------------------------- | ----------------------------- | ---------------------------- | + | Account / DApp Verifier V1, V2 | 2000 | 2000 | + | Account / DApp Verifier V3, V4, V5 | 4000 | 2000 | + | Asset Verifier V1, V2 | 2000 | 2000 | + | Asset Verifier V3, V4, V5 | 4000 | 4000 | + | DApp Callable V1, V2 | 2000 | 2000 | + | DApp Callable V3, V4 | 4000 | 4000 | + | DApp Callable V5 | 10000 | 10000 | + */ + var maxCallableComplexity, maxVerifierComplexity int switch tree.LibVersion { case 1, 2: - maxComplexity = 2000 + maxCallableComplexity = MaxCallableScriptComplexityV12 + maxVerifierComplexity = MaxVerifierScriptComplexityReduced case 3, 4: - maxComplexity = 4000 + maxCallableComplexity = MaxCallableScriptComplexityV34 + maxVerifierComplexity = MaxVerifierScriptComplexity case 5: - maxComplexity = 26000 + maxCallableComplexity = MaxCallableScriptComplexityV5 + maxVerifierComplexity = MaxVerifierScriptComplexity } - complexity := estimation.Verifier - if tree.IsDApp() { - complexity = estimation.Estimation + if reducedVerifierComplexity { + maxVerifierComplexity = MaxVerifierScriptComplexityReduced + } + if !tree.IsDApp() { // Expression (simple) script, has only verifier. + if complexity := estimation.Verifier; complexity > maxVerifierComplexity { + return errors.Errorf("script complexity %d exceeds maximum allowed complexity of %d", complexity, maxVerifierComplexity) + } + return nil + } + if complexity := estimation.Verifier; complexity > maxVerifierComplexity { + return errors.Errorf("verifier script complexity %d exceeds maximum allowed complexity of %d", complexity, maxVerifierComplexity) } - if complexity > maxComplexity { - return errors.Errorf("script complexity %d exceeds maximum allowed complexity of %d", complexity, maxComplexity) + if complexity := estimation.Estimation; complexity > maxCallableComplexity { + return errors.Errorf("callable script complexity %d exceeds maximum allowed complexity of %d", complexity, maxCallableComplexity) } return nil } -func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int) (map[int]ride.TreeEstimation, error) { +func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity bool) (map[int]ride.TreeEstimation, error) { tree, err := ride.Parse(script) if err != nil { return nil, errs.Extend(err, "failed to build AST") @@ -131,7 +153,7 @@ func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion } estimations[ev] = est } - if err := tc.checkScriptComplexity(tree, estimations[estimatorVersion]); err != nil { + if err := tc.checkScriptComplexity(tree, estimations[estimatorVersion], reducedVerifierComplexity); err != nil { return nil, errors.Wrap(err, "failed to check script complexity") } return estimations, nil @@ -390,7 +412,7 @@ func (tc *transactionChecker) checkIssueWithProofs(transaction proto.Transaction // No script checks / actions are needed. return nil, nil } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion()) + estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), false) // For asset scripts do not reduce verifier complexity if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } @@ -1003,7 +1025,7 @@ func (tc *transactionChecker) checkSetScriptWithProofs(transaction proto.Transac } return nil, nil } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion()) + estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), info.blockVersion == proto.ProtobufBlockVersion) if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } @@ -1045,7 +1067,7 @@ func (tc *transactionChecker) checkSetAssetScriptWithProofs(transaction proto.Tr if !isSmartAsset { return nil, errs.NewTxValidationError("Reason: Cannot set script on an asset issued without a script. Referenced assetId not found") } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion()) + estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), false) // Do not reduce verifier complexity for asset scripts if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } From 414c662e6ff3d7b01c9ebf6100d6dd5557d905d9 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 1 Jun 2021 10:10:22 +0300 Subject: [PATCH 43/52] Limit on message size removed from rsaVerify and sigVerify functions since Ride V4. (#479) --- pkg/ride/environment.go | 6 ++++++ pkg/ride/functions_proto.go | 7 +++++-- pkg/ride/functions_proto_test.go | 7 ++++++- pkg/ride/runtime.go | 1 + pkg/ride/runtime_moq_test.go | 36 ++++++++++++++++++++++++++++++++ pkg/ride/tree_evaluation_test.go | 9 ++++++++ 6 files changed, 63 insertions(+), 3 deletions(-) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 96bdba3e2..b5b3b4759 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -1062,6 +1062,7 @@ type EvaluationEnvironment struct { check func(int) bool takeStr func(s string, n int) rideString inv rideObject + ver int } func NewEnvironment(scheme proto.Scheme, state types.SmartState) (*EvaluationEnvironment, error) { @@ -1146,6 +1147,7 @@ func (e *EvaluationEnvironment) ChooseTakeString(isRideV5 bool) error { } func (e *EvaluationEnvironment) ChooseSizeCheck(v int) { + e.ver = v if v > 2 { e.check = func(l int) bool { return l <= maxMessageLength @@ -1283,6 +1285,10 @@ func (e *EvaluationEnvironment) setInvocation(inv rideObject) { e.inv = inv } +func (e *EvaluationEnvironment) libVersion() int { + return e.ver +} + func isAssetWaves(assetID []byte) bool { wavesAsset := crypto.Digest{} if len(wavesAsset) != len(assetID) { diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index b8d37aaed..157cbdacb 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -629,7 +629,7 @@ func sigVerify(env Environment, args ...rideType) (rideType, error) { if !ok { return nil, errors.Errorf("sigVerify: unexpected argument type '%s'", args[0].instanceOf()) } - if l := len(message); env != nil && !env.checkMessageLength(l) { + if l := len(message); env != nil && env.libVersion() == 3 && !env.checkMessageLength(l) { return nil, errors.Errorf("sigVerify: invalid message size %d", l) } signature, ok := args[1].(rideBytes) @@ -831,7 +831,7 @@ func addressToString(_ Environment, args ...rideType) (rideType, error) { } } -func rsaVerify(_ Environment, args ...rideType) (rideType, error) { +func rsaVerify(env Environment, args ...rideType) (rideType, error) { if err := checkArgs(args, 4); err != nil { return nil, errors.Wrap(err, "rsaVerify") } @@ -843,6 +843,9 @@ func rsaVerify(_ Environment, args ...rideType) (rideType, error) { if !ok { return nil, errors.Errorf("rsaVerify: unexpected argument type '%s'", args[1].instanceOf()) } + if l := len(message); env != nil && env.libVersion() == 3 && !env.checkMessageLength(l) { + return nil, errors.Errorf("sigVerify: invalid message size %d", l) + } sig, ok := args[2].(rideBytes) if !ok { return nil, errors.Errorf("rsaVerify: unexpected argument type '%s'", args[2].instanceOf()) diff --git a/pkg/ride/functions_proto_test.go b/pkg/ride/functions_proto_test.go index bb0587b30..50f607ca1 100644 --- a/pkg/ride/functions_proto_test.go +++ b/pkg/ride/functions_proto_test.go @@ -485,7 +485,12 @@ func TestSigVerify(t *testing.T) { {[]rideType{rideInt(12345)}, v2check, true, nil}, {[]rideType{rideString("dsfjsadfl"), rideInt(12345)}, v2check, true, nil}, } { - te := &MockRideEnvironment{checkMessageLengthFunc: test.check} + te := &MockRideEnvironment{ + checkMessageLengthFunc: test.check, + libVersionFunc: func() int { + return 3 + }, + } r, err := sigVerify(te, test.args...) if test.fail { assert.Error(t, err) diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index 9a0f1fe1b..e9074ccde 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -372,6 +372,7 @@ type Environment interface { takeString(s string, n int) rideString invocation() rideObject // Invocation object made of invoke transaction setInvocation(inv rideObject) + libVersion() int } type rideConstructor func(Environment) rideType diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index da7bf8bd0..97ec5f091 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -31,6 +31,9 @@ var _ Environment = &MockRideEnvironment{} // invocationFunc: func() rideObject { // panic("mock out the invocation method") // }, +// libVersionFunc: func() int { +// panic("mock out the libVersion method") +// }, // schemeFunc: func() byte { // panic("mock out the scheme method") // }, @@ -77,6 +80,9 @@ type MockRideEnvironment struct { // invocationFunc mocks the invocation method. invocationFunc func() rideObject + // libVersionFunc mocks the libVersion method. + libVersionFunc func() int + // schemeFunc mocks the scheme method. schemeFunc func() byte @@ -120,6 +126,9 @@ type MockRideEnvironment struct { // invocation holds details about calls to the invocation method. invocation []struct { } + // libVersion holds details about calls to the libVersion method. + libVersion []struct { + } // scheme holds details about calls to the scheme method. scheme []struct { } @@ -160,6 +169,7 @@ type MockRideEnvironment struct { lockcheckMessageLength sync.RWMutex lockheight sync.RWMutex lockinvocation sync.RWMutex + locklibVersion sync.RWMutex lockscheme sync.RWMutex locksetInvocation sync.RWMutex locksetNewDAppAddress sync.RWMutex @@ -280,6 +290,32 @@ func (mock *MockRideEnvironment) invocationCalls() []struct { return calls } +// libVersion calls libVersionFunc. +func (mock *MockRideEnvironment) libVersion() int { + if mock.libVersionFunc == nil { + panic("MockRideEnvironment.libVersionFunc: method is nil but Environment.libVersion was just called") + } + callInfo := struct { + }{} + mock.locklibVersion.Lock() + mock.calls.libVersion = append(mock.calls.libVersion, callInfo) + mock.locklibVersion.Unlock() + return mock.libVersionFunc() +} + +// libVersionCalls gets all the calls that were made to libVersion. +// Check the length with: +// len(mockedEnvironment.libVersionCalls()) +func (mock *MockRideEnvironment) libVersionCalls() []struct { +} { + var calls []struct { + } + mock.locklibVersion.RLock() + calls = mock.calls.libVersion + mock.locklibVersion.RUnlock() + return calls +} + // scheme calls schemeFunc. func (mock *MockRideEnvironment) scheme() byte { if mock.schemeFunc == nil { diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index ae2cbf478..139668488 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -162,6 +162,9 @@ func TestFunctionsEvaluation(t *testing.T) { }, } }, + libVersionFunc: func() int { + return 3 + }, } envWithDataTX := &MockRideEnvironment{ transactionFunc: func() rideObject { @@ -172,6 +175,9 @@ func TestFunctionsEvaluation(t *testing.T) { return obj }, takeStringFunc: v5takeString, + libVersionFunc: func() int { + return 3 + }, } envWithExchangeTX := &MockRideEnvironment{ transactionFunc: func() rideObject { @@ -182,6 +188,9 @@ func TestFunctionsEvaluation(t *testing.T) { return obj }, takeStringFunc: v5takeString, + libVersionFunc: func() int { + return 3 + }, } for _, test := range []struct { name string From 769786812247ee3ad07be02ce0051f165c4f4875 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Tue, 1 Jun 2021 10:10:36 +0300 Subject: [PATCH 44/52] Added the limit of invocation scripts with different versions (#480) --- pkg/ride/tree_evaluation.go | 3 ++ pkg/ride/tree_evaluation_test.go | 90 +++----------------------------- pkg/ride/tree_evaluator.go | 6 +-- 3 files changed, 13 insertions(+), 86 deletions(-) diff --git a/pkg/ride/tree_evaluation.go b/pkg/ride/tree_evaluation.go index 57a9176b9..8219579d0 100644 --- a/pkg/ride/tree_evaluation.go +++ b/pkg/ride/tree_evaluation.go @@ -23,6 +23,9 @@ func invokeFunctionFromDApp(env Environment, recipient proto.Recipient, fnName r if err != nil { return nil, errors.Wrap(err, "failed to get tree by script") } + if tree.LibVersion < 5 { + return nil, errors.Errorf("failed to call 'invoke' for script with version %d. Scripts with version 5 are only allowed to be used in 'invoke'", tree.LibVersion) + } e, err := treeFunctionEvaluatorForInvokeDAppFromDApp(env, tree, string(fnName), listArgs) if err != nil { diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 139668488..20948b113 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -3782,7 +3782,6 @@ func TestPaymentsDifferentScriptVersion4(t *testing.T) { addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) @@ -3819,14 +3818,6 @@ func TestPaymentsDifferentScriptVersion4(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, - } - - expectedTransferWrites := []*proto.TransferScriptAction{ - {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}}, - } - smartState := smartStateDappFromDapp thisAddress = addr @@ -3849,40 +3840,12 @@ func TestPaymentsDifferentScriptVersion4(t *testing.T) { res, err := CallFunction(env, tree, "test", proto.Arguments{}) - require.NoError(t, err) + require.Error(t, err) r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: expectedTransferWrites, - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - } - - assert.Equal(t, expectedActionsResult, sr) - - expectedDiffResult := initWrappedState(smartState(), env).diff - - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9999} - balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} - balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} - expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain - expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender - expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable - intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} - expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry + require.False(t, ok) + require.False(t, r.res) - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + tearDownDappFromDapp() tearDownDappFromDapp() @@ -3943,7 +3906,6 @@ func TestPaymentsDifferentScriptVersion3(t *testing.T) { addressCallable, err = proto.NewAddressFromString("3P8eZVKS7a4troGckytxaefLAi9w7P5aMna") require.NoError(t, err) - recipientCallable := proto.NewRecipientFromAddress(addressCallable) addressCallablePK, err = smartStateDappFromDapp().NewestScriptPKByAddr(addressCallable) require.NoError(t, err) @@ -3980,14 +3942,6 @@ func TestPaymentsDifferentScriptVersion3(t *testing.T) { id = bytes.Repeat([]byte{0}, 32) - expectedDataEntryWrites := []*proto.DataEntryScriptAction{ - {Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, Sender: &addressCallablePK}, - } - - expectedTransferWrites := []*proto.TransferScriptAction{ - {Recipient: recipientCallable, Sender: &addrPK, Amount: 1, Asset: proto.OptionalAsset{}}, - } - smartState := smartStateDappFromDapp thisAddress = addr @@ -4010,40 +3964,10 @@ func TestPaymentsDifferentScriptVersion3(t *testing.T) { res, err := CallFunction(env, tree, "test", proto.Arguments{}) - require.NoError(t, err) + require.Error(t, err) r, ok := res.(DAppResult) - require.True(t, ok) - require.True(t, r.res) - - sr, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) - require.NoError(t, err) - - expectedActionsResult := &proto.ScriptResult{ - DataEntries: expectedDataEntryWrites, - Transfers: expectedTransferWrites, - Issues: make([]*proto.IssueScriptAction, 0), - Reissues: make([]*proto.ReissueScriptAction, 0), - Burns: make([]*proto.BurnScriptAction, 0), - Sponsorships: make([]*proto.SponsorshipScriptAction, 0), - Leases: make([]*proto.LeaseScriptAction, 0), - LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), - } - - assert.Equal(t, expectedActionsResult, sr) - - expectedDiffResult := initWrappedState(smartState(), env).diff - - balanceMain := diffBalance{asset: proto.OptionalAsset{}, regular: 9999} - balanceSender := diffBalance{asset: proto.OptionalAsset{}, regular: 0} - balanceCallable := diffBalance{asset: proto.OptionalAsset{}, regular: 1} - expectedDiffResult.balances[addr.String()+proto.OptionalAsset{}.String()] = balanceMain - expectedDiffResult.balances[senderAddress.String()+proto.OptionalAsset{}.String()] = balanceSender - expectedDiffResult.balances[addressCallable.String()+proto.OptionalAsset{}.String()] = balanceCallable - intEntry := proto.IntegerDataEntry{Key: "int", Value: 1} - expectedDiffResult.dataEntries.diffInteger["int"+addressCallable.String()] = intEntry - - assert.Equal(t, expectedDiffResult.dataEntries, wrappedSt.diff.dataEntries) - assert.Equal(t, expectedDiffResult.balances, wrappedSt.diff.balances) + require.False(t, ok) + require.False(t, r.res) tearDownDappFromDapp() diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index 7dbd27340..c7d1d5c0a 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -213,11 +213,11 @@ func keys(m map[string]int, enableInvocation bool) []string { func selectFunctionNames(v int, enableInvocation bool) ([]string, error) { switch v { case 1, 2: - return keys(CatalogueV2, enableInvocation), nil + return keys(CatalogueV2, false), nil case 3: - return keys(CatalogueV3, enableInvocation), nil + return keys(CatalogueV3, false), nil case 4: - return keys(CatalogueV4, enableInvocation), nil + return keys(CatalogueV4, false), nil case 5: return keys(CatalogueV5, enableInvocation), nil default: From 406763973d11b3fdd7216cc414e3211e1e44ff0b Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 7 Jun 2021 14:30:25 +0300 Subject: [PATCH 45/52] Fixed check on rideV5Activated (#484) --- pkg/state/invoke_applier.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 4073d5f29..d5d885a4f 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -2,6 +2,7 @@ package state import ( "fmt" + "log" "math" "math/big" @@ -678,7 +679,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf } var scriptRuns uint64 = 0 // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. - if info.rideV5Activated { + if !info.rideV5Activated { actionScriptRuns := ia.countActionScriptRuns(scriptActions, info.initialisation) scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns } @@ -709,6 +710,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf libVersion: byte(tree.LibVersion), }) if err != nil { + log.Printf("fallibleValidation error in tx %s. Error: %s", tx.ID.String(), err.Error()) // If fallibleValidation fails, we should save transaction to blockchain when acceptFailed is true. if !info.acceptFailed { return nil, err From 81e729d57b657acbdf211e0b181c01f08c0444fd Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Mon, 7 Jun 2021 16:41:00 +0300 Subject: [PATCH 46/52] Ride payment limits invoke (#485) * Added payment limits in invoke functions * Fixed old mistake of payment limits related to lib version --- pkg/ride/functions_proto.go | 15 ++++++++++++--- pkg/state/invoke_applier.go | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 157cbdacb..e5a87448f 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -130,6 +130,10 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: *asset, Amount: uint64(intAmount)}) } + // since RideV5 the limit of attached payments is 10 + if len(attachedPayments) > 10 { + return nil, errors.New("invoke: no more than ten payments is allowed since RideV5 activation") + } var paymentActions []proto.ScriptAction for _, payment := range attachedPayments { @@ -139,7 +143,7 @@ func reentrantInvoke(env Environment, args ...rideType) (rideType, error) { address, err := env.state().NewestRecipientToAddress(recipient) if err != nil { - return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") + return nil, errors.Errorf("failed to get address from dApp, invokeFunctionFromDApp") } env.setNewDAppAddress(*address) err = ws.smartAppendActions(paymentActions, env) @@ -289,6 +293,11 @@ func invoke(env Environment, args ...rideType) (rideType, error) { attachedPayments = append(attachedPayments, proto.ScriptPayment{Asset: *asset, Amount: uint64(intAmount)}) } + // since RideV5 the limit of attached payments is 10 + if len(attachedPayments) > 10 { + return nil, errors.New("invoke: no more than ten payments is allowed since RideV5 activation") + } + var paymentActions []proto.ScriptAction for _, payment := range attachedPayments { action := &proto.TransferScriptAction{Sender: &callerPublicKey, Recipient: recipient, Amount: int64(payment.Amount), Asset: payment.Asset} @@ -297,7 +306,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { address, err := env.state().NewestRecipientToAddress(recipient) if err != nil { - return nil, errors.Errorf("cannot get address from dApp, invokeFunctionFromDApp") + return nil, errors.Errorf("failed get address from dApp, invokeFunctionFromDApp") } env.setNewDAppAddress(*address) err = ws.smartAppendActions(paymentActions, env) @@ -310,7 +319,7 @@ func invoke(env Environment, args ...rideType) (rideType, error) { if ws.invCount() > 1 { if isAddressInBL(*recipient.Address, ws.blackList) && proto.Address(callerAddress) != *recipient.Address { - return rideUnit{}, errors.Errorf("failed to call ") + return rideUnit{}, errors.Errorf("function call of %s with dApp address %s is forbiden because it had already been called once by 'invoke'", fnName, recipient.Address) } } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index d5d885a4f..bff57df8f 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -641,7 +641,7 @@ func (ia *invokeApplier) applyInvokeScript(tx *proto.InvokeScriptWithProofs, inf } // Check that the script's library supports multiple payments. // We don't have to check feature activation because we done it before. - if len(tx.Payments) == 2 && tree.LibVersion < 4 { + if len(tx.Payments) >= 2 && tree.LibVersion < 4 { return nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", tree.LibVersion) } // Refuse payments to DApp itself since activation of BlockV5 (acceptFailed) and for DApps with StdLib V4. From 2399fa2d1529f3c6474a2004033bcf399fdefd12 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 7 Jun 2021 17:56:56 +0300 Subject: [PATCH 47/52] Node http api improvements, new CBOR peers storage (#481) * Node http api improvements version 0.9 (#475) * Added metrics for node HTTP API * Added Wallet addresses handler for node HTTP API (route = '/addresses') * Added limiter and run options for node HTTP API. * Added all ApiError types from scala-node API * Created new ApiError handling model and middleware for that * Blocks HTTP api refactoring * Created /go/... routes in node HTTP API * Added /peers/all route. Fixed /go/peers/known route. Changed testnet default peers * Created peerInfoFromPeer func for PeerInfo struct in pkg/api * Implemented '/peers/suspended' node HTTP endpoint * Fixes #462 * New CBOR persistent peers storage, version 0.9 (#478) * WIP: new peers storage * Creted new CBOR peers storage * Now node uses new CBOR peers storage * Removed peers storage in State * Updated peers storage inteface. Added 'drop-peers' flag for node. * Code cleanup and node HTTP API error handler bugfix. --- .gitignore | 1 + cmd/custom/node.go | 35 +- cmd/node/node.go | 38 +- go.mod | 3 +- go.sum | 9 + pkg/api/app.go | 22 +- pkg/api/app_addresses.go | 17 + pkg/api/app_blocks.go | 17 +- pkg/api/app_miner.go | 8 +- pkg/api/app_peers.go | 117 +- pkg/api/app_peers_test.go | 59 +- pkg/api/errors.go | 68 +- pkg/api/errors/auth.go | 43 + pkg/api/errors/basics.go | 124 ++ pkg/api/errors/basics_test.go | 41 + pkg/api/errors/consts.go | 97 + pkg/api/errors/transaction.go | 71 + pkg/api/errors/validation.go | 154 ++ pkg/api/errors/validation_test.go | 39 + pkg/api/errors_test.go | 5 - pkg/api/helpers.go | 7 + pkg/api/metrics.go | 43 + pkg/api/middleware.go | 99 + pkg/api/node_api.go | 449 ++-- pkg/api/node_api_test.go | 26 +- pkg/api/rate_limiter.go | 39 + pkg/api/routes.go | 157 +- pkg/api/settings.go | 46 + pkg/mock/peer_manager.go | 306 +-- pkg/mock/peer_storage.go | 204 ++ pkg/mock/state.go | 2023 +++++++++--------- pkg/node/actions_by_type.go | 26 +- pkg/node/actions_by_type_test.go | 6 +- pkg/node/peer_manager/memory_peer_storage.go | 18 - pkg/node/peer_manager/peer_manager.go | 173 +- pkg/node/peer_manager/peer_manager_test.go | 38 - pkg/node/peer_manager/peer_storage.go | 21 +- pkg/node/peer_manager/peer_storage_test.go | 40 + pkg/node/peer_manager/storage/binary.go | 138 -- pkg/node/peer_manager/storage/binary_test.go | 74 - pkg/node/peer_manager/storage/cbor.go | 411 ++++ pkg/node/peer_manager/storage/cbor_test.go | 424 ++++ pkg/node/peer_manager/storage/types.go | 70 + pkg/node/peer_manager/storage/types_test.go | 37 + pkg/node/state_fsm/fsm_sync.go | 2 +- pkg/state/api.go | 5 - pkg/state/keys.go | 4 +- pkg/state/known_peer.go | 25 - pkg/state/known_peer_test.go | 15 - pkg/state/peer_storage.go | 60 - pkg/state/state.go | 15 +- pkg/state/state_test.go | 36 - pkg/state/threadsafe_wrapper.go | 12 - 53 files changed, 3970 insertions(+), 2047 deletions(-) create mode 100644 pkg/api/app_addresses.go create mode 100644 pkg/api/errors/auth.go create mode 100644 pkg/api/errors/basics.go create mode 100644 pkg/api/errors/basics_test.go create mode 100644 pkg/api/errors/consts.go create mode 100644 pkg/api/errors/transaction.go create mode 100644 pkg/api/errors/validation.go create mode 100644 pkg/api/errors/validation_test.go create mode 100644 pkg/api/helpers.go create mode 100644 pkg/api/metrics.go create mode 100644 pkg/api/middleware.go create mode 100644 pkg/api/rate_limiter.go create mode 100644 pkg/mock/peer_storage.go delete mode 100644 pkg/node/peer_manager/memory_peer_storage.go delete mode 100644 pkg/node/peer_manager/peer_manager_test.go create mode 100644 pkg/node/peer_manager/peer_storage_test.go delete mode 100644 pkg/node/peer_manager/storage/binary.go delete mode 100644 pkg/node/peer_manager/storage/binary_test.go create mode 100644 pkg/node/peer_manager/storage/cbor.go create mode 100644 pkg/node/peer_manager/storage/cbor_test.go create mode 100644 pkg/node/peer_manager/storage/types.go create mode 100644 pkg/node/peer_manager/storage/types_test.go delete mode 100644 pkg/state/known_peer.go delete mode 100644 pkg/state/known_peer_test.go delete mode 100644 pkg/state/peer_storage.go diff --git a/.gitignore b/.gitignore index 8d3c65fab..ff766a916 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ vendor/ build/ out/ +.run/ *.lock *.txt diff --git a/cmd/custom/node.go b/cmd/custom/node.go index 43cbe000c..7eef9bd65 100644 --- a/cmd/custom/node.go +++ b/cmd/custom/node.go @@ -24,7 +24,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/node/blocks_applier" "github.com/wavesplatform/gowaves/pkg/node/messages" "github.com/wavesplatform/gowaves/pkg/node/peer_manager" - "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + peersPersistentStorage "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "github.com/wavesplatform/gowaves/pkg/node/state_fsm/ng" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" @@ -57,6 +57,7 @@ var ( walletPassword = flag.String("wallet-password", "", "Pass password for wallet. Extremely insecure") limitConnectionsS = flag.String("limit-connections", "30", "N incoming and outgoing connections") minPeersMining = flag.Int("min-peers-mining", 1, "Minimum connected peers for allow mining") + dropPeers = flag.Bool("drop-peers", false, "Drop peers storage before node start.") ) func init() { @@ -190,7 +191,23 @@ func main() { peerSpawnerImpl := peer_manager.NewPeerSpawner(btsPool, parent, conf.WavesNetwork, declAddr, "gowaves", uint64(rand.Int()), version) - peerStorage := storage.NewBinaryStorage(path) + peerStorage, err := peersPersistentStorage.NewCBORStorage(*statePath, time.Now()) + if err != nil { + zap.S().Errorf("Failed to open or create peers storage: %v", err) + cancel() + return + } + if *dropPeers { + if err := peerStorage.DropStorage(); err != nil { + zap.S().Errorf( + "Failed to drop peers storage. Drop peers storage manually. Err: %v", + err, + ) + cancel() + return + } + zap.S().Info("Successfully dropped peers storage") + } peerManager := peer_manager.NewPeerManager(peerSpawnerImpl, peerStorage, int(limitConnections), version) go peerManager.Run(ctx) @@ -234,7 +251,19 @@ func main() { if len(conf.Addresses) > 0 { addresses := strings.Split(conf.Addresses, ",") for _, addr := range addresses { - peerManager.AddAddress(ctx, addr) + tcpAddr := proto.NewTCPAddrFromString(addr) + if tcpAddr.Empty() { + // nickeskov: that means that configuration parameter is invalid + zap.S().Errorf("Failed to parse TCPAddr from string %q", tcpAddr.String()) + cancel() + return + } + if err := peerManager.AddAddress(ctx, tcpAddr); err != nil { + // nickeskov: than means that we have problems with peers storage + zap.S().Errorf("Failed to add addres into know peers storage: %v", err) + cancel() + return + } } } diff --git a/cmd/node/node.go b/cmd/node/node.go index 157a621f6..418fd1be0 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -31,7 +31,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/node/blocks_applier" "github.com/wavesplatform/gowaves/pkg/node/messages" "github.com/wavesplatform/gowaves/pkg/node/peer_manager" - "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + peersPersistentStorage "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/services" @@ -83,6 +83,7 @@ var ( integrationMinAssetInfoUpdateInterval = flag.Int("integration.min-asset-info-update-interval", 100000, "Minimum asset info update interval for integration tests.") metricsID = flag.Int("metrics-id", -1, "ID of the node on the metrics collection system") metricsURL = flag.String("metrics-url", "", "URL of InfluxDB or Telegraf in form of 'http://username:password@host:port/db'") + dropPeers = flag.Bool("drop-peers", false, "Drop peers storage before node start.") ) var defaultPeers = map[string]string{ @@ -120,6 +121,7 @@ func debugCommandLineParameters() { zap.S().Debugf("limit-connections: %s", *limitConnectionsS) zap.S().Debugf("profiler: %v", *profiler) zap.S().Debugf("bloom: %v", *bloomFilter) + zap.S().Debugf("drop-peers: %v", *dropPeers) } func main() { @@ -294,7 +296,23 @@ func main() { peerSpawnerImpl := peer_manager.NewPeerSpawner(pool, parent, conf.WavesNetwork, declAddr, *nodeName, uint64(rand.Int()), version) - peerStorage := storage.NewBinaryStorage(path) + peerStorage, err := peersPersistentStorage.NewCBORStorage(*statePath, time.Now()) + if err != nil { + zap.S().Errorf("Failed to open or create peers storage: %v", err) + cancel() + return + } + if *dropPeers { + if err := peerStorage.DropStorage(); err != nil { + zap.S().Errorf( + "Failed to drop peers storage. Drop peers storage manually. Err: %v", + err, + ) + cancel() + return + } + zap.S().Info("Successfully dropped peers storage") + } peerManager := peer_manager.NewPeerManager( peerSpawnerImpl, @@ -344,7 +362,19 @@ func main() { if len(conf.Addresses) > 0 { addresses := strings.Split(conf.Addresses, ",") for _, addr := range addresses { - peerManager.AddAddress(ctx, addr) + tcpAddr := proto.NewTCPAddrFromString(addr) + if tcpAddr.Empty() { + // nickeskov: that means that configuration parameter is invalid + zap.S().Errorf("Failed to parse TCPAddr from string %q", tcpAddr.String()) + cancel() + return + } + if err := peerManager.AddAddress(ctx, tcpAddr); err != nil { + // nickeskov: than means that we have problems with peers storage + zap.S().Errorf("Failed to add addres into know peers storage: %v", err) + cancel() + return + } } } @@ -357,6 +387,7 @@ func main() { webApi := api.NewNodeApi(app, st, n) go func() { + zap.S().Infof("Starting node HTTP API on '%v'", conf.HttpAddr) err := api.Run(ctx, conf.HttpAddr, webApi) if err != nil { zap.S().Errorf("Failed to start API: %v", err) @@ -368,6 +399,7 @@ func main() { h := http.NewServeMux() h.Handle("/metrics", promhttp.Handler()) s := &http.Server{Addr: *prometheus, Handler: h} + zap.S().Infof("Starting node metrics endpoint on '%v'", *prometheus) _ = s.ListenAndServe() } }() diff --git a/go.mod b/go.mod index 928e95077..1596a28bc 100644 --- a/go.mod +++ b/go.mod @@ -23,8 +23,6 @@ require ( github.com/kilic/bn254 v0.0.0-20200902152204-ab63fe16fead github.com/magiconair/properties v1.8.1 github.com/mr-tron/base58 v1.1.2 - github.com/onsi/ginkgo v1.10.1 // indirect - github.com/onsi/gomega v1.7.0 // indirect github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 @@ -37,6 +35,7 @@ require ( github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 github.com/stretchr/testify v1.6.1 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d + github.com/throttled/throttled/v2 v2.7.1 github.com/valyala/bytebufferpool v1.0.0 github.com/xenolf/lego v2.7.2+incompatible go.uber.org/atomic v1.4.0 diff --git a/go.sum b/go.sum index 974cfae70..9d1041c36 100644 --- a/go.sum +++ b/go.sum @@ -93,6 +93,7 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -115,6 +116,8 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -126,6 +129,7 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk= github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= @@ -256,6 +260,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/throttled/throttled/v2 v2.7.1 h1:FnBysDX4Sok55bvfDMI0l2Y71V1vM2wi7O79OW7fNtw= +github.com/throttled/throttled/v2 v2.7.1/go.mod h1:fuOeyK9fmnA+LQnsBbfT/mmPHjmkdogRBQxaD8YsgZ8= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -290,6 +296,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -307,6 +314,7 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -371,6 +379,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/pkg/api/app.go b/pkg/api/app.go index 38965ebb5..c051b396f 100644 --- a/pkg/api/app.go +++ b/pkg/api/app.go @@ -97,30 +97,34 @@ func (a *App) LoadKeys(apiKey string, password []byte) error { } func (a *App) Accounts() ([]account, error) { - r := make([]account, 0) - for _, s := range a.services.Wallet.Seeds() { - _, pk, err := crypto.GenerateKeyPair(s) + seeds := a.services.Wallet.Seeds() + + accounts := make([]account, 0, len(seeds)) + for _, seed := range seeds { + _, pk, err := crypto.GenerateKeyPair(seed) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to generate key pair for seed") } - a, err := proto.NewAddressFromPublicKey(a.services.Scheme, pk) + addr, err := proto.NewAddressFromPublicKey(a.services.Scheme, pk) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to generate new address from public key") } - r = append(r, account{Address: a, PublicKey: pk}) + accounts = append(accounts, account{Address: addr, PublicKey: pk}) } - return r, nil + return accounts, nil } func (a *App) checkAuth(key string) error { if !a.apiKeyEnabled { + // TODO(nickeskov): use new types of errors return &AuthError{errors.New("api key disabled")} } d, err := crypto.SecureHash([]byte(key)) if err != nil { - return &AuthError{err} + return errors.Wrap(err, "failed to calculate secure hash for API key") } if d != a.hashedApiKey { + // TODO(nickeskov): use new types of errors return &AuthError{errors.New("invalid api key")} } return nil diff --git a/pkg/api/app_addresses.go b/pkg/api/app_addresses.go new file mode 100644 index 000000000..9d37c8909 --- /dev/null +++ b/pkg/api/app_addresses.go @@ -0,0 +1,17 @@ +package api + +import "github.com/pkg/errors" + +func (a *App) Addresses() ([]string, error) { + accounts, err := a.Accounts() + if err != nil { + return nil, errors.Wrap(err, "failed to get wallet accounts") + } + + addresses := make([]string, 0, len(accounts)) + for i := range accounts { + addresses = append(addresses, accounts[i].Address.String()) + } + + return addresses, nil +} diff --git a/pkg/api/app_blocks.go b/pkg/api/app_blocks.go index 4f22a9555..deed560ff 100644 --- a/pkg/api/app_blocks.go +++ b/pkg/api/app_blocks.go @@ -1,6 +1,7 @@ package api import ( + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -9,23 +10,23 @@ type Score struct { Score string `json:"score"` } -func (a *App) BlocksScoreAt(at proto.Height) (*Score, error) { +func (a *App) BlocksScoreAt(at proto.Height) (Score, error) { score, err := a.state.ScoreAtHeight(at) if err != nil { - return nil, err + return Score{}, err } - return &Score{Score: score.String()}, nil + return Score{Score: score.String()}, nil } func (a *App) BlocksLast() (*proto.Block, error) { h, err := a.state.Height() if err != nil { - return nil, &InternalError{err} + return nil, errors.Wrap(err, "failed to get state height") } block, err := a.state.BlockByHeight(h) if err != nil { - return nil, &InternalError{err} + return nil, errors.Wrapf(err, "failed to get %d block from state", h) } block.Height = h return block, nil @@ -34,7 +35,7 @@ func (a *App) BlocksLast() (*proto.Block, error) { func (a *App) BlocksFirst() (*proto.Block, error) { block, err := a.state.BlockByHeight(1) if err != nil { - return nil, &InternalError{err} + return nil, errors.Wrap(err, "failed to get first block from state") } block.Height = 1 return block, nil @@ -49,7 +50,7 @@ type Generator struct { func (a *App) BlocksGenerators() (Generators, error) { curHeight, err := a.state.Height() if err != nil { - return nil, &InternalError{err} + return nil, errors.Wrap(err, "failed to get state height") } // show only last 150 rows @@ -62,7 +63,7 @@ func (a *App) BlocksGenerators() (Generators, error) { for i := initialHeight; i < curHeight; i++ { block, err := a.state.BlockByHeight(i) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "failed to get from state block by height %d", i) } out = append(out, Generator{ diff --git a/pkg/api/app_miner.go b/pkg/api/app_miner.go index 486834c1b..0d4278ae8 100644 --- a/pkg/api/app_miner.go +++ b/pkg/api/app_miner.go @@ -19,10 +19,10 @@ type MinerInfo struct { Scheduler Scheduler } -func (a *App) Miner() (*MinerInfo, error) { +func (a *App) Miner() MinerInfo { e := a.scheduler.Emits() - next := make([]Next, 0) + next := make([]Next, 0, len(e)) for _, row := range e { next = append(next, Next{ PublicKey: row.KeyPair.Public, @@ -30,10 +30,10 @@ func (a *App) Miner() (*MinerInfo, error) { }) } - return &MinerInfo{ + return MinerInfo{ Scheduler: Scheduler{ TimeNow: time.Now(), Next: next, }, - }, nil + } } diff --git a/pkg/api/app_peers.go b/pkg/api/app_peers.go index 064f32ecc..35c485134 100644 --- a/pkg/api/app_peers.go +++ b/pkg/api/app_peers.go @@ -2,34 +2,60 @@ package api import ( "context" - "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" "go.uber.org/zap" + "time" ) type Peer struct { Address string `json:"address"` - LastSeen uint64 `json:"lastSeen"` + LastSeen uint64 `json:"lastSeen,omitempty"` } -type PeersAll struct { +type PeersKnown struct { Peers []Peer `json:"peers"` } -func (a *App) PeersAll() (*PeersAll, error) { - peers, err := a.state.Peers() - if err != nil { - return nil, &InternalError{err} +// PeersAll is a list of all known not banned and not suspended peers with a publicly available declared address +func (a *App) PeersAll() (PeersKnown, error) { + suspended := a.peers.Suspended() + suspendedIPsMap := make(map[string]struct{}, len(suspended)) + for _, suspendedPeer := range suspended { + suspendedIPsMap[suspendedPeer.IP.String()] = struct{}{} + } + + knownPeers := a.peers.KnownPeers() + + nowMillis := unixMillis(time.Now()) + + out := make([]Peer, 0, len(knownPeers)) + for _, knownPeer := range knownPeers { + ip := knownPeer.String() + if _, in := suspendedIPsMap[ip]; in { + continue + } + // FIXME(nickeksov): add normal lastSeen field + out = append(out, Peer{ + Address: "/" + ip, + LastSeen: uint64(nowMillis), + }) } - var out []Peer - for _, row := range peers { - out = append(out, Peer{Address: row.String()}) + return PeersKnown{Peers: out}, nil +} + +func (a *App) PeersKnown() (PeersKnown, error) { + knownPeers := a.peers.KnownPeers() + + out := make([]Peer, 0, len(knownPeers)) + for _, knownPeer := range knownPeers { + // nickeksov: knownPeers without lastSeen field + out = append(out, Peer{Address: knownPeer.String()}) } - return &PeersAll{Peers: out}, nil + return PeersKnown{Peers: out}, nil } type PeersConnectResponse struct { @@ -61,10 +87,10 @@ func (a *App) PeersConnect(ctx context.Context, apiKey string, addr string) (*Pe } type PeersConnectedResponse struct { - Peers []PeersConnectedRow `json:"peers"` + Peers []PeerInfo `json:"peers"` } -type PeersConnectedRow struct { +type PeerInfo struct { Address string `json:"address"` DeclaredAddress string `json:"declaredAddress"` PeerName string `json:"peerName"` @@ -73,42 +99,61 @@ type PeersConnectedRow struct { ApplicationVersion string `json:"applicationVersion"` } -func (a *App) PeersConnected() (*PeersConnectedResponse, error) { - var out []PeersConnectedRow - a.peers.EachConnected(func(peer peer.Peer, i *proto.Score) { - - v := PeersConnectedRow{ - Address: "/" + peer.RemoteAddr().String(), - DeclaredAddress: "/" + peer.Handshake().DeclaredAddr.String(), - PeerName: peer.Handshake().NodeName, - PeerNonce: peer.Handshake().NodeNonce, - ApplicationName: peer.Handshake().AppName, - ApplicationVersion: peer.Handshake().Version.String(), - } +func peerInfoFromPeer(peer peer.Peer) PeerInfo { + handshake := peer.Handshake() + + declaredAddrStr := "N/A" + if !handshake.DeclaredAddr.Empty() { + declaredAddrStr = handshake.DeclaredAddr.String() + } - out = append(out, v) + return PeerInfo{ + Address: "/" + peer.RemoteAddr().String(), + DeclaredAddress: "/" + declaredAddrStr, + PeerName: handshake.NodeName, + PeerNonce: handshake.NodeNonce, + ApplicationName: handshake.AppName, + ApplicationVersion: handshake.Version.String(), + } +} +func (a *App) PeersConnected() PeersConnectedResponse { + var out []PeerInfo + a.peers.EachConnected(func(peer peer.Peer, _ *proto.Score) { + out = append(out, peerInfoFromPeer(peer)) }) - return &PeersConnectedResponse{ + return PeersConnectedResponse{ Peers: out, - }, nil + } } -type PeersSuspendedResponse struct { - Peers []string `json:"peers"` +type SuspendedPeerInfo struct { + Hostname string `json:"hostname"` + Timestamp int64 `json:"timestamp"` // nickeskov: timestamp in millis + Reason string `json:"reason,omitempty"` } -func (a *App) PeersSuspended() (*PeersSuspendedResponse, error) { - peers := a.peers.Suspended() - return &PeersSuspendedResponse{peers}, nil +func (a *App) PeersSuspended() []SuspendedPeerInfo { + suspended := a.peers.Suspended() + + out := make([]SuspendedPeerInfo, 0, len(suspended)) + for _, p := range suspended { + out = append(out, SuspendedPeerInfo{ + Hostname: "/" + p.IP.String(), + Timestamp: p.SuspendTimestampMillis, + Reason: p.Reason, + }) + } + + return out } type PeersSpawnedResponse struct { - Peers []proto.IpPort + Peers []proto.IpPort `json:"peers"` } -func (a *App) PeersSpawned() *PeersSpawnedResponse { +func (a *App) PeersSpawned() PeersSpawnedResponse { rs := a.peers.Spawned() - return &PeersSpawnedResponse{Peers: rs} + return PeersSpawnedResponse{Peers: rs} } diff --git a/pkg/api/app_peers_test.go b/pkg/api/app_peers_test.go index e90ca964c..3a883be02 100644 --- a/pkg/api/app_peers_test.go +++ b/pkg/api/app_peers_test.go @@ -1,26 +1,73 @@ package api import ( + "github.com/stretchr/testify/assert" + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + "github.com/wavesplatform/gowaves/pkg/proto" + "net" "testing" + "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/mock" - "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/services" ) -func TestApp_PeersAll(t *testing.T) { +func TestApp_PeersKnown(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - s := mock.NewMockState(ctrl) - s.EXPECT().Peers().Return([]proto.TCPAddr{proto.NewTCPAddrFromString("127.0.0.1:6868")}, nil) + peerManager := mock.NewMockPeerManager(ctrl) + addr := proto.NewTCPAddr(net.ParseIP("127.0.0.1"), 6868).ToIpPort() + peerManager.EXPECT().KnownPeers().Return([]storage.KnownPeer{storage.KnownPeer(addr)}) - app, err := NewApp("key", nil, services.Services{State: s}) + app, err := NewApp("key", nil, services.Services{Peers: peerManager}) require.NoError(t, err) - rs2, err := app.PeersAll() + rs2, err := app.PeersKnown() require.NoError(t, err) require.Len(t, rs2.Peers, 1) } + +func TestApp_PeersSuspended(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + peerManager := mock.NewMockPeerManager(ctrl) + + now := time.Now() + + ips := []string{"13.3.4.1", "5.3.6.7"} + testData := []storage.SuspendedPeer{ + { + IP: storage.IPFromString(ips[0]), + SuspendTimestampMillis: now.Add(time.Minute).UnixNano() / 1_000_000, + SuspendDuration: time.Minute, + Reason: "some reason #1", + }, + { + IP: storage.IPFromString(ips[1]), + SuspendTimestampMillis: now.Add(2*time.Minute).UnixNano() / 1_000_000, + SuspendDuration: time.Minute, + Reason: "some reason #2", + }, + } + + peerManager.EXPECT().Suspended().Return(testData) + + app, err := NewApp("key", nil, services.Services{Peers: peerManager}) + require.NoError(t, err) + + suspended := app.PeersSuspended() + + for i, actual := range suspended { + p := testData[i] + expected := SuspendedPeerInfo{ + Hostname: "/" + ips[i], + Timestamp: p.SuspendTimestampMillis, + Reason: p.Reason, + } + assert.Equal(t, expected, actual) + } +} diff --git a/pkg/api/errors.go b/pkg/api/errors.go index 30a908610..e3856d651 100644 --- a/pkg/api/errors.go +++ b/pkg/api/errors.go @@ -1,5 +1,15 @@ package api +import ( + "encoding/json" + "fmt" + "github.com/go-chi/chi/middleware" + "github.com/pkg/errors" + apiErrs "github.com/wavesplatform/gowaves/pkg/api/errors" + "go.uber.org/zap" + "net/http" +) + type BadRequestError struct { error } @@ -8,6 +18,60 @@ type AuthError struct { error } -type InternalError struct { - error +type ErrorHandler struct { + logger *zap.Logger +} + +func NewErrorHandler(logger *zap.Logger) ErrorHandler { + return ErrorHandler{ + logger: logger, + } +} + +func (eh *ErrorHandler) Handle(w http.ResponseWriter, r *http.Request, err error) { + if err == nil { + return + } + switch innerErr := errors.Cause(err).(type) { + case BadRequestError, *BadRequestError: + // nickeskov: this error type will be removed in future + http.Error(w, fmt.Sprintf("Failed to complete request: %s", innerErr.Error()), http.StatusBadRequest) + case AuthError, *AuthError: + // nickeskov: this error type will be removed in future + http.Error(w, fmt.Sprintf("Failed to complete request: %s", innerErr.Error()), http.StatusForbidden) + case *apiErrs.UnknownError: + eh.logger.Error("UnknownError", + zap.String("proto", r.Proto), + zap.String("path", r.URL.Path), + zap.String("reqId", middleware.GetReqID(r.Context())), + zap.Error(err), + ) + eh.sendApiErrJSON(w, r, innerErr) + case apiErrs.ApiError: + eh.sendApiErrJSON(w, r, innerErr) + default: + eh.logger.Error("InternalServerError", + zap.String("proto", r.Proto), + zap.String("path", r.URL.Path), + zap.String("reqId", middleware.GetReqID(r.Context())), + zap.Error(err), + ) + unknownErrWrapper := apiErrs.NewUnknownError(innerErr) + eh.sendApiErrJSON(w, r, unknownErrWrapper) + } +} + +func (eh *ErrorHandler) sendApiErrJSON(w http.ResponseWriter, r *http.Request, apiErr apiErrs.ApiError) { + w.WriteHeader(apiErr.GetHttpCode()) + if encodeErr := json.NewEncoder(w).Encode(apiErr); encodeErr != nil { + eh.logger.Error("Failed to marshal API Error to JSON", + zap.String("proto", r.Proto), + zap.String("path", r.URL.Path), + zap.String("request_id", middleware.GetReqID(r.Context())), + zap.Error(encodeErr), + zap.String("api_error", apiErr.Error()), + ) + // nickeskov: Type which implements ApiError interface MUST be serializable to JSON. + panic(errors.Errorf("BUG, CREATE REPORT: %s", encodeErr.Error())) + } } diff --git a/pkg/api/errors/auth.go b/pkg/api/errors/auth.go new file mode 100644 index 000000000..8201ed040 --- /dev/null +++ b/pkg/api/errors/auth.go @@ -0,0 +1,43 @@ +package errors + +import ( + "fmt" + "net/http" +) + +//API Auth +type authError struct { + genericError +} + +type ( + ApiKeyNotValidError authError + TooBigArrayAllocationError authError +) + +var ( + ApiKeyNotValid = &ApiKeyNotValidError{ + genericError: genericError{ + ID: ApiKeyNotValidErrorID, + HttpCode: http.StatusBadRequest, + Message: "Provided API key is not correct", + }, + } + TooBigArrayAllocation = &TooBigArrayAllocationError{ + genericError: genericError{ + ID: TooBigArrayAllocationErrorID, + HttpCode: http.StatusBadRequest, + Message: "Too big sequence requested", + }, + } +) + +func NewTooBigArrayAllocationError(limit int) *TooBigArrayAllocationError { + return &TooBigArrayAllocationError{ + genericError: genericError{ + ID: TooBigArrayAllocationErrorID, + HttpCode: http.StatusBadRequest, + Message: fmt.Sprintf("Too big sequence requested: max limit is %d entries", limit), + }, + } +} diff --git a/pkg/api/errors/basics.go b/pkg/api/errors/basics.go new file mode 100644 index 000000000..20a02d549 --- /dev/null +++ b/pkg/api/errors/basics.go @@ -0,0 +1,124 @@ +package errors + +import ( + "fmt" + "net/http" +) + +type Identifier interface { + IntCode() int +} + +// ApiError is a basic interface for node HTTP API. +// Type which implements this interface MUST be serializable to JSON. +type ApiError interface { + error + GetID() Identifier + GetName() string + GetHttpCode() int + GetMessage() string +} + +type ErrorID int +type ApiAuthErrorID ErrorID +type ValidationErrorID ErrorID +type TransactionErrorID ErrorID + +func (e ErrorID) IntCode() int { + return int(e) +} +func (e ApiAuthErrorID) IntCode() int { + return int(e) +} +func (e ValidationErrorID) IntCode() int { + return int(e) +} +func (e TransactionErrorID) IntCode() int { + return int(e) +} + +// generic error + +type genericError struct { + ID Identifier `json:"error"` + HttpCode int `json:"-"` + Message string `json:"message"` +} + +func (g *genericError) GetID() Identifier { + return g.ID +} + +func (g *genericError) GetName() string { + return errorNames[g.ID] +} + +func (g *genericError) GetHttpCode() int { + return g.HttpCode +} + +func (g *genericError) GetMessage() string { + return g.Message +} + +func (g *genericError) Error() string { + return fmt.Sprintf("%s #%d: %s", g.GetName(), g.ID.IntCode(), g.Message) +} + +// --generic error + +// UnknownError is a wrapper for any unknown internal error +type UnknownError struct { + genericError + inner error +} + +func (u *UnknownError) Unwrap() error { + return u.inner +} + +func (u *UnknownError) Error() string { + if u.Unwrap() != nil { + return fmt.Sprintf( + "%s; inner error (%T): %s", + u.genericError.Error(), + u.Unwrap(), u.Unwrap().Error(), + ) + } + return u.genericError.Error() +} + +func NewUnknownError(inner error) *UnknownError { + return NewUnknownErrorWithMsg("Error is unknown", inner) +} + +func NewUnknownErrorWithMsg(message string, inner error) *UnknownError { + return &UnknownError{ + genericError: genericError{ + ID: UnknownErrorID, + HttpCode: http.StatusInternalServerError, + Message: message, + }, + inner: inner, + } +} + +// --UnknownError + +type WrongJsonError struct { + genericError + Cause string `json:"cause,omitempty"` + ValidationErrors []error `json:"validationErrors,omitempty"` +} + +func NewWrongJsonError(cause string, validationErrors []error) *WrongJsonError { + return &WrongJsonError{ + genericError: genericError{ + ID: WrongJsonErrorID, + HttpCode: http.StatusBadRequest, + Message: "failed to parse json message", + }, + Cause: cause, + ValidationErrors: validationErrors, + } +} diff --git a/pkg/api/errors/basics_test.go b/pkg/api/errors/basics_test.go new file mode 100644 index 000000000..cc3d8e1d7 --- /dev/null +++ b/pkg/api/errors/basics_test.go @@ -0,0 +1,41 @@ +package errors + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestApiErrorWithSameIntID(t *testing.T) { + type testSample struct { + id Identifier + expectedName string + } + + testData := []struct { + first testSample + second testSample + }{ + { + testSample{InvalidNameErrorID, "InvalidNameError"}, + testSample{NegativeAmountErrorID, "NegativeAmountError"}, + }, + { + testSample{StateCheckFailedErrorID, "StateCheckFailedError"}, + testSample{InsufficientFeeErrorID, "InsufficientFeeError"}, + }, + { + testSample{ToSelfErrorID, "ToSelfError"}, + testSample{NegativeMinFeeErrorID, "NegativeMinFeeError"}, + }, + { + testSample{MissingSenderPrivateKeyErrorID, "MissingSenderPrivateKeyError"}, + testSample{NonPositiveAmountErrorID, "NonPositiveAmountError"}, + }, + } + + for _, sample := range testData { + assert.Equal(t, sample.first.id.IntCode(), sample.second.id.IntCode()) + assert.Equal(t, sample.first.expectedName, errorNames[sample.first.id]) + assert.Equal(t, sample.second.expectedName, errorNames[sample.second.id]) + } +} diff --git a/pkg/api/errors/consts.go b/pkg/api/errors/consts.go new file mode 100644 index 000000000..bca3f3219 --- /dev/null +++ b/pkg/api/errors/consts.go @@ -0,0 +1,97 @@ +package errors + +const ( + UnknownErrorID ErrorID = 0 + WrongJsonErrorID ErrorID = 1 +) + +//API Auth +const ( + ApiKeyNotValidErrorID ApiAuthErrorID = 2 + TooBigArrayAllocationErrorID ApiAuthErrorID = 10 +) + +//VALIDATION +const ( + InvalidSignatureErrorID ValidationErrorID = 101 + InvalidAddressErrorID ValidationErrorID = 102 + InvalidPublicKeyErrorID ValidationErrorID = 108 + InvalidMessageErrorID ValidationErrorID = 110 + InvalidNameErrorID ValidationErrorID = 111 + StateCheckFailedErrorID ValidationErrorID = 112 + OverflowErrorID ValidationErrorID = 113 + ToSelfErrorID ValidationErrorID = 114 + MissingSenderPrivateKeyErrorID ValidationErrorID = 115 + InvalidIdsErrorID ValidationErrorID = 116 + CustomValidationErrorErrorID ValidationErrorID = 199 + BlockDoesNotExistErrorID ValidationErrorID = 301 + AliasDoesNotExistErrorID ValidationErrorID = 302 + MistimingErrorID ValidationErrorID = 303 + DataKeyDoesNotExistErrorID ValidationErrorID = 304 + ScriptCompilerErrorID ValidationErrorID = 305 + ScriptExecutionErrorErrorID ValidationErrorID = 306 + TransactionNotAllowedByAccountScriptErrorID ValidationErrorID = 307 + TransactionNotAllowedByAssetScriptErrorID ValidationErrorID = 308 +) + +//TRANSACTIONS +const ( + TransactionDoesNotExistErrorID TransactionErrorID = 311 + UnsupportedTransactionTypeErrorID TransactionErrorID = 312 + AssetDoesNotExistErrorID TransactionErrorID = 313 + NegativeAmountErrorID TransactionErrorID = 111 + InsufficientFeeErrorID TransactionErrorID = 112 + NegativeMinFeeErrorID TransactionErrorID = 114 + NonPositiveAmountErrorID TransactionErrorID = 115 + AlreadyInStateErrorID TransactionErrorID = 400 + AccountBalanceErrorsErrorID TransactionErrorID = 402 + OrderInvalidErrorID TransactionErrorID = 403 + InvalidChainIdErrorID TransactionErrorID = 404 + InvalidProofsErrorID TransactionErrorID = 405 + InvalidTransactionIdErrorID TransactionErrorID = 4001 + InvalidBlockIdErrorID TransactionErrorID = 4002 + InvalidAssetIdErrorID TransactionErrorID = 4007 +) + +var errorNames = map[Identifier]string{ + UnknownErrorID: "UnknownError", + WrongJsonErrorID: "WrongJsonError", + + ApiKeyNotValidErrorID: "ApiKeyNotValidError", + TooBigArrayAllocationErrorID: "TooBigArrayAllocationError", + InvalidSignatureErrorID: "InvalidSignatureError", + InvalidAddressErrorID: "InvalidAddressError", + InvalidPublicKeyErrorID: "InvalidPublicKeyError", + InvalidMessageErrorID: "InvalidMessageError", + InvalidNameErrorID: "InvalidNameError", + StateCheckFailedErrorID: "StateCheckFailedError", + OverflowErrorID: "OverflowError", + ToSelfErrorID: "ToSelfError", + MissingSenderPrivateKeyErrorID: "MissingSenderPrivateKeyError", + InvalidIdsErrorID: "InvalidIdsError", + CustomValidationErrorErrorID: "CustomValidationErrorError", + BlockDoesNotExistErrorID: "BlockDoesNotExistError", + AliasDoesNotExistErrorID: "AliasDoesNotExistError", + MistimingErrorID: "MistimingError", + DataKeyDoesNotExistErrorID: "DataKeyDoesNotExistError", + ScriptCompilerErrorID: "ScriptCompilerError", + ScriptExecutionErrorErrorID: "ScriptExecutionErrorError", + TransactionNotAllowedByAccountScriptErrorID: "TransactionNotAllowedByAccountScriptError", + TransactionNotAllowedByAssetScriptErrorID: "TransactionNotAllowedByAssetScriptError", + + TransactionDoesNotExistErrorID: "TransactionDoesNotExistError", + UnsupportedTransactionTypeErrorID: "UnsupportedTransactionTypeError", + AssetDoesNotExistErrorID: "AssetDoesNotExistError", + NegativeAmountErrorID: "NegativeAmountError", + InsufficientFeeErrorID: "InsufficientFeeError", + NegativeMinFeeErrorID: "NegativeMinFeeError", + NonPositiveAmountErrorID: "NonPositiveAmountError", + AlreadyInStateErrorID: "AlreadyInStateError", + AccountBalanceErrorsErrorID: "AccountBalanceErrorsError", + OrderInvalidErrorID: "OrderInvalidError", + InvalidChainIdErrorID: "InvalidChainIdError", + InvalidProofsErrorID: "InvalidProofsError", + InvalidTransactionIdErrorID: "InvalidTransactionIdError", + InvalidBlockIdErrorID: "InvalidBlockIdError", + InvalidAssetIdErrorID: "InvalidAssetIdError", +} diff --git a/pkg/api/errors/transaction.go b/pkg/api/errors/transaction.go new file mode 100644 index 000000000..e30faf2d5 --- /dev/null +++ b/pkg/api/errors/transaction.go @@ -0,0 +1,71 @@ +package errors + +import ( + "github.com/wavesplatform/gowaves/pkg/proto" + "net/http" +) + +type transactionError struct { + genericError +} + +// TODO(nickeskov): IMPLEMENT ME +type order struct{} + +type ( + TransactionDoesNotExistError transactionError + UnsupportedTransactionTypeError transactionError + AssetDoesNotExistError transactionError + NegativeAmount transactionError + InsufficientFeeError transactionError + NegativeMinFeeError transactionError + NonPositiveAmountError transactionError + AlreadyInStateError transactionError + AccountBalanceErrorsError struct { + transactionError + Details map[proto.Address]string `json:"details"` + } + OrderInvalidError struct { + transactionError + Order order `json:"order"` + } + InvalidChainIdError transactionError + InvalidProofsError transactionError + InvalidTransactionIdError transactionError + InvalidBlockIdError transactionError + InvalidAssetIdError transactionError +) + +var ( + TransactionDoesNotExist = &TransactionDoesNotExistError{ + genericError: genericError{ + ID: TransactionDoesNotExistErrorID, + HttpCode: http.StatusNotFound, + Message: "transactions does not exist", + }, + } + UnsupportedTransactionType = &UnsupportedTransactionTypeError{ + genericError: genericError{ + ID: UnsupportedTransactionTypeErrorID, + HttpCode: http.StatusNotImplemented, + Message: "transaction type not supported", + }, + } + InvalidAssetId = &InvalidAssetIdError{ + genericError: genericError{ + ID: InvalidAssetIdErrorID, + HttpCode: http.StatusBadRequest, + Message: "Invalid asset id", + }, + } +) + +func NewInvalidBlockIDError(message string) *InvalidBlockIdError { + return &InvalidBlockIdError{ + genericError: genericError{ + ID: InvalidBlockIdErrorID, + HttpCode: http.StatusBadRequest, + Message: message, + }, + } +} diff --git a/pkg/api/errors/validation.go b/pkg/api/errors/validation.go new file mode 100644 index 000000000..dd3a59b6f --- /dev/null +++ b/pkg/api/errors/validation.go @@ -0,0 +1,154 @@ +package errors + +import ( + "encoding/json" + "github.com/pkg/errors" + "net/http" +) + +type validationError struct { + genericError +} + +// TODO(nickeskov): IMPLEMENT ME +type transaction interface{} + +type validationErrorWithTransaction struct { + validationError + Transaction transaction `json:"transaction,omitempty"` +} + +type ( + InvalidSignatureError validationError + InvalidAddressError validationError + InvalidPublicKeyError validationError + InvalidMessageError validationError + InvalidNameError validationError + StateCheckFailedError struct { + validationErrorWithTransaction + // TODO(nickeskov): implement more optimized way for fields embedding + // for converting any structs to map[string]interface{} + // in a convenient way use "github.com/mitchellh/mapstructure" + embeddedFields map[string]interface{} + } + OverflowError validationError + ToSelfError validationError + MissingSenderPrivateKeyError validationError + InvalidIdsError struct { + validationError + Ids []string `json:"ids"` + } + CustomValidationError validationError + BlockDoesNotExistError validationError + AliasDoesNotExistError validationError + MistimingError validationError + DataKeyDoesNotExistError validationError + ScriptCompilerError validationError + ScriptExecutionError validationErrorWithTransaction + TransactionNotAllowedByAccountScriptError validationErrorWithTransaction +) + +func (e *StateCheckFailedError) MarshalJSON() ([]byte, error) { + errorJson, err := json.Marshal(e.validationErrorWithTransaction) + if err != nil { + return nil, errors.Wrap(err, "StateCheckFailedError.MarshalJSON") + } + + if len(e.embeddedFields) == 0 { + return errorJson, nil + } + + embedded, err := json.Marshal(e.embeddedFields) + if err != nil { + return nil, errors.Wrap(err, "StateCheckFailedError.MarshalJSON") + } + + // nickeskov `{"extra":"somevalue"}` -> `"extra":"somevalue"` + extraFields := embedded[1 : len(embedded)-1] + + buffer := make([]byte, 0, len(errorJson)+len(extraFields)+1) + + // nickeskov: errorJson=`{"somekey":"somevalue"}`, buffer = `"{"somekey":"somevalue"` + buffer = append(buffer, errorJson[:len(errorJson)-1]...) + // buffer = `"{"somekey":"somevalue",` + buffer = append(buffer, ',') + // buffer = `"{"somekey":"somevalue","extra":"somevalue"` + buffer = append(buffer, extraFields...) + // buffer = `"{"somekey":"somevalue","extra":"somevalue"}` + buffer = append(buffer, '}') + + return buffer, nil +} + +var ( + InvalidSignature = &InvalidSignatureError{ + genericError: genericError{ + ID: InvalidSignatureErrorID, + HttpCode: http.StatusBadRequest, + Message: "invalid signature", + }, + } + InvalidAddress = &InvalidAddressError{ + genericError: genericError{ + ID: InvalidAddressErrorID, + HttpCode: http.StatusBadRequest, + Message: "invalid address", + }, + } + InvalidPublicKey = &InvalidPublicKeyError{ + genericError: genericError{ + ID: InvalidPublicKeyErrorID, + HttpCode: http.StatusBadRequest, + Message: "invalid public key", + }, + } + InvalidMessage = &InvalidMessageError{ + genericError: genericError{ + ID: InvalidMessageErrorID, + HttpCode: http.StatusBadRequest, + Message: "invalid message", + }, + } + InvalidName = &InvalidNameError{ + genericError: genericError{ + ID: InvalidNameErrorID, + HttpCode: http.StatusBadRequest, + Message: "invalid name", + }, + } + Overflow = &OverflowError{ + genericError: genericError{ + ID: OverflowErrorID, + HttpCode: http.StatusBadRequest, + Message: "overflow error", + }, + } + ToSelf = &ToSelfError{ + genericError: genericError{ + ID: ToSelfErrorID, + HttpCode: http.StatusBadRequest, + Message: "Transaction to yourself", + }, + } + MissingSenderPrivateKey = &MissingSenderPrivateKeyError{ + genericError: genericError{ + ID: MissingSenderPrivateKeyErrorID, + HttpCode: http.StatusBadRequest, + Message: "no private key for sender address in wallet", + }, + } + BlockDoesNotExist = &BlockDoesNotExistError{ + genericError: genericError{ + ID: BlockDoesNotExistErrorID, + HttpCode: http.StatusNotFound, + Message: "block does not exist", + }, + } + DataKeyDoesNotExist = &DataKeyDoesNotExistError{ + genericError: genericError{ + ID: DataKeyDoesNotExistErrorID, + HttpCode: http.StatusNotFound, + Message: "no data for this key", + }, + } +) diff --git a/pkg/api/errors/validation_test.go b/pkg/api/errors/validation_test.go new file mode 100644 index 000000000..8059cb3e6 --- /dev/null +++ b/pkg/api/errors/validation_test.go @@ -0,0 +1,39 @@ +package errors + +import ( + "encoding/json" + "github.com/stretchr/testify/assert" + "net/http" + "testing" +) + +func TestStateCheckFailedError_MarshalJSON(t *testing.T) { + value := StateCheckFailedError{ + validationErrorWithTransaction: validationErrorWithTransaction{ + validationError: validationError{ + genericError: genericError{ + ID: StateCheckFailedErrorID, + HttpCode: http.StatusBadRequest, + Message: "some message", + }, + }, + Transaction: nil, + }, + embeddedFields: map[string]interface{}{ + "extra_field": "value", + "extra_int": 1, + }, + } + + marshaled, err := value.MarshalJSON() + assert.NoError(t, err) + + var unmarshaled map[string]interface{} + err = json.Unmarshal(marshaled, &unmarshaled) + assert.NoError(t, err) + + assert.Equal(t, float64(StateCheckFailedErrorID), unmarshaled["error"].(float64)) + assert.Equal(t, "some message", unmarshaled["message"]) + assert.Equal(t, "value", unmarshaled["extra_field"]) + assert.Equal(t, float64(1), unmarshaled["extra_int"].(float64)) +} diff --git a/pkg/api/errors_test.go b/pkg/api/errors_test.go index 5d62b3e17..156c66fd1 100644 --- a/pkg/api/errors_test.go +++ b/pkg/api/errors_test.go @@ -15,8 +15,3 @@ func TestAuthError(t *testing.T) { err := AuthError{errors.New("bad auth")} require.Error(t, err) } - -func TestInternalError(t *testing.T) { - err := InternalError{errors.New("internal error")} - require.Error(t, err) -} diff --git a/pkg/api/helpers.go b/pkg/api/helpers.go new file mode 100644 index 000000000..4d7a52d64 --- /dev/null +++ b/pkg/api/helpers.go @@ -0,0 +1,7 @@ +package api + +import "time" + +func unixMillis(t time.Time) int64 { + return t.UnixNano() / 1_000_000 +} diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go new file mode 100644 index 000000000..69f9572a9 --- /dev/null +++ b/pkg/api/metrics.go @@ -0,0 +1,43 @@ +package api + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +const httpAPIMetricsNamespace = "http_api" + +var ( + metricApiTotalRequests = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: httpAPIMetricsNamespace, + Name: "total_hits", + Help: "Node HTTP API Requests count", + }, + ) + + metricApiHits = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: httpAPIMetricsNamespace, + Name: "path_hits", + Help: "Node HTTP API paths hits", + }, + []string{"status", "path"}, + ) + + metricApiRequestDuration = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: httpAPIMetricsNamespace, + Name: "path_duration", + // TODO(nickeskov): add custom buckets + }, + []string{"method", "path"}, + ) +) + +func init() { + prometheus.MustRegister( + metricApiTotalRequests, + metricApiHits, + metricApiRequestDuration, + ) +} diff --git a/pkg/api/middleware.go b/pkg/api/middleware.go new file mode 100644 index 000000000..e0c69f3c2 --- /dev/null +++ b/pkg/api/middleware.go @@ -0,0 +1,99 @@ +package api + +import ( + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "go.uber.org/zap" + "net/http" + "strconv" + "time" +) + +// CreateLoggerMiddleware creates a middleware that logs the start and end of each request, along +// with some useful data about what was requested, what the response status was, +// and how long it took to return. +func CreateLoggerMiddleware(l *zap.Logger) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + ww, ok := w.(middleware.WrapResponseWriter) + if !ok { + ww = middleware.NewWrapResponseWriter(w, r.ProtoMajor) + } + + t1 := time.Now() + defer func() { + l.Info("ServedHttpRequest", + zap.String("proto", r.Proto), + zap.String("path", r.URL.Path), + zap.Duration("lat", time.Since(t1)), + zap.Int("status", ww.Status()), + zap.Int("size", ww.BytesWritten()), + zap.String("request_id", middleware.GetReqID(r.Context()))) + }() + + next.ServeHTTP(ww, r) + } + return http.HandlerFunc(fn) + } +} + +func chiHttpApiGeneralMetricsMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + begin := time.Now() + + metricApiTotalRequests.Inc() + + ww, ok := w.(middleware.WrapResponseWriter) + if !ok { + ww = middleware.NewWrapResponseWriter(w, r.ProtoMajor) + } + + defer func() { + routePath := r.URL.Path + if chiRouteContext := chi.RouteContext(r.Context()); chiRouteContext != nil { + if updatedRoutePath := chiRouteContext.RoutePattern(); updatedRoutePath != "" { + routePath = updatedRoutePath + } + } + + statusCode := ww.Status() + metricApiHits.WithLabelValues(strconv.Itoa(statusCode), routePath).Inc() + + observer := metricApiRequestDuration.WithLabelValues(r.Method, routePath) + observer.Observe(time.Since(begin).Seconds()) + }() + + next.ServeHTTP(ww, r) + }) +} + +func CreateHeadersMiddleware(headers map[string]string) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for k, v := range headers { + w.Header().Set(k, v) + } + next.ServeHTTP(w, r) + }) + } +} + +func JsonContentTypeMiddleware(next http.Handler) http.Handler { + return CreateHeadersMiddleware(map[string]string{ + "Content-Type": "application/json", + })(next) +} + +func createCheckAuthMiddleware(app *App, errorHandler HandleErrorFunc) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + apiKey := r.Header.Get("X-API-Key") + err := app.checkAuth(apiKey) + if err != nil { + errorHandler(w, r, err) + } else { + next.ServeHTTP(w, r) + } + }) + } +} diff --git a/pkg/api/node_api.go b/pkg/api/node_api.go index 3c1ab86e1..8956f64ec 100644 --- a/pkg/api/node_api.go +++ b/pkg/api/node_api.go @@ -8,43 +8,18 @@ import ( "io/ioutil" "net/http" "strconv" - "time" - - "github.com/pkg/errors" "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/mr-tron/base58" + "github.com/pkg/errors" + apiErrs "github.com/wavesplatform/gowaves/pkg/api/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/node" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/state" "go.uber.org/zap" ) -// Logger is a middleware that logs the start and end of each request, along -// with some useful data about what was requested, what the response status was, -// and how long it took to return. -func Logger(l *zap.Logger) func(next http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) - - t1 := time.Now() - defer func() { - l.Info("Served", - zap.String("proto", r.Proto), - zap.String("path", r.URL.Path), - zap.Duration("lat", time.Since(t1)), - zap.Int("status", ww.Status()), - zap.Int("size", ww.BytesWritten()), - zap.String("reqId", middleware.GetReqID(r.Context()))) - }() - - next.ServeHTTP(ww, r) - } - return http.HandlerFunc(fn) - } -} - type NodeApi struct { state state.State node *node.Node @@ -59,145 +34,194 @@ func NewNodeApi(app *App, state state.State, node *node.Node) *NodeApi { } } -func (a *NodeApi) TransactionsBroadcast(w http.ResponseWriter, r *http.Request) { - defer func(body io.ReadCloser) { - err := body.Close() - if err != nil { - zap.S().Warnf("Failed to close body: %v", err) - } - }(r.Body) +func (a *NodeApi) TransactionsBroadcast(w http.ResponseWriter, r *http.Request) error { b, err := ioutil.ReadAll(r.Body) if err != nil { - handleError(w, &BadRequestError{err}) - return + return errors.Wrap(err, "TransactionsBroadcast: failed to read request body") } err = a.app.TransactionsBroadcast(r.Context(), b) if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "TransactionsBroadcast") } + return nil } -func (a *NodeApi) BlocksLast(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) BlocksLast(w http.ResponseWriter, _ *http.Request) error { block, err := a.app.BlocksLast() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "BlocksLast: failed to get last block") } bts, err := proto.BlockEncodeJson(block) if err != nil { - http.Error(w, fmt.Sprintf("Failed to marshal status to JSON: %s", err.Error()), http.StatusInternalServerError) - return + return errors.Wrap(err, "BlocksLast: failed to marshal block to JSON") } - _, _ = w.Write(bts) + if _, err = w.Write(bts); err != nil { + return errors.Wrap(err, "BlocksLast: failed to write block json to ResponseWriter") + } + return nil } -func (a *NodeApi) BlocksFirst(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) BlocksFirst(w http.ResponseWriter, _ *http.Request) error { block, err := a.state.BlockByHeight(1) if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "BlocksFirst") } block.Height = 1 bts, err := proto.BlockEncodeJson(block) if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "BlocksFirst: failed to marshal block to JSON") + } + if _, err = w.Write(bts); err != nil { + return errors.Wrap(err, "BlocksFirst: failed to write block json to ResponseWriter") } - _, _ = w.Write(bts) + return nil +} + +func blockIDAtInvalidLenErr(key string) *apiErrs.InvalidBlockIdError { + return apiErrs.NewInvalidBlockIDError( + fmt.Sprintf("%s has invalid length %d. Length can either be %d or %d", + key, // nickeskov: this part must be the last part of HTTP path + len(key), + crypto.DigestSize, + crypto.SignatureSize, + ), + ) } -func (a *NodeApi) BlockAt(w http.ResponseWriter, r *http.Request) { +func blockIDAtInvalidCharErr(invalidChar rune, id string) *apiErrs.InvalidBlockIdError { + return apiErrs.NewInvalidBlockIDError( + fmt.Sprintf( + "requirement failed: Wrong char %q in Base58 string '%s'", + invalidChar, + id, + ), + ) +} + +func (a *NodeApi) BlockAt(w http.ResponseWriter, r *http.Request) error { s := chi.URLParam(r, "height") id, err := strconv.ParseUint(s, 10, 64) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return + // nickeskov: message taken from scala node + // try execute `curl -X GET "https://nodes-testnet.wavesnodes.com/blocks/at/fdsfasdff" -H "accept: application/json"` + return blockIDAtInvalidLenErr("at") } block, err := a.state.BlockByHeight(id) if err != nil { - handleError(w, err) - return + origErr := errors.Cause(err) + if state.IsNotFound(origErr) { + // nickeskov: it's strange, but scala node sends empty response... + // try execute `curl -X GET "https://nodes-testnet.wavesnodes.com/blocks/at/0" -H "accept: application/json"` + return nil + } + return errors.Wrap(err, + "BlockAt: expected NotFound in state error, but received other error") } + block.Height = id err = json.NewEncoder(w).Encode(block) if err != nil { - handleError(w, err) - return + return errors.Wrap(err, + "BlockEncodeJson: failed to marshal block to JSON and write to ResponseWriter") } + return nil } -func (a *NodeApi) DebugSyncEnabled(w http.ResponseWriter, r *http.Request) { - s := chi.URLParam(r, "enabled") - id, err := strconv.ParseUint(s, 10, 64) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return +func findFirstInvalidRuneInBase58String(str string) *rune { + for _, r := range str { + if _, err := base58.Decode(string(r)); err != nil { + return &r + } } - a.app.DebugSyncEnabled(id == 1) + return nil } -func (a *NodeApi) BlockIDAt(w http.ResponseWriter, r *http.Request) { +func (a *NodeApi) BlockIDAt(w http.ResponseWriter, r *http.Request) error { + // nickeskov: in this case id param must be non zero length s := chi.URLParam(r, "id") id, err := proto.NewBlockIDFromBase58(s) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return + if invalidRune := findFirstInvalidRuneInBase58String(s); invalidRune != nil { + return blockIDAtInvalidCharErr(*invalidRune, s) + } + return blockIDAtInvalidLenErr(s) } block, err := a.state.Block(id) if err != nil { - handleError(w, err) - return + origErr := errors.Cause(err) + if state.IsNotFound(origErr) { + return apiErrs.BlockDoesNotExist + } + return errors.Wrapf(err, + "BlockIDAt: expected NotFound in state error, but received other error for blockID=%s", + s, + ) } + height, err := a.state.BlockIDToHeight(id) if err != nil { - handleError(w, err) - return + // TODO(nickeskov): should handle state.IsNotFound(...)? + return errors.Wrapf(err, + "BlockIDAt: failed to execute state.BlockIDToHeight for blockID=%s", s) } block.Height = height err = json.NewEncoder(w).Encode(block) if err != nil { - handleError(w, err) - return + return errors.Wrap(err, + "BlockIDAt: failed to marshal block to JSON and write to ResponseWriter") } + return nil } -type BlockHeightResponse struct { - Height uint64 `json:"height"` -} +func (a *NodeApi) BlockHeight(w http.ResponseWriter, _ *http.Request) error { + type blockHeightResponse struct { + Height uint64 `json:"height"` + } -func (a *NodeApi) BlockHeight(w http.ResponseWriter, _ *http.Request) { height, err := a.state.Height() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "BlockHeight: failed to bet blocks height") } - err = json.NewEncoder(w).Encode(&BlockHeightResponse{Height: height}) - if err != nil { - handleError(w, err) - return + + if err := trySendJson(w, blockHeightResponse{Height: height}); err != nil { + return errors.Wrap(err, "BlockHeight") } + return nil } -func (a *NodeApi) BlockScoreAt(w http.ResponseWriter, r *http.Request) { +// nickeskov: in scala node this route does not exist + +func (a *NodeApi) BlockScoreAt(w http.ResponseWriter, r *http.Request) error { s := chi.URLParam(r, "id") id, err := strconv.ParseUint(s, 10, 64) if err != nil { - handleError(w, &BadRequestError{err}) - return + // TODO(nickeskov): which error it should send? + return &BadRequestError{err} } rs, err := a.app.BlocksScoreAt(id) if err != nil { - handleError(w, err) - return + // TODO(nickeskov): which error it should send? + return errors.Wrapf(err, "failed get blocks score at for id %d", id) + } + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "BlockScoreAt") } - sendJson(w, rs) + return nil } -func Run(ctx context.Context, address string, n *NodeApi) error { - apiServer := &http.Server{Addr: address, Handler: n.routes()} +func RunWithOpts(ctx context.Context, address string, n *NodeApi, opts *RunOptions) error { + if opts == nil { + opts = DefaultRunOptions() + } + + routes, err := n.routes(opts) + if err != nil { + return errors.Wrap(err, "RunWithOpts") + } + + apiServer := &http.Server{Addr: address, Handler: routes} go func() { <-ctx.Done() zap.S().Info("Shutting down API...") @@ -206,25 +230,47 @@ func Run(ctx context.Context, address string, n *NodeApi) error { zap.S().Errorf("Failed to shutdown API server: %v", err) } }() - err := apiServer.ListenAndServe() + + err = apiServer.ListenAndServe() if err != nil && err != http.ErrServerClosed { return err } return nil } -func (a *NodeApi) PeersAll(w http.ResponseWriter, _ *http.Request) { +func Run(ctx context.Context, address string, n *NodeApi) error { + // TODO(nickeskov): add run flags in CLI flags + return RunWithOpts(ctx, address, n, nil) +} + +func (a *NodeApi) PeersAll(w http.ResponseWriter, _ *http.Request) error { rs, err := a.app.PeersAll() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "failed to fetch all peers") } - sendJson(w, rs) + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersAll") + } + return nil +} + +func (a *NodeApi) PeersKnown(w http.ResponseWriter, _ *http.Request) error { + rs, err := a.app.PeersKnown() + if err != nil { + return errors.Wrap(err, "failed to fetch known peers") + } + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersKnown") + } + return nil } -func (a *NodeApi) PeersSpawned(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) PeersSpawned(w http.ResponseWriter, _ *http.Request) error { rs := a.app.PeersSpawned() - sendJson(w, rs) + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersSpawned") + } + return nil } type PeersConnectRequest struct { @@ -232,58 +278,78 @@ type PeersConnectRequest struct { Port uint16 `json:"port"` } -func (a *NodeApi) PeersConnect(w http.ResponseWriter, r *http.Request) { - req := new(PeersConnectRequest) - err := json.NewDecoder(r.Body).Decode(req) - if err != nil { - handleError(w, err) - return +func (a *NodeApi) PeersConnect(w http.ResponseWriter, r *http.Request) error { + req := &PeersConnectRequest{} + if err := tryParseJson(r.Body, req); err != nil { + return errors.Wrap(err, "failed to parse PeersConnect request body as JSON") } + // TODO(nickeskov): remove this and use auth middleware apiKey := r.Header.Get("X-API-Key") - rs, err := a.app.PeersConnect(r.Context(), apiKey, fmt.Sprintf("%s:%d", req.Host, req.Port)) + addr := fmt.Sprintf("%s:%d", req.Host, req.Port) + rs, err := a.app.PeersConnect(r.Context(), apiKey, addr) if err != nil { - handleError(w, err) - return + return errors.Wrapf(err, "failed to connect to new peer, addr %s", addr) } - sendJson(w, rs) + + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersConnect") + } + return nil } -func (a *NodeApi) PeersConnected(w http.ResponseWriter, _ *http.Request) { - rs, err := a.app.PeersConnected() - if err != nil { - handleError(w, err) - return +func (a *NodeApi) PeersConnected(w http.ResponseWriter, _ *http.Request) error { + rs := a.app.PeersConnected() + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersConnected") } - sendJson(w, rs) + return nil } -func (a *NodeApi) PeersSuspended(w http.ResponseWriter, _ *http.Request) { - rs, err := a.app.PeersSuspended() - if err != nil { - handleError(w, err) - return +func (a *NodeApi) PeersSuspended(w http.ResponseWriter, _ *http.Request) error { + rs := a.app.PeersSuspended() + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "PeersSuspended") } - sendJson(w, rs) + return nil } -func (a *NodeApi) BlocksGenerators(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) BlocksGenerators(w http.ResponseWriter, _ *http.Request) error { rs, err := a.app.BlocksGenerators() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "failed to get BlocksGenerators") } - sendJson(w, rs) + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "BlocksGenerators") + } + return nil } -func (a *NodeApi) poolTransactions(w http.ResponseWriter, _ *http.Request) { - rs := a.app.PoolTransactions() - sendJson(w, rs) +func (a *NodeApi) poolTransactions(w http.ResponseWriter, _ *http.Request) error { + type poolTransactions struct { + Count int `json:"count"` + } + + rs := poolTransactions{ + Count: a.app.PoolTransactions(), + } + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "poolTransactions") + } + return nil } -func (a *NodeApi) unconfirmedSize(w http.ResponseWriter, _ *http.Request) { - sendJson(w, map[string]int{ - "size": a.app.PoolTransactions(), - }) +func (a *NodeApi) unconfirmedSize(w http.ResponseWriter, _ *http.Request) error { + type unconfirmedSize struct { + Size int `json:"size"` + } + + rs := unconfirmedSize{ + Size: a.app.PoolTransactions(), + } + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "unconfirmedSize") + } + return nil } type rollbackRequest struct { @@ -294,21 +360,22 @@ type rollbackToHeight interface { RollbackToHeight(string, proto.Height) error } -func RollbackToHeight(app rollbackToHeight) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - js := &rollbackRequest{} - err := json.NewDecoder(r.Body).Decode(js) - if err != nil { - handleError(w, err) - return +func RollbackToHeight(app rollbackToHeight) HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + rollbackReq := &rollbackRequest{} + if err := tryParseJson(r.Body, rollbackReq); err != nil { + return errors.Wrap(err, "failed to parse RollbackToHeight body as JSON") } + // TODO(nickeskov): remove this and use auth middleware apiKey := r.Header.Get("X-API-Key") - err = app.RollbackToHeight(apiKey, js.Height) - if err != nil { - handleError(w, err) - return + if err := app.RollbackToHeight(apiKey, rollbackReq.Height); err != nil { + return errors.Wrapf(err, "failed to rollback to height %d", rollbackReq.Height) + } + // TODO(nickeskov): looks like bug... + if err := trySendJson(w, nil); err != nil { + return errors.Wrap(err, "RollbackToHeight") } - sendJson(w, nil) + return nil } } @@ -320,81 +387,91 @@ type walletLoadKeys interface { LoadKeys(apiKey string, password []byte) error } -func WalletLoadKeys(app walletLoadKeys) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { +func WalletLoadKeys(app walletLoadKeys) HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { js := &walletLoadKeysRequest{} - err := json.NewDecoder(r.Body).Decode(js) - if err != nil { - handleError(w, err) - return + if err := tryParseJson(r.Body, js); err != nil { + return errors.Wrap(err, "failed to parse WalletLoadKeys body as JSON") } + // TODO(nickeskov): remove this and use auth middleware apiKey := r.Header.Get("X-API-Key") - err = app.LoadKeys(apiKey, []byte(js.Password)) - if err != nil { - handleError(w, err) - return + if err := app.LoadKeys(apiKey, []byte(js.Password)); err != nil { + return errors.Wrap(err, "failed to execute LoadKeys") } - sendJson(w, nil) + return nil } } -func (a *NodeApi) WalletAccounts(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) WalletAccounts(w http.ResponseWriter, _ *http.Request) error { rs, err := a.app.Accounts() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "failed to get Accounts") + } + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "WalletAccounts") } - sendJson(w, rs) + return nil } -func (a *NodeApi) MinerInfo(w http.ResponseWriter, _ *http.Request) { - rs, err := a.app.Miner() +func (a *NodeApi) GoMinerInfo(w http.ResponseWriter, _ *http.Request) error { + rs := a.app.Miner() + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "GoMinerInfo") + } + return nil +} + +func (a *NodeApi) Addresses(w http.ResponseWriter, _ *http.Request) error { + addresses, err := a.app.Addresses() if err != nil { - handleError(w, err) - return + return errors.Wrap(err, "failed to get Addresses") + } + if err := trySendJson(w, addresses); err != nil { + return errors.Wrap(err, "Addresses") } - sendJson(w, rs) + return nil } -func (a *NodeApi) nodeProcesses(w http.ResponseWriter, _ *http.Request) { +func (a *NodeApi) nodeProcesses(w http.ResponseWriter, _ *http.Request) error { rs := a.app.NodeProcesses() - sendJson(w, rs) + if err := trySendJson(w, rs); err != nil { + return errors.Wrap(err, "nodeProcesses") + } + return nil } -func (a *NodeApi) stateHash(w http.ResponseWriter, r *http.Request) { +func (a *NodeApi) stateHash(w http.ResponseWriter, r *http.Request) error { s := chi.URLParam(r, "height") height, err := strconv.ParseUint(s, 10, 64) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return + // TODO(nickeskov): which error it should send? + return &BadRequestError{err} } stateHash, err := a.state.StateHashAtHeight(height) if err != nil { - handleError(w, err) - return + return errors.Wrapf(err, "failed to get state hash at height %d", height) } - err = json.NewEncoder(w).Encode(stateHash) - if err != nil { - handleError(w, err) - return + if err := trySendJson(w, stateHash); err != nil { + return errors.Wrap(err, "stateHash") } + return nil } -func handleError(w http.ResponseWriter, err error) { - switch err.(type) { - case *AuthError: - http.Error(w, fmt.Sprintf("Failed to complete request: %s", err.Error()), http.StatusForbidden) - case *BadRequestError: - http.Error(w, fmt.Sprintf("Failed to complete request: %s", err.Error()), http.StatusBadRequest) - default: - http.Error(w, fmt.Sprintf("Failed to complete request: %s", err.Error()), http.StatusInternalServerError) +// tryParseJson receives reader and out params. out MUST be a pointer +func tryParseJson(r io.Reader, out interface{}) error { + // TODO(nickeskov): check empty reader + err := json.NewDecoder(r).Decode(out) + if err != nil { + return errors.Wrapf(err, "Failed to unmarshal %T as JSON into %T", r, out) } + return nil } -func sendJson(w http.ResponseWriter, v interface{}) { +func trySendJson(w io.Writer, v interface{}) error { err := json.NewEncoder(w).Encode(v) if err != nil { - http.Error(w, fmt.Sprintf("Failed to marshal status to JSON: %s", err.Error()), http.StatusInternalServerError) + return errors.Wrapf(err, "Failed to marshal %T to JSON and write it to %T", v, w) } + return nil } diff --git a/pkg/api/node_api_test.go b/pkg/api/node_api_test.go index baa3de1fe..36e0d47b5 100644 --- a/pkg/api/node_api_test.go +++ b/pkg/api/node_api_test.go @@ -28,7 +28,8 @@ func TestRollbackToHeight(t *testing.T) { req := httptest.NewRequest("POST", "/blocks/rollback", strings.NewReader(`{"height": 100500}`)) req.Header.Add(apiKey, "apikey") resp := httptest.NewRecorder() - f(resp, req) + err := f(resp, req) + assert.NoError(t, err) assert.Equal(t, "apikey", r.apiKey) assert.EqualValues(t, 100500, r.height) @@ -52,8 +53,29 @@ func TestWalletLoadKeys(t *testing.T) { req := httptest.NewRequest("POST", "/wallet/load", strings.NewReader(`{"password": "password"}`)) req.Header.Add(apiKey, "apikey") resp := httptest.NewRecorder() - f(resp, req) + err := f(resp, req) + assert.NoError(t, err) assert.Equal(t, "apikey", r.apiKey) assert.EqualValues(t, "password", r.password) } + +func TestNodeApi_FindFirstInvalidRuneInBase58String(t *testing.T) { + invalidData := []struct { + str string + expected rune + }{ + {"234234😀$32@", '😀'}, + {"234234$32@", '$'}, + {"2@3423432", '@'}, + } + + for _, testCase := range invalidData { + actual := findFirstInvalidRuneInBase58String(testCase.str) + assert.NotNil(t, actual) + assert.Equal(t, testCase.expected, *actual) + } + + actual := findFirstInvalidRuneInBase58String("42354") + assert.Nil(t, actual) +} diff --git a/pkg/api/rate_limiter.go b/pkg/api/rate_limiter.go new file mode 100644 index 000000000..17f0a8eaa --- /dev/null +++ b/pkg/api/rate_limiter.go @@ -0,0 +1,39 @@ +package api + +import ( + "github.com/pkg/errors" + "github.com/throttled/throttled/v2" + "github.com/throttled/throttled/v2/store/memstore" +) + +func createRateLimiter(opts *RateLimiterOptions) (throttled.HTTPRateLimiter, error) { + store, err := memstore.New(opts.MemoryCacheSize) + if err != nil { + return throttled.HTTPRateLimiter{}, + errors.Wrapf( + err, + "createRateLimiter: failed to create memstore with capacity %d", + opts.MemoryCacheSize, + ) + } + + quota := throttled.RateQuota{ + MaxRate: throttled.PerSec(opts.MaxRequestsPerSecond), + MaxBurst: opts.MaxBurst, + } + + rateLimiter, err := throttled.NewGCRARateLimiter(store, quota) + if err != nil { + return throttled.HTTPRateLimiter{}, + errors.Wrap(err, "createRateLimiter: can't create rate limiter") + } + + httpRateLimiter := throttled.HTTPRateLimiter{ + RateLimiter: rateLimiter, + VaryBy: &throttled.VaryBy{ + RemoteAddr: true, + }, + } + + return httpRateLimiter, nil +} diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 110dd9d2e..c8e425f37 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -1,50 +1,135 @@ package api import ( - "io/ioutil" - "net/http" - "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "github.com/pkg/errors" "go.uber.org/zap" + "net/http" ) -func (a *NodeApi) routes() chi.Router { +type HandleErrorFunc func(w http.ResponseWriter, r *http.Request, err error) +type HandlerFunc func(w http.ResponseWriter, r *http.Request) error + +func toHTTPHandlerFunc(handler HandlerFunc, errorHandler HandleErrorFunc) http.HandlerFunc { + return func(writer http.ResponseWriter, request *http.Request) { + err := handler(writer, request) + if err != nil { + errorHandler(writer, request, err) + } + } +} + +func (a *NodeApi) routes(opts *RunOptions) (chi.Router, error) { r := chi.NewRouter() - r.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - zap.S().Debugf("NodeApi not found %+v, %s", r, r.URL.Path) - if r.Method == "POST" { - rs, err := ioutil.ReadAll(r.Body) - zap.S().Debugf("NodeApi not found post body: %s %+v", string(rs), err) + + if opts.UseRealIPMiddleware { + // nickeskov: for nginx/haproxy specific headers + r.Use(middleware.RealIP) + } + if opts.CollectMetrics { + r.Use(chiHttpApiGeneralMetricsMiddleware) + } + if opts.RateLimiterOpts != nil { + rateLimiter, err := createRateLimiter(opts.RateLimiterOpts) + if err != nil { + return nil, errors.WithStack(err) } - w.WriteHeader(http.StatusNotFound) - })) - r.Get("/blocks/last", a.BlocksLast) - r.Get("/blocks/height", a.BlockHeight) - r.Get("/blocks/first", a.BlocksFirst) - r.Get("/blocks/at/{height:\\d+}", a.BlockAt) - r.Get("/blocks/score/at/{id:\\d+}", a.BlockScoreAt) - r.Get("/blocks/id/{id}", a.BlockIDAt) - r.Get("/blocks/generators", a.BlocksGenerators) - r.Post("/blocks/rollback", RollbackToHeight(a.app)) - r.Get("/pool/transactions", a.poolTransactions) - r.Get("/transactions/unconfirmed/size", a.unconfirmedSize) - r.Route("/peers", func(r chi.Router) { - r.Get("/known", a.PeersAll) - r.Get("/connected", a.PeersConnected) - r.Post("/connect", a.PeersConnect) - r.Get("/suspended", a.PeersSuspended) - r.Get("/spawned", a.PeersSpawned) + r.Use(rateLimiter.RateLimit) + } + if opts.LogHttpRequestOpts { + r.Use(middleware.RequestID, CreateLoggerMiddleware(zap.L())) + } + if opts.RouteNotFoundHandler != nil { + r.NotFound(opts.RouteNotFoundHandler) + } + + // nickeskov: middlewares and custom handlers + errHandler := NewErrorHandler(zap.L()) + checkAuthMiddleware := createCheckAuthMiddleware(a.app, errHandler.Handle) + + wrapper := func(handlerFunc HandlerFunc) http.HandlerFunc { + return toHTTPHandlerFunc(handlerFunc, errHandler.Handle) + } + + if opts.EnableHeartbeatRoute { + r.Get("/go/node/healthz", func(w http.ResponseWriter, r *http.Request) { + if _, err := w.Write([]byte("OK")); err != nil { + zap.S().Errorf("Can't write 'OK' to ResponseWriter: %+v", err) + w.WriteHeader(http.StatusInternalServerError) + } + }) + } + + // nickeskov: go node routes + r.Route("/go", func(r chi.Router) { + r.Route("/blocks", func(r chi.Router) { + r.Get("/score/at/{id:\\d+}", wrapper(a.BlockScoreAt)) + r.Get("/id/{id}", wrapper(a.BlockIDAt)) + r.Get("/generators", wrapper(a.BlocksGenerators)) + + rAuth := r.With(checkAuthMiddleware) + + rAuth.Post("/rollback", wrapper(RollbackToHeight(a.app))) + }) + + r.Route("/peers", func(r chi.Router) { + r.Get("/known", wrapper(a.PeersKnown)) + r.Get("/spawned", wrapper(a.PeersSpawned)) + }) + + r.Route("/wallet", func(r chi.Router) { + r.Get("/accounts", wrapper(a.WalletAccounts)) + + rAuth := r.With(checkAuthMiddleware) + + rAuth.Post("/load", wrapper(WalletLoadKeys(a.app))) + }) + + r.Get("/miner/info", wrapper(a.GoMinerInfo)) + r.Get("/node/processes", wrapper(a.nodeProcesses)) + r.Get("/pool/transactions", wrapper(a.poolTransactions)) }) - r.Get("/miner/info", a.MinerInfo) - r.Post("/transactions/broadcast", a.TransactionsBroadcast) - r.Post("/wallet/load", WalletLoadKeys(a.app)) - r.Get("/wallet/accounts", a.WalletAccounts) + // nickeskov: json api + r.Group(func(r chi.Router) { + r.Route("/blocks", func(r chi.Router) { + r.Get("/last", wrapper(a.BlocksLast)) + r.Get("/height", wrapper(a.BlockHeight)) + r.Get("/first", wrapper(a.BlocksFirst)) + r.Get("/at/{height}", wrapper(a.BlockAt)) + r.Get("/{id}", wrapper(a.BlockIDAt)) + }) + + r.Route("/addresses", func(r chi.Router) { + r.Get("/", wrapper(a.Addresses)) + }) + + r.Route("/transactions", func(r chi.Router) { + r.Get("/unconfirmed/size", wrapper(a.unconfirmedSize)) - r.Get("/node/processes", a.nodeProcesses) - r.Get("/debug/stateHash/{height:\\d+}", a.stateHash) - // enable or disable history sync - //r.Get("/debug/sync/{enabled:\\d+}", a.DebugSyncEnabled) + rAuth := r.With(checkAuthMiddleware) + + rAuth.Post("/broadcast", wrapper(a.TransactionsBroadcast)) + }) + + r.Route("/peers", func(r chi.Router) { + r.Get("/all", wrapper(a.PeersAll)) + r.Get("/connected", wrapper(a.PeersConnected)) + r.Get("/suspended", wrapper(a.PeersSuspended)) + + rAuth := r.With(checkAuthMiddleware) + + rAuth.Post("/connect", wrapper(a.PeersConnect)) + }) + + r.Route("/debug", func(r chi.Router) { + r.Get("/stateHash/{height:\\d+}", wrapper(a.stateHash)) + }) + + // enable or disable history sync + //r.Get("/debug/sync/{enabled:\\d+}", a.DebugSyncEnabled) + }) - return r + return r, nil } diff --git a/pkg/api/settings.go b/pkg/api/settings.go index 778f64ec1..3322c502e 100644 --- a/pkg/api/settings.go +++ b/pkg/api/settings.go @@ -1 +1,47 @@ package api + +import ( + "go.uber.org/zap" + "io/ioutil" + "net/http" +) + +//const ( +// rateLimiterMemoryCacheSize = 65_536 +// rateLimiterMaxRequestsPerSecond = 100 +// rateLimiterMaxBurst = 5 +//) + +type RunOptions struct { + RateLimiterOpts *RateLimiterOptions + LogHttpRequestOpts bool + CollectMetrics bool + UseRealIPMiddleware bool + EnableHeartbeatRoute bool + RouteNotFoundHandler func(w http.ResponseWriter, r *http.Request) +} + +type RateLimiterOptions struct { + MemoryCacheSize int + MaxRequestsPerSecond int + MaxBurst int +} + +func DefaultRunOptions() *RunOptions { + return &RunOptions{ + RateLimiterOpts: nil, + LogHttpRequestOpts: false, + EnableHeartbeatRoute: true, + UseRealIPMiddleware: true, + CollectMetrics: true, + RouteNotFoundHandler: func(w http.ResponseWriter, r *http.Request) { + zap.S().Debugf("NodeApi not found %+v, %s", r, r.URL.Path) + if r.Method == http.MethodPost { + // TODO(nickeskov): it looks vulnerable (memory overflow) + rs, err := ioutil.ReadAll(r.Body) + zap.S().Debugf("NodeApi not found post body: %s %+v", string(rs), err) + } + w.WriteHeader(http.StatusNotFound) + }, + } +} diff --git a/pkg/mock/peer_manager.go b/pkg/mock/peer_manager.go index 60a069743..a2ba7dcb0 100644 --- a/pkg/mock/peer_manager.go +++ b/pkg/mock/peer_manager.go @@ -6,67 +6,106 @@ package mock import ( context "context" - gomock "github.com/golang/mock/gomock" - peer "github.com/wavesplatform/gowaves/pkg/p2p/peer" - proto "github.com/wavesplatform/gowaves/pkg/proto" big "math/big" net "net" reflect "reflect" + time "time" + + gomock "github.com/golang/mock/gomock" + storage "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + peer "github.com/wavesplatform/gowaves/pkg/p2p/peer" + proto "github.com/wavesplatform/gowaves/pkg/proto" ) -// MockPeerManager is a mock of PeerManager interface +// MockPeerManager is a mock of PeerManager interface. type MockPeerManager struct { ctrl *gomock.Controller recorder *MockPeerManagerMockRecorder } -// MockPeerManagerMockRecorder is the mock recorder for MockPeerManager +// MockPeerManagerMockRecorder is the mock recorder for MockPeerManager. type MockPeerManagerMockRecorder struct { mock *MockPeerManager } -// NewMockPeerManager creates a new mock instance +// NewMockPeerManager creates a new mock instance. func NewMockPeerManager(ctrl *gomock.Controller) *MockPeerManager { mock := &MockPeerManager{ctrl: ctrl} mock.recorder = &MockPeerManagerMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockPeerManager) EXPECT() *MockPeerManagerMockRecorder { return m.recorder } -// Connected mocks base method -func (m *MockPeerManager) Connected(arg0 peer.Peer) (peer.Peer, bool) { +// AddConnected mocks base method. +func (m *MockPeerManager) AddConnected(arg0 peer.Peer) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Connected", arg0) - ret0, _ := ret[0].(peer.Peer) - ret1, _ := ret[1].(bool) - return ret0, ret1 + m.ctrl.Call(m, "AddConnected", arg0) } -// Connected indicates an expected call of Connected -func (mr *MockPeerManagerMockRecorder) Connected(arg0 interface{}) *gomock.Call { +// AddConnected indicates an expected call of AddConnected. +func (mr *MockPeerManagerMockRecorder) AddConnected(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*MockPeerManager)(nil).Connected), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddConnected", reflect.TypeOf((*MockPeerManager)(nil).AddConnected), arg0) } -// NewConnection mocks base method -func (m *MockPeerManager) NewConnection(arg0 peer.Peer) error { +// AskPeers mocks base method. +func (m *MockPeerManager) AskPeers() { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewConnection", arg0) + m.ctrl.Call(m, "AskPeers") +} + +// AskPeers indicates an expected call of AskPeers. +func (mr *MockPeerManagerMockRecorder) AskPeers() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskPeers", reflect.TypeOf((*MockPeerManager)(nil).AskPeers)) +} + +// Close mocks base method. +func (m *MockPeerManager) Close() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Close") +} + +// Close indicates an expected call of Close. +func (mr *MockPeerManagerMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockPeerManager)(nil).Close)) +} + +// Connect mocks base method. +func (m *MockPeerManager) Connect(arg0 context.Context, arg1 proto.TCPAddr) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Connect", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// NewConnection indicates an expected call of NewConnection -func (mr *MockPeerManagerMockRecorder) NewConnection(arg0 interface{}) *gomock.Call { +// Connect indicates an expected call of Connect. +func (mr *MockPeerManagerMockRecorder) Connect(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewConnection", reflect.TypeOf((*MockPeerManager)(nil).NewConnection), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connect", reflect.TypeOf((*MockPeerManager)(nil).Connect), arg0, arg1) } -// ConnectedCount mocks base method +// Connected mocks base method. +func (m *MockPeerManager) Connected(arg0 peer.Peer) (peer.Peer, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Connected", arg0) + ret0, _ := ret[0].(peer.Peer) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// Connected indicates an expected call of Connected. +func (mr *MockPeerManagerMockRecorder) Connected(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*MockPeerManager)(nil).Connected), arg0) +} + +// ConnectedCount mocks base method. func (m *MockPeerManager) ConnectedCount() int { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ConnectedCount") @@ -74,92 +113,94 @@ func (m *MockPeerManager) ConnectedCount() int { return ret0 } -// ConnectedCount indicates an expected call of ConnectedCount +// ConnectedCount indicates an expected call of ConnectedCount. func (mr *MockPeerManagerMockRecorder) ConnectedCount() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConnectedCount", reflect.TypeOf((*MockPeerManager)(nil).ConnectedCount)) } -// InOutCount mocks base method -func (m *MockPeerManager) InOutCount() (int, int) { +// Disconnect mocks base method. +func (m *MockPeerManager) Disconnect(arg0 peer.Peer) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InOutCount") - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(int) - return ret0, ret1 + m.ctrl.Call(m, "Disconnect", arg0) } -// InOutCount indicates an expected call of InOutCount -func (mr *MockPeerManagerMockRecorder) InOutCount() *gomock.Call { +// Disconnect indicates an expected call of Disconnect. +func (mr *MockPeerManagerMockRecorder) Disconnect(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InOutCount", reflect.TypeOf((*MockPeerManager)(nil).InOutCount)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Disconnect", reflect.TypeOf((*MockPeerManager)(nil).Disconnect), arg0) } -// EachConnected mocks base method +// EachConnected mocks base method. func (m *MockPeerManager) EachConnected(arg0 func(peer.Peer, *proto.Score)) { m.ctrl.T.Helper() m.ctrl.Call(m, "EachConnected", arg0) } -// EachConnected indicates an expected call of EachConnected +// EachConnected indicates an expected call of EachConnected. func (mr *MockPeerManagerMockRecorder) EachConnected(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EachConnected", reflect.TypeOf((*MockPeerManager)(nil).EachConnected), arg0) } -// IsSuspended mocks base method -func (m *MockPeerManager) IsSuspended(arg0 peer.Peer) bool { +// InOutCount mocks base method. +func (m *MockPeerManager) InOutCount() (int, int) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsSuspended", arg0) - ret0, _ := ret[0].(bool) - return ret0 + ret := m.ctrl.Call(m, "InOutCount") + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(int) + return ret0, ret1 } -// IsSuspended indicates an expected call of IsSuspended -func (mr *MockPeerManagerMockRecorder) IsSuspended(arg0 interface{}) *gomock.Call { +// InOutCount indicates an expected call of InOutCount. +func (mr *MockPeerManagerMockRecorder) InOutCount() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSuspended", reflect.TypeOf((*MockPeerManager)(nil).IsSuspended), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InOutCount", reflect.TypeOf((*MockPeerManager)(nil).InOutCount)) } -// Suspend mocks base method -func (m *MockPeerManager) Suspend(arg0 peer.Peer, arg1 string) { +// IsSuspended mocks base method. +func (m *MockPeerManager) IsSuspended(arg0 peer.Peer) bool { m.ctrl.T.Helper() - m.ctrl.Call(m, "Suspend", arg0, arg1) + ret := m.ctrl.Call(m, "IsSuspended", arg0) + ret0, _ := ret[0].(bool) + return ret0 } -// Suspend indicates an expected call of Suspend -func (mr *MockPeerManagerMockRecorder) Suspend(arg0, arg1 interface{}) *gomock.Call { +// IsSuspended indicates an expected call of IsSuspended. +func (mr *MockPeerManagerMockRecorder) IsSuspended(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Suspend", reflect.TypeOf((*MockPeerManager)(nil).Suspend), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSuspended", reflect.TypeOf((*MockPeerManager)(nil).IsSuspended), arg0) } -// Suspended mocks base method -func (m *MockPeerManager) Suspended() []string { +// KnownPeers mocks base method. +func (m *MockPeerManager) KnownPeers() []storage.KnownPeer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Suspended") - ret0, _ := ret[0].([]string) + ret := m.ctrl.Call(m, "KnownPeers") + ret0, _ := ret[0].([]storage.KnownPeer) return ret0 } -// Suspended indicates an expected call of Suspended -func (mr *MockPeerManagerMockRecorder) Suspended() *gomock.Call { +// KnownPeers indicates an expected call of KnownPeers. +func (mr *MockPeerManagerMockRecorder) KnownPeers() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Suspended", reflect.TypeOf((*MockPeerManager)(nil).Suspended)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KnownPeers", reflect.TypeOf((*MockPeerManager)(nil).KnownPeers)) } -// AddConnected mocks base method -func (m *MockPeerManager) AddConnected(arg0 peer.Peer) { +// NewConnection mocks base method. +func (m *MockPeerManager) NewConnection(arg0 peer.Peer) error { m.ctrl.T.Helper() - m.ctrl.Call(m, "AddConnected", arg0) + ret := m.ctrl.Call(m, "NewConnection", arg0) + ret0, _ := ret[0].(error) + return ret0 } -// AddConnected indicates an expected call of AddConnected -func (mr *MockPeerManagerMockRecorder) AddConnected(arg0 interface{}) *gomock.Call { +// NewConnection indicates an expected call of NewConnection. +func (mr *MockPeerManagerMockRecorder) NewConnection(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddConnected", reflect.TypeOf((*MockPeerManager)(nil).AddConnected), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewConnection", reflect.TypeOf((*MockPeerManager)(nil).NewConnection), arg0) } -// PeerWithHighestScore mocks base method +// PeerWithHighestScore mocks base method. func (m *MockPeerManager) PeerWithHighestScore() (peer.Peer, *big.Int, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PeerWithHighestScore") @@ -169,94 +210,54 @@ func (m *MockPeerManager) PeerWithHighestScore() (peer.Peer, *big.Int, bool) { return ret0, ret1, ret2 } -// PeerWithHighestScore indicates an expected call of PeerWithHighestScore +// PeerWithHighestScore indicates an expected call of PeerWithHighestScore. func (mr *MockPeerManagerMockRecorder) PeerWithHighestScore() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerWithHighestScore", reflect.TypeOf((*MockPeerManager)(nil).PeerWithHighestScore)) } -// UpdateScore mocks base method -func (m *MockPeerManager) UpdateScore(p peer.Peer, score *proto.Score) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateScore", p, score) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateScore indicates an expected call of UpdateScore -func (mr *MockPeerManagerMockRecorder) UpdateScore(p, score interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateScore", reflect.TypeOf((*MockPeerManager)(nil).UpdateScore), p, score) -} - -// UpdateKnownPeers mocks base method -func (m *MockPeerManager) UpdateKnownPeers(arg0 []proto.TCPAddr) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateKnownPeers", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateKnownPeers indicates an expected call of UpdateKnownPeers -func (mr *MockPeerManagerMockRecorder) UpdateKnownPeers(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateKnownPeers", reflect.TypeOf((*MockPeerManager)(nil).UpdateKnownPeers), arg0) -} - -// KnownPeers mocks base method -func (m *MockPeerManager) KnownPeers() ([]proto.TCPAddr, error) { +// Score mocks base method. +func (m *MockPeerManager) Score(p peer.Peer) (*proto.Score, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "KnownPeers") - ret0, _ := ret[0].([]proto.TCPAddr) + ret := m.ctrl.Call(m, "Score", p) + ret0, _ := ret[0].(*proto.Score) ret1, _ := ret[1].(error) return ret0, ret1 } -// KnownPeers indicates an expected call of KnownPeers -func (mr *MockPeerManagerMockRecorder) KnownPeers() *gomock.Call { +// Score indicates an expected call of Score. +func (mr *MockPeerManagerMockRecorder) Score(p interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KnownPeers", reflect.TypeOf((*MockPeerManager)(nil).KnownPeers)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Score", reflect.TypeOf((*MockPeerManager)(nil).Score), p) } -// Close mocks base method -func (m *MockPeerManager) Close() { +// SpawnIncomingConnection mocks base method. +func (m *MockPeerManager) SpawnIncomingConnection(ctx context.Context, conn net.Conn) error { m.ctrl.T.Helper() - m.ctrl.Call(m, "Close") + ret := m.ctrl.Call(m, "SpawnIncomingConnection", ctx, conn) + ret0, _ := ret[0].(error) + return ret0 } -// Close indicates an expected call of Close -func (mr *MockPeerManagerMockRecorder) Close() *gomock.Call { +// SpawnIncomingConnection indicates an expected call of SpawnIncomingConnection. +func (mr *MockPeerManagerMockRecorder) SpawnIncomingConnection(ctx, conn interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockPeerManager)(nil).Close)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpawnIncomingConnection", reflect.TypeOf((*MockPeerManager)(nil).SpawnIncomingConnection), ctx, conn) } -// SpawnOutgoingConnections mocks base method +// SpawnOutgoingConnections mocks base method. func (m *MockPeerManager) SpawnOutgoingConnections(arg0 context.Context) { m.ctrl.T.Helper() m.ctrl.Call(m, "SpawnOutgoingConnections", arg0) } -// SpawnOutgoingConnections indicates an expected call of SpawnOutgoingConnections +// SpawnOutgoingConnections indicates an expected call of SpawnOutgoingConnections. func (mr *MockPeerManagerMockRecorder) SpawnOutgoingConnections(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpawnOutgoingConnections", reflect.TypeOf((*MockPeerManager)(nil).SpawnOutgoingConnections), arg0) } -// SpawnIncomingConnection mocks base method -func (m *MockPeerManager) SpawnIncomingConnection(ctx context.Context, conn net.Conn) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpawnIncomingConnection", ctx, conn) - ret0, _ := ret[0].(error) - return ret0 -} - -// SpawnIncomingConnection indicates an expected call of SpawnIncomingConnection -func (mr *MockPeerManagerMockRecorder) SpawnIncomingConnection(ctx, conn interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpawnIncomingConnection", reflect.TypeOf((*MockPeerManager)(nil).SpawnIncomingConnection), ctx, conn) -} - -// Spawned mocks base method +// Spawned mocks base method. func (m *MockPeerManager) Spawned() []proto.IpPort { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Spawned") @@ -264,61 +265,62 @@ func (m *MockPeerManager) Spawned() []proto.IpPort { return ret0 } -// Spawned indicates an expected call of Spawned +// Spawned indicates an expected call of Spawned. func (mr *MockPeerManagerMockRecorder) Spawned() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Spawned", reflect.TypeOf((*MockPeerManager)(nil).Spawned)) } -// Connect mocks base method -func (m *MockPeerManager) Connect(arg0 context.Context, arg1 proto.TCPAddr) error { +// Suspend mocks base method. +func (m *MockPeerManager) Suspend(peer peer.Peer, suspendTime time.Time, reason string) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Connect", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 + m.ctrl.Call(m, "Suspend", peer, suspendTime, reason) } -// Connect indicates an expected call of Connect -func (mr *MockPeerManagerMockRecorder) Connect(arg0, arg1 interface{}) *gomock.Call { +// Suspend indicates an expected call of Suspend. +func (mr *MockPeerManagerMockRecorder) Suspend(peer, suspendTime, reason interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connect", reflect.TypeOf((*MockPeerManager)(nil).Connect), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Suspend", reflect.TypeOf((*MockPeerManager)(nil).Suspend), peer, suspendTime, reason) } -// Score mocks base method -func (m *MockPeerManager) Score(p peer.Peer) (*proto.Score, error) { +// Suspended mocks base method. +func (m *MockPeerManager) Suspended() []storage.SuspendedPeer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Score", p) - ret0, _ := ret[0].(*proto.Score) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "Suspended") + ret0, _ := ret[0].([]storage.SuspendedPeer) + return ret0 } -// Score indicates an expected call of Score -func (mr *MockPeerManagerMockRecorder) Score(p interface{}) *gomock.Call { +// Suspended indicates an expected call of Suspended. +func (mr *MockPeerManagerMockRecorder) Suspended() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Score", reflect.TypeOf((*MockPeerManager)(nil).Score), p) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Suspended", reflect.TypeOf((*MockPeerManager)(nil).Suspended)) } -// AskPeers mocks base method -func (m *MockPeerManager) AskPeers() { +// UpdateKnownPeers mocks base method. +func (m *MockPeerManager) UpdateKnownPeers(arg0 []storage.KnownPeer) error { m.ctrl.T.Helper() - m.ctrl.Call(m, "AskPeers") + ret := m.ctrl.Call(m, "UpdateKnownPeers", arg0) + ret0, _ := ret[0].(error) + return ret0 } -// AskPeers indicates an expected call of AskPeers -func (mr *MockPeerManagerMockRecorder) AskPeers() *gomock.Call { +// UpdateKnownPeers indicates an expected call of UpdateKnownPeers. +func (mr *MockPeerManagerMockRecorder) UpdateKnownPeers(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AskPeers", reflect.TypeOf((*MockPeerManager)(nil).AskPeers)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateKnownPeers", reflect.TypeOf((*MockPeerManager)(nil).UpdateKnownPeers), arg0) } -// Disconnect mocks base method -func (m *MockPeerManager) Disconnect(arg0 peer.Peer) { +// UpdateScore mocks base method. +func (m *MockPeerManager) UpdateScore(p peer.Peer, score *proto.Score) error { m.ctrl.T.Helper() - m.ctrl.Call(m, "Disconnect", arg0) + ret := m.ctrl.Call(m, "UpdateScore", p, score) + ret0, _ := ret[0].(error) + return ret0 } -// Disconnect indicates an expected call of Disconnect -func (mr *MockPeerManagerMockRecorder) Disconnect(arg0 interface{}) *gomock.Call { +// UpdateScore indicates an expected call of UpdateScore. +func (mr *MockPeerManagerMockRecorder) UpdateScore(p, score interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Disconnect", reflect.TypeOf((*MockPeerManager)(nil).Disconnect), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateScore", reflect.TypeOf((*MockPeerManager)(nil).UpdateScore), p, score) } diff --git a/pkg/mock/peer_storage.go b/pkg/mock/peer_storage.go new file mode 100644 index 000000000..b4ce4cb10 --- /dev/null +++ b/pkg/mock/peer_storage.go @@ -0,0 +1,204 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: pkg/node/peer_manager/peer_storage.go + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + time "time" + + gomock "github.com/golang/mock/gomock" + storage "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" +) + +// MockPeerStorage is a mock of PeerStorage interface. +type MockPeerStorage struct { + ctrl *gomock.Controller + recorder *MockPeerStorageMockRecorder +} + +// MockPeerStorageMockRecorder is the mock recorder for MockPeerStorage. +type MockPeerStorageMockRecorder struct { + mock *MockPeerStorage +} + +// NewMockPeerStorage creates a new mock instance. +func NewMockPeerStorage(ctrl *gomock.Controller) *MockPeerStorage { + mock := &MockPeerStorage{ctrl: ctrl} + mock.recorder = &MockPeerStorageMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPeerStorage) EXPECT() *MockPeerStorageMockRecorder { + return m.recorder +} + +// AddKnown mocks base method. +func (m *MockPeerStorage) AddKnown(known []storage.KnownPeer) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddKnown", known) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddKnown indicates an expected call of AddKnown. +func (mr *MockPeerStorageMockRecorder) AddKnown(known interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddKnown", reflect.TypeOf((*MockPeerStorage)(nil).AddKnown), known) +} + +// AddSuspended mocks base method. +func (m *MockPeerStorage) AddSuspended(suspended []storage.SuspendedPeer) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddSuspended", suspended) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddSuspended indicates an expected call of AddSuspended. +func (mr *MockPeerStorageMockRecorder) AddSuspended(suspended interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSuspended", reflect.TypeOf((*MockPeerStorage)(nil).AddSuspended), suspended) +} + +// DeleteKnown mocks base method. +func (m *MockPeerStorage) DeleteKnown(known []storage.KnownPeer) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteKnown", known) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteKnown indicates an expected call of DeleteKnown. +func (mr *MockPeerStorageMockRecorder) DeleteKnown(known interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteKnown", reflect.TypeOf((*MockPeerStorage)(nil).DeleteKnown), known) +} + +// DeleteSuspendedByIP mocks base method. +func (m *MockPeerStorage) DeleteSuspendedByIP(suspended []storage.SuspendedPeer) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteSuspendedByIP", suspended) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteSuspendedByIP indicates an expected call of DeleteSuspendedByIP. +func (mr *MockPeerStorageMockRecorder) DeleteSuspendedByIP(suspended interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSuspendedByIP", reflect.TypeOf((*MockPeerStorage)(nil).DeleteSuspendedByIP), suspended) +} + +// DropKnown mocks base method. +func (m *MockPeerStorage) DropKnown() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DropKnown") + ret0, _ := ret[0].(error) + return ret0 +} + +// DropKnown indicates an expected call of DropKnown. +func (mr *MockPeerStorageMockRecorder) DropKnown() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DropKnown", reflect.TypeOf((*MockPeerStorage)(nil).DropKnown)) +} + +// DropStorage mocks base method. +func (m *MockPeerStorage) DropStorage() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DropStorage") + ret0, _ := ret[0].(error) + return ret0 +} + +// DropStorage indicates an expected call of DropStorage. +func (mr *MockPeerStorageMockRecorder) DropStorage() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DropStorage", reflect.TypeOf((*MockPeerStorage)(nil).DropStorage)) +} + +// DropSuspended mocks base method. +func (m *MockPeerStorage) DropSuspended() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DropSuspended") + ret0, _ := ret[0].(error) + return ret0 +} + +// DropSuspended indicates an expected call of DropSuspended. +func (mr *MockPeerStorageMockRecorder) DropSuspended() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DropSuspended", reflect.TypeOf((*MockPeerStorage)(nil).DropSuspended)) +} + +// IsSuspendedIP mocks base method. +func (m *MockPeerStorage) IsSuspendedIP(ip storage.IP, now time.Time) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSuspendedIP", ip, now) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSuspendedIP indicates an expected call of IsSuspendedIP. +func (mr *MockPeerStorageMockRecorder) IsSuspendedIP(ip, now interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSuspendedIP", reflect.TypeOf((*MockPeerStorage)(nil).IsSuspendedIP), ip, now) +} + +// IsSuspendedIPs mocks base method. +func (m *MockPeerStorage) IsSuspendedIPs(ips []storage.IP, now time.Time) []bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSuspendedIPs", ips, now) + ret0, _ := ret[0].([]bool) + return ret0 +} + +// IsSuspendedIPs indicates an expected call of IsSuspendedIPs. +func (mr *MockPeerStorageMockRecorder) IsSuspendedIPs(ips, now interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSuspendedIPs", reflect.TypeOf((*MockPeerStorage)(nil).IsSuspendedIPs), ips, now) +} + +// Known mocks base method. +func (m *MockPeerStorage) Known() []storage.KnownPeer { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Known") + ret0, _ := ret[0].([]storage.KnownPeer) + return ret0 +} + +// Known indicates an expected call of Known. +func (mr *MockPeerStorageMockRecorder) Known() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Known", reflect.TypeOf((*MockPeerStorage)(nil).Known)) +} + +// RefreshSuspended mocks base method. +func (m *MockPeerStorage) RefreshSuspended(now time.Time) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RefreshSuspended", now) + ret0, _ := ret[0].(error) + return ret0 +} + +// RefreshSuspended indicates an expected call of RefreshSuspended. +func (mr *MockPeerStorageMockRecorder) RefreshSuspended(now interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RefreshSuspended", reflect.TypeOf((*MockPeerStorage)(nil).RefreshSuspended), now) +} + +// Suspended mocks base method. +func (m *MockPeerStorage) Suspended(now time.Time) []storage.SuspendedPeer { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Suspended", now) + ret0, _ := ret[0].([]storage.SuspendedPeer) + return ret0 +} + +// Suspended indicates an expected call of Suspended. +func (mr *MockPeerStorageMockRecorder) Suspended(now interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Suspended", reflect.TypeOf((*MockPeerStorage)(nil).Suspended), now) +} diff --git a/pkg/mock/state.go b/pkg/mock/state.go index d377cedcf..3c367d936 100644 --- a/pkg/mock/state.go +++ b/pkg/mock/state.go @@ -5,55 +5,54 @@ package mock import ( + big "math/big" + reflect "reflect" + gomock "github.com/golang/mock/gomock" crypto "github.com/wavesplatform/gowaves/pkg/crypto" proto "github.com/wavesplatform/gowaves/pkg/proto" settings "github.com/wavesplatform/gowaves/pkg/settings" state "github.com/wavesplatform/gowaves/pkg/state" - big "math/big" - reflect "reflect" ) -// MockTransactionIterator is a mock of TransactionIterator interface +// MockTransactionIterator is a mock of TransactionIterator interface. type MockTransactionIterator struct { ctrl *gomock.Controller recorder *MockTransactionIteratorMockRecorder } -// MockTransactionIteratorMockRecorder is the mock recorder for MockTransactionIterator +// MockTransactionIteratorMockRecorder is the mock recorder for MockTransactionIterator. type MockTransactionIteratorMockRecorder struct { mock *MockTransactionIterator } -// NewMockTransactionIterator creates a new mock instance +// NewMockTransactionIterator creates a new mock instance. func NewMockTransactionIterator(ctrl *gomock.Controller) *MockTransactionIterator { mock := &MockTransactionIterator{ctrl: ctrl} mock.recorder = &MockTransactionIteratorMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockTransactionIterator) EXPECT() *MockTransactionIteratorMockRecorder { return m.recorder } -// Transaction mocks base method -func (m *MockTransactionIterator) Transaction() (proto.Transaction, bool, error) { +// Error mocks base method. +func (m *MockTransactionIterator) Error() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Transaction") - ret0, _ := ret[0].(proto.Transaction) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 + ret := m.ctrl.Call(m, "Error") + ret0, _ := ret[0].(error) + return ret0 } -// Transaction indicates an expected call of Transaction -func (mr *MockTransactionIteratorMockRecorder) Transaction() *gomock.Call { +// Error indicates an expected call of Error. +func (mr *MockTransactionIteratorMockRecorder) Error() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transaction", reflect.TypeOf((*MockTransactionIterator)(nil).Transaction)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockTransactionIterator)(nil).Error)) } -// Next mocks base method +// Next mocks base method. func (m *MockTransactionIterator) Next() bool { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Next") @@ -61,151 +60,199 @@ func (m *MockTransactionIterator) Next() bool { return ret0 } -// Next indicates an expected call of Next +// Next indicates an expected call of Next. func (mr *MockTransactionIteratorMockRecorder) Next() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Next", reflect.TypeOf((*MockTransactionIterator)(nil).Next)) } -// Release mocks base method +// Release mocks base method. func (m *MockTransactionIterator) Release() { m.ctrl.T.Helper() m.ctrl.Call(m, "Release") } -// Release indicates an expected call of Release +// Release indicates an expected call of Release. func (mr *MockTransactionIteratorMockRecorder) Release() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Release", reflect.TypeOf((*MockTransactionIterator)(nil).Release)) } -// Error mocks base method -func (m *MockTransactionIterator) Error() error { +// Transaction mocks base method. +func (m *MockTransactionIterator) Transaction() (proto.Transaction, bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Error") - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "Transaction") + ret0, _ := ret[0].(proto.Transaction) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } -// Error indicates an expected call of Error -func (mr *MockTransactionIteratorMockRecorder) Error() *gomock.Call { +// Transaction indicates an expected call of Transaction. +func (mr *MockTransactionIteratorMockRecorder) Transaction() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockTransactionIterator)(nil).Error)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transaction", reflect.TypeOf((*MockTransactionIterator)(nil).Transaction)) } -// MockStateInfo is a mock of StateInfo interface +// MockStateInfo is a mock of StateInfo interface. type MockStateInfo struct { ctrl *gomock.Controller recorder *MockStateInfoMockRecorder } -// MockStateInfoMockRecorder is the mock recorder for MockStateInfo +// MockStateInfoMockRecorder is the mock recorder for MockStateInfo. type MockStateInfoMockRecorder struct { mock *MockStateInfo } -// NewMockStateInfo creates a new mock instance +// NewMockStateInfo creates a new mock instance. func NewMockStateInfo(ctrl *gomock.Controller) *MockStateInfo { mock := &MockStateInfo{ctrl: ctrl} mock.recorder = &MockStateInfoMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockStateInfo) EXPECT() *MockStateInfoMockRecorder { return m.recorder } -// TopBlock mocks base method -func (m *MockStateInfo) TopBlock() *proto.Block { +// AccountBalance mocks base method. +func (m *MockStateInfo) AccountBalance(account proto.Recipient, asset []byte) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TopBlock") - ret0, _ := ret[0].(*proto.Block) - return ret0 + ret := m.ctrl.Call(m, "AccountBalance", account, asset) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// TopBlock indicates an expected call of TopBlock -func (mr *MockStateInfoMockRecorder) TopBlock() *gomock.Call { +// AccountBalance indicates an expected call of AccountBalance. +func (mr *MockStateInfoMockRecorder) AccountBalance(account, asset interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopBlock", reflect.TypeOf((*MockStateInfo)(nil).TopBlock)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountBalance", reflect.TypeOf((*MockStateInfo)(nil).AccountBalance), account, asset) } -// Block mocks base method -func (m *MockStateInfo) Block(blockID proto.BlockID) (*proto.Block, error) { +// ActivationHeight mocks base method. +func (m *MockStateInfo) ActivationHeight(featureID int16) (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Block", blockID) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "ActivationHeight", featureID) + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// Block indicates an expected call of Block -func (mr *MockStateInfoMockRecorder) Block(blockID interface{}) *gomock.Call { +// ActivationHeight indicates an expected call of ActivationHeight. +func (mr *MockStateInfoMockRecorder) ActivationHeight(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Block", reflect.TypeOf((*MockStateInfo)(nil).Block), blockID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivationHeight", reflect.TypeOf((*MockStateInfo)(nil).ActivationHeight), featureID) } -// BlockByHeight mocks base method -func (m *MockStateInfo) BlockByHeight(height proto.Height) (*proto.Block, error) { +// AddrByAlias mocks base method. +func (m *MockStateInfo) AddrByAlias(alias proto.Alias) (proto.Address, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockByHeight", height) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "AddrByAlias", alias) + ret0, _ := ret[0].(proto.Address) ret1, _ := ret[1].(error) return ret0, ret1 } -// BlockByHeight indicates an expected call of BlockByHeight -func (mr *MockStateInfoMockRecorder) BlockByHeight(height interface{}) *gomock.Call { +// AddrByAlias indicates an expected call of AddrByAlias. +func (mr *MockStateInfoMockRecorder) AddrByAlias(alias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHeight", reflect.TypeOf((*MockStateInfo)(nil).BlockByHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrByAlias", reflect.TypeOf((*MockStateInfo)(nil).AddrByAlias), alias) } -// Header mocks base method -func (m *MockStateInfo) Header(blockID proto.BlockID) (*proto.BlockHeader, error) { +// AllFeatures mocks base method. +func (m *MockStateInfo) AllFeatures() ([]int16, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Header", blockID) - ret0, _ := ret[0].(*proto.BlockHeader) + ret := m.ctrl.Call(m, "AllFeatures") + ret0, _ := ret[0].([]int16) ret1, _ := ret[1].(error) return ret0, ret1 } -// Header indicates an expected call of Header -func (mr *MockStateInfoMockRecorder) Header(blockID interface{}) *gomock.Call { +// AllFeatures indicates an expected call of AllFeatures. +func (mr *MockStateInfoMockRecorder) AllFeatures() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockStateInfo)(nil).Header), blockID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllFeatures", reflect.TypeOf((*MockStateInfo)(nil).AllFeatures)) } -// HeaderByHeight mocks base method -func (m *MockStateInfo) HeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { +// ApprovalHeight mocks base method. +func (m *MockStateInfo) ApprovalHeight(featureID int16) (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeaderByHeight", height) - ret0, _ := ret[0].(*proto.BlockHeader) + ret := m.ctrl.Call(m, "ApprovalHeight", featureID) + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// HeaderByHeight indicates an expected call of HeaderByHeight -func (mr *MockStateInfoMockRecorder) HeaderByHeight(height interface{}) *gomock.Call { +// ApprovalHeight indicates an expected call of ApprovalHeight. +func (mr *MockStateInfoMockRecorder) ApprovalHeight(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHeight", reflect.TypeOf((*MockStateInfo)(nil).HeaderByHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApprovalHeight", reflect.TypeOf((*MockStateInfo)(nil).ApprovalHeight), featureID) } -// Height mocks base method -func (m *MockStateInfo) Height() (proto.Height, error) { +// AssetInfo mocks base method. +func (m *MockStateInfo) AssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Height") - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "AssetInfo", assetID) + ret0, _ := ret[0].(*proto.AssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// Height indicates an expected call of Height -func (mr *MockStateInfoMockRecorder) Height() *gomock.Call { +// AssetInfo indicates an expected call of AssetInfo. +func (mr *MockStateInfoMockRecorder) AssetInfo(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Height", reflect.TypeOf((*MockStateInfo)(nil).Height)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetInfo", reflect.TypeOf((*MockStateInfo)(nil).AssetInfo), assetID) +} + +// AssetIsSponsored mocks base method. +func (m *MockStateInfo) AssetIsSponsored(assetID crypto.Digest) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AssetIsSponsored", assetID) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AssetIsSponsored indicates an expected call of AssetIsSponsored. +func (mr *MockStateInfoMockRecorder) AssetIsSponsored(assetID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetIsSponsored", reflect.TypeOf((*MockStateInfo)(nil).AssetIsSponsored), assetID) +} + +// Block mocks base method. +func (m *MockStateInfo) Block(blockID proto.BlockID) (*proto.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Block", blockID) + ret0, _ := ret[0].(*proto.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Block indicates an expected call of Block. +func (mr *MockStateInfoMockRecorder) Block(blockID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Block", reflect.TypeOf((*MockStateInfo)(nil).Block), blockID) +} + +// BlockByHeight mocks base method. +func (m *MockStateInfo) BlockByHeight(height proto.Height) (*proto.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockByHeight", height) + ret0, _ := ret[0].(*proto.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BlockByHeight indicates an expected call of BlockByHeight. +func (mr *MockStateInfoMockRecorder) BlockByHeight(height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHeight", reflect.TypeOf((*MockStateInfo)(nil).BlockByHeight), height) } -// BlockIDToHeight mocks base method +// BlockIDToHeight mocks base method. func (m *MockStateInfo) BlockIDToHeight(blockID proto.BlockID) (proto.Height, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockIDToHeight", blockID) @@ -214,43 +261,43 @@ func (m *MockStateInfo) BlockIDToHeight(blockID proto.BlockID) (proto.Height, er return ret0, ret1 } -// BlockIDToHeight indicates an expected call of BlockIDToHeight +// BlockIDToHeight indicates an expected call of BlockIDToHeight. func (mr *MockStateInfoMockRecorder) BlockIDToHeight(blockID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockIDToHeight", reflect.TypeOf((*MockStateInfo)(nil).BlockIDToHeight), blockID) } -// HeightToBlockID mocks base method -func (m *MockStateInfo) HeightToBlockID(height proto.Height) (proto.BlockID, error) { +// BlockchainSettings mocks base method. +func (m *MockStateInfo) BlockchainSettings() (*settings.BlockchainSettings, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeightToBlockID", height) - ret0, _ := ret[0].(proto.BlockID) + ret := m.ctrl.Call(m, "BlockchainSettings") + ret0, _ := ret[0].(*settings.BlockchainSettings) ret1, _ := ret[1].(error) return ret0, ret1 } -// HeightToBlockID indicates an expected call of HeightToBlockID -func (mr *MockStateInfoMockRecorder) HeightToBlockID(height interface{}) *gomock.Call { +// BlockchainSettings indicates an expected call of BlockchainSettings. +func (mr *MockStateInfoMockRecorder) BlockchainSettings() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeightToBlockID", reflect.TypeOf((*MockStateInfo)(nil).HeightToBlockID), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockchainSettings", reflect.TypeOf((*MockStateInfo)(nil).BlockchainSettings)) } -// FullWavesBalance mocks base method -func (m *MockStateInfo) FullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { +// CurrentScore mocks base method. +func (m *MockStateInfo) CurrentScore() (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FullWavesBalance", account) - ret0, _ := ret[0].(*proto.FullWavesBalance) + ret := m.ctrl.Call(m, "CurrentScore") + ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } -// FullWavesBalance indicates an expected call of FullWavesBalance -func (mr *MockStateInfoMockRecorder) FullWavesBalance(account interface{}) *gomock.Call { +// CurrentScore indicates an expected call of CurrentScore. +func (mr *MockStateInfoMockRecorder) CurrentScore() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullWavesBalance", reflect.TypeOf((*MockStateInfo)(nil).FullWavesBalance), account) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentScore", reflect.TypeOf((*MockStateInfo)(nil).CurrentScore)) } -// EffectiveBalance mocks base method +// EffectiveBalance mocks base method. func (m *MockStateInfo) EffectiveBalance(account proto.Recipient, startHeight, endHeight proto.Height) (uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EffectiveBalance", account, startHeight, endHeight) @@ -259,133 +306,148 @@ func (m *MockStateInfo) EffectiveBalance(account proto.Recipient, startHeight, e return ret0, ret1 } -// EffectiveBalance indicates an expected call of EffectiveBalance +// EffectiveBalance indicates an expected call of EffectiveBalance. func (mr *MockStateInfoMockRecorder) EffectiveBalance(account, startHeight, endHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EffectiveBalance", reflect.TypeOf((*MockStateInfo)(nil).EffectiveBalance), account, startHeight, endHeight) } -// AccountBalance mocks base method -func (m *MockStateInfo) AccountBalance(account proto.Recipient, asset []byte) (uint64, error) { +// EstimatorVersion mocks base method. +func (m *MockStateInfo) EstimatorVersion() (int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AccountBalance", account, asset) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "EstimatorVersion") + ret0, _ := ret[0].(int) ret1, _ := ret[1].(error) return ret0, ret1 } -// AccountBalance indicates an expected call of AccountBalance -func (mr *MockStateInfoMockRecorder) AccountBalance(account, asset interface{}) *gomock.Call { +// EstimatorVersion indicates an expected call of EstimatorVersion. +func (mr *MockStateInfoMockRecorder) EstimatorVersion() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountBalance", reflect.TypeOf((*MockStateInfo)(nil).AccountBalance), account, asset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimatorVersion", reflect.TypeOf((*MockStateInfo)(nil).EstimatorVersion)) } -// WavesAddressesNumber mocks base method -func (m *MockStateInfo) WavesAddressesNumber() (uint64, error) { +// FullAssetInfo mocks base method. +func (m *MockStateInfo) FullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WavesAddressesNumber") - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "FullAssetInfo", assetID) + ret0, _ := ret[0].(*proto.FullAssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// WavesAddressesNumber indicates an expected call of WavesAddressesNumber -func (mr *MockStateInfoMockRecorder) WavesAddressesNumber() *gomock.Call { +// FullAssetInfo indicates an expected call of FullAssetInfo. +func (mr *MockStateInfoMockRecorder) FullAssetInfo(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WavesAddressesNumber", reflect.TypeOf((*MockStateInfo)(nil).WavesAddressesNumber)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullAssetInfo", reflect.TypeOf((*MockStateInfo)(nil).FullAssetInfo), assetID) } -// ScoreAtHeight mocks base method -func (m *MockStateInfo) ScoreAtHeight(height proto.Height) (*big.Int, error) { +// FullWavesBalance mocks base method. +func (m *MockStateInfo) FullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScoreAtHeight", height) - ret0, _ := ret[0].(*big.Int) + ret := m.ctrl.Call(m, "FullWavesBalance", account) + ret0, _ := ret[0].(*proto.FullWavesBalance) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScoreAtHeight indicates an expected call of ScoreAtHeight -func (mr *MockStateInfoMockRecorder) ScoreAtHeight(height interface{}) *gomock.Call { +// FullWavesBalance indicates an expected call of FullWavesBalance. +func (mr *MockStateInfoMockRecorder) FullWavesBalance(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScoreAtHeight", reflect.TypeOf((*MockStateInfo)(nil).ScoreAtHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullWavesBalance", reflect.TypeOf((*MockStateInfo)(nil).FullWavesBalance), account) } -// CurrentScore mocks base method -func (m *MockStateInfo) CurrentScore() (*big.Int, error) { +// Header mocks base method. +func (m *MockStateInfo) Header(blockID proto.BlockID) (*proto.BlockHeader, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CurrentScore") - ret0, _ := ret[0].(*big.Int) + ret := m.ctrl.Call(m, "Header", blockID) + ret0, _ := ret[0].(*proto.BlockHeader) ret1, _ := ret[1].(error) return ret0, ret1 } -// CurrentScore indicates an expected call of CurrentScore -func (mr *MockStateInfoMockRecorder) CurrentScore() *gomock.Call { +// Header indicates an expected call of Header. +func (mr *MockStateInfoMockRecorder) Header(blockID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentScore", reflect.TypeOf((*MockStateInfo)(nil).CurrentScore)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockStateInfo)(nil).Header), blockID) } -// BlockchainSettings mocks base method -func (m *MockStateInfo) BlockchainSettings() (*settings.BlockchainSettings, error) { +// HeaderByHeight mocks base method. +func (m *MockStateInfo) HeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockchainSettings") - ret0, _ := ret[0].(*settings.BlockchainSettings) + ret := m.ctrl.Call(m, "HeaderByHeight", height) + ret0, _ := ret[0].(*proto.BlockHeader) ret1, _ := ret[1].(error) return ret0, ret1 } -// BlockchainSettings indicates an expected call of BlockchainSettings -func (mr *MockStateInfoMockRecorder) BlockchainSettings() *gomock.Call { +// HeaderByHeight indicates an expected call of HeaderByHeight. +func (mr *MockStateInfoMockRecorder) HeaderByHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockchainSettings", reflect.TypeOf((*MockStateInfo)(nil).BlockchainSettings)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHeight", reflect.TypeOf((*MockStateInfo)(nil).HeaderByHeight), height) } -// Peers mocks base method -func (m *MockStateInfo) Peers() ([]proto.TCPAddr, error) { +// Height mocks base method. +func (m *MockStateInfo) Height() (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Peers") - ret0, _ := ret[0].([]proto.TCPAddr) + ret := m.ctrl.Call(m, "Height") + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// Peers indicates an expected call of Peers -func (mr *MockStateInfoMockRecorder) Peers() *gomock.Call { +// Height indicates an expected call of Height. +func (mr *MockStateInfoMockRecorder) Height() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Peers", reflect.TypeOf((*MockStateInfo)(nil).Peers)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Height", reflect.TypeOf((*MockStateInfo)(nil).Height)) } -// VotesNum mocks base method -func (m *MockStateInfo) VotesNum(featureID int16) (uint64, error) { +// HeightToBlockID mocks base method. +func (m *MockStateInfo) HeightToBlockID(height proto.Height) (proto.BlockID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VotesNum", featureID) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "HeightToBlockID", height) + ret0, _ := ret[0].(proto.BlockID) ret1, _ := ret[1].(error) return ret0, ret1 } -// VotesNum indicates an expected call of VotesNum -func (mr *MockStateInfoMockRecorder) VotesNum(featureID interface{}) *gomock.Call { +// HeightToBlockID indicates an expected call of HeightToBlockID. +func (mr *MockStateInfoMockRecorder) HeightToBlockID(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNum", reflect.TypeOf((*MockStateInfo)(nil).VotesNum), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeightToBlockID", reflect.TypeOf((*MockStateInfo)(nil).HeightToBlockID), height) } -// VotesNumAtHeight mocks base method -func (m *MockStateInfo) VotesNumAtHeight(featureID int16, height proto.Height) (uint64, error) { +// HitSourceAtHeight mocks base method. +func (m *MockStateInfo) HitSourceAtHeight(height proto.Height) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VotesNumAtHeight", featureID, height) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "HitSourceAtHeight", height) + ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } -// VotesNumAtHeight indicates an expected call of VotesNumAtHeight -func (mr *MockStateInfoMockRecorder) VotesNumAtHeight(featureID, height interface{}) *gomock.Call { +// HitSourceAtHeight indicates an expected call of HitSourceAtHeight. +func (mr *MockStateInfoMockRecorder) HitSourceAtHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNumAtHeight", reflect.TypeOf((*MockStateInfo)(nil).VotesNumAtHeight), featureID, height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HitSourceAtHeight", reflect.TypeOf((*MockStateInfo)(nil).HitSourceAtHeight), height) +} + +// InvokeResultByID mocks base method. +func (m *MockStateInfo) InvokeResultByID(invokeID crypto.Digest) (*proto.ScriptResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InvokeResultByID", invokeID) + ret0, _ := ret[0].(*proto.ScriptResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// InvokeResultByID indicates an expected call of InvokeResultByID. +func (mr *MockStateInfoMockRecorder) InvokeResultByID(invokeID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeResultByID", reflect.TypeOf((*MockStateInfo)(nil).InvokeResultByID), invokeID) } -// IsActivated mocks base method +// IsActivated mocks base method. func (m *MockStateInfo) IsActivated(featureID int16) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsActivated", featureID) @@ -394,13 +456,13 @@ func (m *MockStateInfo) IsActivated(featureID int16) (bool, error) { return ret0, ret1 } -// IsActivated indicates an expected call of IsActivated +// IsActivated indicates an expected call of IsActivated. func (mr *MockStateInfoMockRecorder) IsActivated(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActivated", reflect.TypeOf((*MockStateInfo)(nil).IsActivated), featureID) } -// IsActiveAtHeight mocks base method +// IsActiveAtHeight mocks base method. func (m *MockStateInfo) IsActiveAtHeight(featureID int16, height proto.Height) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsActiveAtHeight", featureID, height) @@ -409,28 +471,28 @@ func (m *MockStateInfo) IsActiveAtHeight(featureID int16, height proto.Height) ( return ret0, ret1 } -// IsActiveAtHeight indicates an expected call of IsActiveAtHeight +// IsActiveAtHeight indicates an expected call of IsActiveAtHeight. func (mr *MockStateInfoMockRecorder) IsActiveAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveAtHeight", reflect.TypeOf((*MockStateInfo)(nil).IsActiveAtHeight), featureID, height) } -// ActivationHeight mocks base method -func (m *MockStateInfo) ActivationHeight(featureID int16) (proto.Height, error) { +// IsActiveLeasing mocks base method. +func (m *MockStateInfo) IsActiveLeasing(leaseID crypto.Digest) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ActivationHeight", featureID) - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "IsActiveLeasing", leaseID) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// ActivationHeight indicates an expected call of ActivationHeight -func (mr *MockStateInfoMockRecorder) ActivationHeight(featureID interface{}) *gomock.Call { +// IsActiveLeasing indicates an expected call of IsActiveLeasing. +func (mr *MockStateInfoMockRecorder) IsActiveLeasing(leaseID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivationHeight", reflect.TypeOf((*MockStateInfo)(nil).ActivationHeight), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveLeasing", reflect.TypeOf((*MockStateInfo)(nil).IsActiveLeasing), leaseID) } -// IsApproved mocks base method +// IsApproved mocks base method. func (m *MockStateInfo) IsApproved(featureID int16) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsApproved", featureID) @@ -439,13 +501,13 @@ func (m *MockStateInfo) IsApproved(featureID int16) (bool, error) { return ret0, ret1 } -// IsApproved indicates an expected call of IsApproved +// IsApproved indicates an expected call of IsApproved. func (mr *MockStateInfoMockRecorder) IsApproved(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApproved", reflect.TypeOf((*MockStateInfo)(nil).IsApproved), featureID) } -// IsApprovedAtHeight mocks base method +// IsApprovedAtHeight mocks base method. func (m *MockStateInfo) IsApprovedAtHeight(featureID int16, height proto.Height) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsApprovedAtHeight", featureID, height) @@ -454,73 +516,118 @@ func (m *MockStateInfo) IsApprovedAtHeight(featureID int16, height proto.Height) return ret0, ret1 } -// IsApprovedAtHeight indicates an expected call of IsApprovedAtHeight +// IsApprovedAtHeight indicates an expected call of IsApprovedAtHeight. func (mr *MockStateInfoMockRecorder) IsApprovedAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApprovedAtHeight", reflect.TypeOf((*MockStateInfo)(nil).IsApprovedAtHeight), featureID, height) } -// ApprovalHeight mocks base method -func (m *MockStateInfo) ApprovalHeight(featureID int16) (proto.Height, error) { +// MapR mocks base method. +func (m *MockStateInfo) MapR(arg0 func(state.StateInfo) (interface{}, error)) (interface{}, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ApprovalHeight", featureID) - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "MapR", arg0) + ret0, _ := ret[0].(interface{}) ret1, _ := ret[1].(error) return ret0, ret1 } -// ApprovalHeight indicates an expected call of ApprovalHeight -func (mr *MockStateInfoMockRecorder) ApprovalHeight(featureID interface{}) *gomock.Call { +// MapR indicates an expected call of MapR. +func (mr *MockStateInfoMockRecorder) MapR(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApprovalHeight", reflect.TypeOf((*MockStateInfo)(nil).ApprovalHeight), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MapR", reflect.TypeOf((*MockStateInfo)(nil).MapR), arg0) } -// AllFeatures mocks base method -func (m *MockStateInfo) AllFeatures() ([]int16, error) { +// NFTList mocks base method. +func (m *MockStateInfo) NFTList(account proto.Recipient, limit uint64, afterAssetID []byte) ([]*proto.FullAssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AllFeatures") - ret0, _ := ret[0].([]int16) + ret := m.ctrl.Call(m, "NFTList", account, limit, afterAssetID) + ret0, _ := ret[0].([]*proto.FullAssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// AllFeatures indicates an expected call of AllFeatures -func (mr *MockStateInfoMockRecorder) AllFeatures() *gomock.Call { +// NFTList indicates an expected call of NFTList. +func (mr *MockStateInfoMockRecorder) NFTList(account, limit, afterAssetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllFeatures", reflect.TypeOf((*MockStateInfo)(nil).AllFeatures)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NFTList", reflect.TypeOf((*MockStateInfo)(nil).NFTList), account, limit, afterAssetID) } -// EstimatorVersion mocks base method -func (m *MockStateInfo) EstimatorVersion() (int, error) { +// NewAddrTransactionsIterator mocks base method. +func (m *MockStateInfo) NewAddrTransactionsIterator(addr proto.Address) (state.TransactionIterator, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EstimatorVersion") - ret0, _ := ret[0].(int) + ret := m.ctrl.Call(m, "NewAddrTransactionsIterator", addr) + ret0, _ := ret[0].(state.TransactionIterator) ret1, _ := ret[1].(error) return ret0, ret1 } -// EstimatorVersion indicates an expected call of EstimatorVersion -func (mr *MockStateInfoMockRecorder) EstimatorVersion() *gomock.Call { +// NewAddrTransactionsIterator indicates an expected call of NewAddrTransactionsIterator. +func (mr *MockStateInfoMockRecorder) NewAddrTransactionsIterator(addr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimatorVersion", reflect.TypeOf((*MockStateInfo)(nil).EstimatorVersion)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddrTransactionsIterator", reflect.TypeOf((*MockStateInfo)(nil).NewAddrTransactionsIterator), addr) } -// AddrByAlias mocks base method -func (m *MockStateInfo) AddrByAlias(alias proto.Alias) (proto.Address, error) { +// ProvidesExtendedApi mocks base method. +func (m *MockStateInfo) ProvidesExtendedApi() (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddrByAlias", alias) - ret0, _ := ret[0].(proto.Address) + ret := m.ctrl.Call(m, "ProvidesExtendedApi") + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// AddrByAlias indicates an expected call of AddrByAlias -func (mr *MockStateInfoMockRecorder) AddrByAlias(alias interface{}) *gomock.Call { +// ProvidesExtendedApi indicates an expected call of ProvidesExtendedApi. +func (mr *MockStateInfoMockRecorder) ProvidesExtendedApi() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrByAlias", reflect.TypeOf((*MockStateInfo)(nil).AddrByAlias), alias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesExtendedApi", reflect.TypeOf((*MockStateInfo)(nil).ProvidesExtendedApi)) +} + +// ProvidesStateHashes mocks base method. +func (m *MockStateInfo) ProvidesStateHashes() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ProvidesStateHashes") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ProvidesStateHashes indicates an expected call of ProvidesStateHashes. +func (mr *MockStateInfoMockRecorder) ProvidesStateHashes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesStateHashes", reflect.TypeOf((*MockStateInfo)(nil).ProvidesStateHashes)) +} + +// RetrieveBinaryEntry mocks base method. +func (m *MockStateInfo) RetrieveBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RetrieveBinaryEntry", account, key) + ret0, _ := ret[0].(*proto.BinaryDataEntry) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveBinaryEntry indicates an expected call of RetrieveBinaryEntry. +func (mr *MockStateInfoMockRecorder) RetrieveBinaryEntry(account, key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBinaryEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveBinaryEntry), account, key) +} + +// RetrieveBooleanEntry mocks base method. +func (m *MockStateInfo) RetrieveBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RetrieveBooleanEntry", account, key) + ret0, _ := ret[0].(*proto.BooleanDataEntry) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveBooleanEntry indicates an expected call of RetrieveBooleanEntry. +func (mr *MockStateInfoMockRecorder) RetrieveBooleanEntry(account, key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBooleanEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveBooleanEntry), account, key) } -// RetrieveEntries mocks base method +// RetrieveEntries mocks base method. func (m *MockStateInfo) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RetrieveEntries", account) @@ -529,13 +636,13 @@ func (m *MockStateInfo) RetrieveEntries(account proto.Recipient) ([]proto.DataEn return ret0, ret1 } -// RetrieveEntries indicates an expected call of RetrieveEntries +// RetrieveEntries indicates an expected call of RetrieveEntries. func (mr *MockStateInfoMockRecorder) RetrieveEntries(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntries", reflect.TypeOf((*MockStateInfo)(nil).RetrieveEntries), account) } -// RetrieveEntry mocks base method +// RetrieveEntry mocks base method. func (m *MockStateInfo) RetrieveEntry(account proto.Recipient, key string) (proto.DataEntry, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RetrieveEntry", account, key) @@ -544,13 +651,13 @@ func (m *MockStateInfo) RetrieveEntry(account proto.Recipient, key string) (prot return ret0, ret1 } -// RetrieveEntry indicates an expected call of RetrieveEntry +// RetrieveEntry indicates an expected call of RetrieveEntry. func (mr *MockStateInfoMockRecorder) RetrieveEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveEntry), account, key) } -// RetrieveIntegerEntry mocks base method +// RetrieveIntegerEntry mocks base method. func (m *MockStateInfo) RetrieveIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RetrieveIntegerEntry", account, key) @@ -559,58 +666,117 @@ func (m *MockStateInfo) RetrieveIntegerEntry(account proto.Recipient, key string return ret0, ret1 } -// RetrieveIntegerEntry indicates an expected call of RetrieveIntegerEntry +// RetrieveIntegerEntry indicates an expected call of RetrieveIntegerEntry. func (mr *MockStateInfoMockRecorder) RetrieveIntegerEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveIntegerEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveIntegerEntry), account, key) } -// RetrieveBooleanEntry mocks base method -func (m *MockStateInfo) RetrieveBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { +// RetrieveStringEntry mocks base method. +func (m *MockStateInfo) RetrieveStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveBooleanEntry", account, key) - ret0, _ := ret[0].(*proto.BooleanDataEntry) + ret := m.ctrl.Call(m, "RetrieveStringEntry", account, key) + ret0, _ := ret[0].(*proto.StringDataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveBooleanEntry indicates an expected call of RetrieveBooleanEntry -func (mr *MockStateInfoMockRecorder) RetrieveBooleanEntry(account, key interface{}) *gomock.Call { +// RetrieveStringEntry indicates an expected call of RetrieveStringEntry. +func (mr *MockStateInfoMockRecorder) RetrieveStringEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBooleanEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveBooleanEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveStringEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveStringEntry), account, key) } -// RetrieveStringEntry mocks base method -func (m *MockStateInfo) RetrieveStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { +// ScoreAtHeight mocks base method. +func (m *MockStateInfo) ScoreAtHeight(height proto.Height) (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveStringEntry", account, key) - ret0, _ := ret[0].(*proto.StringDataEntry) + ret := m.ctrl.Call(m, "ScoreAtHeight", height) + ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveStringEntry indicates an expected call of RetrieveStringEntry -func (mr *MockStateInfoMockRecorder) RetrieveStringEntry(account, key interface{}) *gomock.Call { +// ScoreAtHeight indicates an expected call of ScoreAtHeight. +func (mr *MockStateInfoMockRecorder) ScoreAtHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveStringEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveStringEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScoreAtHeight", reflect.TypeOf((*MockStateInfo)(nil).ScoreAtHeight), height) } -// RetrieveBinaryEntry mocks base method -func (m *MockStateInfo) RetrieveBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { +// ScriptInfoByAccount mocks base method. +func (m *MockStateInfo) ScriptInfoByAccount(account proto.Recipient) (*proto.ScriptInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveBinaryEntry", account, key) - ret0, _ := ret[0].(*proto.BinaryDataEntry) + ret := m.ctrl.Call(m, "ScriptInfoByAccount", account) + ret0, _ := ret[0].(*proto.ScriptInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveBinaryEntry indicates an expected call of RetrieveBinaryEntry -func (mr *MockStateInfoMockRecorder) RetrieveBinaryEntry(account, key interface{}) *gomock.Call { +// ScriptInfoByAccount indicates an expected call of ScriptInfoByAccount. +func (mr *MockStateInfoMockRecorder) ScriptInfoByAccount(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBinaryEntry", reflect.TypeOf((*MockStateInfo)(nil).RetrieveBinaryEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAccount", reflect.TypeOf((*MockStateInfo)(nil).ScriptInfoByAccount), account) +} + +// ScriptInfoByAsset mocks base method. +func (m *MockStateInfo) ScriptInfoByAsset(assetID crypto.Digest) (*proto.ScriptInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ScriptInfoByAsset", assetID) + ret0, _ := ret[0].(*proto.ScriptInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ScriptInfoByAsset indicates an expected call of ScriptInfoByAsset. +func (mr *MockStateInfoMockRecorder) ScriptInfoByAsset(assetID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAsset", reflect.TypeOf((*MockStateInfo)(nil).ScriptInfoByAsset), assetID) +} + +// ShouldPersistAddressTransactions mocks base method. +func (m *MockStateInfo) ShouldPersistAddressTransactions() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ShouldPersistAddressTransactions") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ShouldPersistAddressTransactions indicates an expected call of ShouldPersistAddressTransactions. +func (mr *MockStateInfoMockRecorder) ShouldPersistAddressTransactions() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockStateInfo)(nil).ShouldPersistAddressTransactions)) +} + +// StateHashAtHeight mocks base method. +func (m *MockStateInfo) StateHashAtHeight(height uint64) (*proto.StateHash, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateHashAtHeight", height) + ret0, _ := ret[0].(*proto.StateHash) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateHashAtHeight indicates an expected call of StateHashAtHeight. +func (mr *MockStateInfoMockRecorder) StateHashAtHeight(height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateHashAtHeight", reflect.TypeOf((*MockStateInfo)(nil).StateHashAtHeight), height) +} + +// TopBlock mocks base method. +func (m *MockStateInfo) TopBlock() *proto.Block { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TopBlock") + ret0, _ := ret[0].(*proto.Block) + return ret0 } -// TransactionByID mocks base method +// TopBlock indicates an expected call of TopBlock. +func (mr *MockStateInfoMockRecorder) TopBlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopBlock", reflect.TypeOf((*MockStateInfo)(nil).TopBlock)) +} + +// TransactionByID mocks base method. func (m *MockStateInfo) TransactionByID(id []byte) (proto.Transaction, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TransactionByID", id) @@ -619,13 +785,13 @@ func (m *MockStateInfo) TransactionByID(id []byte) (proto.Transaction, error) { return ret0, ret1 } -// TransactionByID indicates an expected call of TransactionByID +// TransactionByID indicates an expected call of TransactionByID. func (mr *MockStateInfoMockRecorder) TransactionByID(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByID", reflect.TypeOf((*MockStateInfo)(nil).TransactionByID), id) } -// TransactionByIDWithStatus mocks base method +// TransactionByIDWithStatus mocks base method. func (m *MockStateInfo) TransactionByIDWithStatus(id []byte) (proto.Transaction, bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TransactionByIDWithStatus", id) @@ -635,13 +801,13 @@ func (m *MockStateInfo) TransactionByIDWithStatus(id []byte) (proto.Transaction, return ret0, ret1, ret2 } -// TransactionByIDWithStatus indicates an expected call of TransactionByIDWithStatus +// TransactionByIDWithStatus indicates an expected call of TransactionByIDWithStatus. func (mr *MockStateInfoMockRecorder) TransactionByIDWithStatus(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByIDWithStatus", reflect.TypeOf((*MockStateInfo)(nil).TransactionByIDWithStatus), id) } -// TransactionHeightByID mocks base method +// TransactionHeightByID mocks base method. func (m *MockStateInfo) TransactionHeightByID(id []byte) (uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TransactionHeightByID", id) @@ -650,320 +816,140 @@ func (m *MockStateInfo) TransactionHeightByID(id []byte) (uint64, error) { return ret0, ret1 } -// TransactionHeightByID indicates an expected call of TransactionHeightByID +// TransactionHeightByID indicates an expected call of TransactionHeightByID. func (mr *MockStateInfoMockRecorder) TransactionHeightByID(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionHeightByID", reflect.TypeOf((*MockStateInfo)(nil).TransactionHeightByID), id) } -// NewAddrTransactionsIterator mocks base method -func (m *MockStateInfo) NewAddrTransactionsIterator(addr proto.Address) (state.TransactionIterator, error) { +// VotesNum mocks base method. +func (m *MockStateInfo) VotesNum(featureID int16) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewAddrTransactionsIterator", addr) - ret0, _ := ret[0].(state.TransactionIterator) + ret := m.ctrl.Call(m, "VotesNum", featureID) + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// NewAddrTransactionsIterator indicates an expected call of NewAddrTransactionsIterator -func (mr *MockStateInfoMockRecorder) NewAddrTransactionsIterator(addr interface{}) *gomock.Call { +// VotesNum indicates an expected call of VotesNum. +func (mr *MockStateInfoMockRecorder) VotesNum(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddrTransactionsIterator", reflect.TypeOf((*MockStateInfo)(nil).NewAddrTransactionsIterator), addr) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNum", reflect.TypeOf((*MockStateInfo)(nil).VotesNum), featureID) } -// AssetIsSponsored mocks base method -func (m *MockStateInfo) AssetIsSponsored(assetID crypto.Digest) (bool, error) { +// VotesNumAtHeight mocks base method. +func (m *MockStateInfo) VotesNumAtHeight(featureID int16, height proto.Height) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssetIsSponsored", assetID) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "VotesNumAtHeight", featureID, height) + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// AssetIsSponsored indicates an expected call of AssetIsSponsored -func (mr *MockStateInfoMockRecorder) AssetIsSponsored(assetID interface{}) *gomock.Call { +// VotesNumAtHeight indicates an expected call of VotesNumAtHeight. +func (mr *MockStateInfoMockRecorder) VotesNumAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetIsSponsored", reflect.TypeOf((*MockStateInfo)(nil).AssetIsSponsored), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNumAtHeight", reflect.TypeOf((*MockStateInfo)(nil).VotesNumAtHeight), featureID, height) } -// AssetInfo mocks base method -func (m *MockStateInfo) AssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { +// WavesAddressesNumber mocks base method. +func (m *MockStateInfo) WavesAddressesNumber() (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssetInfo", assetID) - ret0, _ := ret[0].(*proto.AssetInfo) + ret := m.ctrl.Call(m, "WavesAddressesNumber") + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// AssetInfo indicates an expected call of AssetInfo -func (mr *MockStateInfoMockRecorder) AssetInfo(assetID interface{}) *gomock.Call { +// WavesAddressesNumber indicates an expected call of WavesAddressesNumber. +func (mr *MockStateInfoMockRecorder) WavesAddressesNumber() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetInfo", reflect.TypeOf((*MockStateInfo)(nil).AssetInfo), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WavesAddressesNumber", reflect.TypeOf((*MockStateInfo)(nil).WavesAddressesNumber)) } -// FullAssetInfo mocks base method -func (m *MockStateInfo) FullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FullAssetInfo", assetID) - ret0, _ := ret[0].(*proto.FullAssetInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 +// MockStateModifier is a mock of StateModifier interface. +type MockStateModifier struct { + ctrl *gomock.Controller + recorder *MockStateModifierMockRecorder } -// FullAssetInfo indicates an expected call of FullAssetInfo -func (mr *MockStateInfoMockRecorder) FullAssetInfo(assetID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullAssetInfo", reflect.TypeOf((*MockStateInfo)(nil).FullAssetInfo), assetID) +// MockStateModifierMockRecorder is the mock recorder for MockStateModifier. +type MockStateModifierMockRecorder struct { + mock *MockStateModifier } -// NFTList mocks base method -func (m *MockStateInfo) NFTList(account proto.Recipient, limit uint64, afterAssetID []byte) ([]*proto.FullAssetInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NFTList", account, limit, afterAssetID) - ret0, _ := ret[0].([]*proto.FullAssetInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 +// NewMockStateModifier creates a new mock instance. +func NewMockStateModifier(ctrl *gomock.Controller) *MockStateModifier { + mock := &MockStateModifier{ctrl: ctrl} + mock.recorder = &MockStateModifierMockRecorder{mock} + return mock } -// NFTList indicates an expected call of NFTList -func (mr *MockStateInfoMockRecorder) NFTList(account, limit, afterAssetID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NFTList", reflect.TypeOf((*MockStateInfo)(nil).NFTList), account, limit, afterAssetID) +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockStateModifier) EXPECT() *MockStateModifierMockRecorder { + return m.recorder } -// ScriptInfoByAccount mocks base method -func (m *MockStateInfo) ScriptInfoByAccount(account proto.Recipient) (*proto.ScriptInfo, error) { +// AddBlock mocks base method. +func (m *MockStateModifier) AddBlock(block []byte) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScriptInfoByAccount", account) - ret0, _ := ret[0].(*proto.ScriptInfo) + ret := m.ctrl.Call(m, "AddBlock", block) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScriptInfoByAccount indicates an expected call of ScriptInfoByAccount -func (mr *MockStateInfoMockRecorder) ScriptInfoByAccount(account interface{}) *gomock.Call { +// AddBlock indicates an expected call of AddBlock. +func (mr *MockStateModifierMockRecorder) AddBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAccount", reflect.TypeOf((*MockStateInfo)(nil).ScriptInfoByAccount), account) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlock", reflect.TypeOf((*MockStateModifier)(nil).AddBlock), block) } -// ScriptInfoByAsset mocks base method -func (m *MockStateInfo) ScriptInfoByAsset(assetID crypto.Digest) (*proto.ScriptInfo, error) { +// AddDeserializedBlock mocks base method. +func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScriptInfoByAsset", assetID) - ret0, _ := ret[0].(*proto.ScriptInfo) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScriptInfoByAsset indicates an expected call of ScriptInfoByAsset -func (mr *MockStateInfoMockRecorder) ScriptInfoByAsset(assetID interface{}) *gomock.Call { +// AddDeserializedBlock indicates an expected call of AddDeserializedBlock. +func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAsset", reflect.TypeOf((*MockStateInfo)(nil).ScriptInfoByAsset), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block) } -// IsActiveLeasing mocks base method -func (m *MockStateInfo) IsActiveLeasing(leaseID crypto.Digest) (bool, error) { +// AddNewBlocks mocks base method. +func (m *MockStateModifier) AddNewBlocks(blocks [][]byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsActiveLeasing", leaseID) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "AddNewBlocks", blocks) + ret0, _ := ret[0].(error) + return ret0 } -// IsActiveLeasing indicates an expected call of IsActiveLeasing -func (mr *MockStateInfoMockRecorder) IsActiveLeasing(leaseID interface{}) *gomock.Call { +// AddNewBlocks indicates an expected call of AddNewBlocks. +func (mr *MockStateModifierMockRecorder) AddNewBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveLeasing", reflect.TypeOf((*MockStateInfo)(nil).IsActiveLeasing), leaseID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddNewBlocks), blocks) } -// InvokeResultByID mocks base method -func (m *MockStateInfo) InvokeResultByID(invokeID crypto.Digest) (*proto.ScriptResult, error) { +// AddNewDeserializedBlocks mocks base method. +func (m *MockStateModifier) AddNewDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InvokeResultByID", invokeID) - ret0, _ := ret[0].(*proto.ScriptResult) + ret := m.ctrl.Call(m, "AddNewDeserializedBlocks", blocks) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// InvokeResultByID indicates an expected call of InvokeResultByID -func (mr *MockStateInfoMockRecorder) InvokeResultByID(invokeID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeResultByID", reflect.TypeOf((*MockStateInfo)(nil).InvokeResultByID), invokeID) -} - -// ProvidesExtendedApi mocks base method -func (m *MockStateInfo) ProvidesExtendedApi() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProvidesExtendedApi") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ProvidesExtendedApi indicates an expected call of ProvidesExtendedApi -func (mr *MockStateInfoMockRecorder) ProvidesExtendedApi() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesExtendedApi", reflect.TypeOf((*MockStateInfo)(nil).ProvidesExtendedApi)) -} - -// ProvidesStateHashes mocks base method -func (m *MockStateInfo) ProvidesStateHashes() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProvidesStateHashes") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ProvidesStateHashes indicates an expected call of ProvidesStateHashes -func (mr *MockStateInfoMockRecorder) ProvidesStateHashes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesStateHashes", reflect.TypeOf((*MockStateInfo)(nil).ProvidesStateHashes)) -} - -// StateHashAtHeight mocks base method -func (m *MockStateInfo) StateHashAtHeight(height uint64) (*proto.StateHash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StateHashAtHeight", height) - ret0, _ := ret[0].(*proto.StateHash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// StateHashAtHeight indicates an expected call of StateHashAtHeight -func (mr *MockStateInfoMockRecorder) StateHashAtHeight(height interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateHashAtHeight", reflect.TypeOf((*MockStateInfo)(nil).StateHashAtHeight), height) -} - -// MapR mocks base method -func (m *MockStateInfo) MapR(arg0 func(state.StateInfo) (interface{}, error)) (interface{}, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MapR", arg0) - ret0, _ := ret[0].(interface{}) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// MapR indicates an expected call of MapR -func (mr *MockStateInfoMockRecorder) MapR(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MapR", reflect.TypeOf((*MockStateInfo)(nil).MapR), arg0) -} - -// HitSourceAtHeight mocks base method -func (m *MockStateInfo) HitSourceAtHeight(height proto.Height) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HitSourceAtHeight", height) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// HitSourceAtHeight indicates an expected call of HitSourceAtHeight -func (mr *MockStateInfoMockRecorder) HitSourceAtHeight(height interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HitSourceAtHeight", reflect.TypeOf((*MockStateInfo)(nil).HitSourceAtHeight), height) -} - -// ShouldPersistAddressTransactions mocks base method -func (m *MockStateInfo) ShouldPersistAddressTransactions() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ShouldPersistAddressTransactions") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ShouldPersistAddressTransactions indicates an expected call of ShouldPersistAddressTransactions -func (mr *MockStateInfoMockRecorder) ShouldPersistAddressTransactions() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockStateInfo)(nil).ShouldPersistAddressTransactions)) -} - -// MockStateModifier is a mock of StateModifier interface -type MockStateModifier struct { - ctrl *gomock.Controller - recorder *MockStateModifierMockRecorder -} - -// MockStateModifierMockRecorder is the mock recorder for MockStateModifier -type MockStateModifierMockRecorder struct { - mock *MockStateModifier -} - -// NewMockStateModifier creates a new mock instance -func NewMockStateModifier(ctrl *gomock.Controller) *MockStateModifier { - mock := &MockStateModifier{ctrl: ctrl} - mock.recorder = &MockStateModifierMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockStateModifier) EXPECT() *MockStateModifierMockRecorder { - return m.recorder -} - -// AddBlock mocks base method -func (m *MockStateModifier) AddBlock(block []byte) (*proto.Block, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddBlock", block) - ret0, _ := ret[0].(*proto.Block) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddBlock indicates an expected call of AddBlock -func (mr *MockStateModifierMockRecorder) AddBlock(block interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlock", reflect.TypeOf((*MockStateModifier)(nil).AddBlock), block) -} - -// AddDeserializedBlock mocks base method -func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block) - ret0, _ := ret[0].(*proto.Block) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddDeserializedBlock indicates an expected call of AddDeserializedBlock -func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block) -} - -// AddNewBlocks mocks base method -func (m *MockStateModifier) AddNewBlocks(blocks [][]byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddNewBlocks", blocks) - ret0, _ := ret[0].(error) - return ret0 -} - -// AddNewBlocks indicates an expected call of AddNewBlocks -func (mr *MockStateModifierMockRecorder) AddNewBlocks(blocks interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddNewBlocks), blocks) -} - -// AddNewDeserializedBlocks mocks base method -func (m *MockStateModifier) AddNewDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddNewDeserializedBlocks", blocks) - ret0, _ := ret[0].(*proto.Block) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddNewDeserializedBlocks indicates an expected call of AddNewDeserializedBlocks +// AddNewDeserializedBlocks indicates an expected call of AddNewDeserializedBlocks. func (mr *MockStateModifierMockRecorder) AddNewDeserializedBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddNewDeserializedBlocks), blocks) } -// AddOldBlocks mocks base method +// AddOldBlocks mocks base method. func (m *MockStateModifier) AddOldBlocks(blocks [][]byte) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddOldBlocks", blocks) @@ -971,13 +957,13 @@ func (m *MockStateModifier) AddOldBlocks(blocks [][]byte) error { return ret0 } -// AddOldBlocks indicates an expected call of AddOldBlocks +// AddOldBlocks indicates an expected call of AddOldBlocks. func (mr *MockStateModifierMockRecorder) AddOldBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddOldBlocks), blocks) } -// AddOldDeserializedBlocks mocks base method +// AddOldDeserializedBlocks mocks base method. func (m *MockStateModifier) AddOldDeserializedBlocks(blocks []*proto.Block) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddOldDeserializedBlocks", blocks) @@ -985,109 +971,95 @@ func (m *MockStateModifier) AddOldDeserializedBlocks(blocks []*proto.Block) erro return ret0 } -// AddOldDeserializedBlocks indicates an expected call of AddOldDeserializedBlocks +// AddOldDeserializedBlocks indicates an expected call of AddOldDeserializedBlocks. func (mr *MockStateModifierMockRecorder) AddOldDeserializedBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddOldDeserializedBlocks), blocks) } -// RollbackToHeight mocks base method -func (m *MockStateModifier) RollbackToHeight(height proto.Height) error { +// Close mocks base method. +func (m *MockStateModifier) Close() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RollbackToHeight", height) + ret := m.ctrl.Call(m, "Close") ret0, _ := ret[0].(error) return ret0 } -// RollbackToHeight indicates an expected call of RollbackToHeight -func (mr *MockStateModifierMockRecorder) RollbackToHeight(height interface{}) *gomock.Call { +// Close indicates an expected call of Close. +func (mr *MockStateModifierMockRecorder) Close() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackToHeight", reflect.TypeOf((*MockStateModifier)(nil).RollbackToHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockStateModifier)(nil).Close)) } -// RollbackTo mocks base method -func (m *MockStateModifier) RollbackTo(removalEdge proto.BlockID) error { +// Map mocks base method. +func (m *MockStateModifier) Map(arg0 func(state.NonThreadSafeState) error) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RollbackTo", removalEdge) + ret := m.ctrl.Call(m, "Map", arg0) ret0, _ := ret[0].(error) return ret0 } -// RollbackTo indicates an expected call of RollbackTo -func (mr *MockStateModifierMockRecorder) RollbackTo(removalEdge interface{}) *gomock.Call { +// Map indicates an expected call of Map. +func (mr *MockStateModifierMockRecorder) Map(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackTo", reflect.TypeOf((*MockStateModifier)(nil).RollbackTo), removalEdge) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Map", reflect.TypeOf((*MockStateModifier)(nil).Map), arg0) } -// ValidateNextTx mocks base method -func (m *MockStateModifier) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, blockVersion proto.BlockVersion, acceptFailed bool) error { +// PersistAddressTransactions mocks base method. +func (m *MockStateModifier) PersistAddressTransactions() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ValidateNextTx", tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) + ret := m.ctrl.Call(m, "PersistAddressTransactions") ret0, _ := ret[0].(error) return ret0 } -// ValidateNextTx indicates an expected call of ValidateNextTx -func (mr *MockStateModifierMockRecorder) ValidateNextTx(tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed interface{}) *gomock.Call { +// PersistAddressTransactions indicates an expected call of PersistAddressTransactions. +func (mr *MockStateModifierMockRecorder) PersistAddressTransactions() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateNextTx", reflect.TypeOf((*MockStateModifier)(nil).ValidateNextTx), tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistAddressTransactions", reflect.TypeOf((*MockStateModifier)(nil).PersistAddressTransactions)) } -// ResetValidationList mocks base method +// ResetValidationList mocks base method. func (m *MockStateModifier) ResetValidationList() { m.ctrl.T.Helper() m.ctrl.Call(m, "ResetValidationList") } -// ResetValidationList indicates an expected call of ResetValidationList +// ResetValidationList indicates an expected call of ResetValidationList. func (mr *MockStateModifierMockRecorder) ResetValidationList() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetValidationList", reflect.TypeOf((*MockStateModifier)(nil).ResetValidationList)) } -// TxValidation mocks base method -func (m *MockStateModifier) TxValidation(arg0 func(state.TxValidation) error) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TxValidation", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// TxValidation indicates an expected call of TxValidation -func (mr *MockStateModifierMockRecorder) TxValidation(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxValidation", reflect.TypeOf((*MockStateModifier)(nil).TxValidation), arg0) -} - -// Map mocks base method -func (m *MockStateModifier) Map(arg0 func(state.NonThreadSafeState) error) error { +// RollbackTo mocks base method. +func (m *MockStateModifier) RollbackTo(removalEdge proto.BlockID) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Map", arg0) + ret := m.ctrl.Call(m, "RollbackTo", removalEdge) ret0, _ := ret[0].(error) return ret0 } -// Map indicates an expected call of Map -func (mr *MockStateModifierMockRecorder) Map(arg0 interface{}) *gomock.Call { +// RollbackTo indicates an expected call of RollbackTo. +func (mr *MockStateModifierMockRecorder) RollbackTo(removalEdge interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Map", reflect.TypeOf((*MockStateModifier)(nil).Map), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackTo", reflect.TypeOf((*MockStateModifier)(nil).RollbackTo), removalEdge) } -// SavePeers mocks base method -func (m *MockStateModifier) SavePeers(arg0 []proto.TCPAddr) error { +// RollbackToHeight mocks base method. +func (m *MockStateModifier) RollbackToHeight(height proto.Height) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SavePeers", arg0) + ret := m.ctrl.Call(m, "RollbackToHeight", height) ret0, _ := ret[0].(error) return ret0 } -// SavePeers indicates an expected call of SavePeers -func (mr *MockStateModifierMockRecorder) SavePeers(arg0 interface{}) *gomock.Call { +// RollbackToHeight indicates an expected call of RollbackToHeight. +func (mr *MockStateModifierMockRecorder) RollbackToHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SavePeers", reflect.TypeOf((*MockStateModifier)(nil).SavePeers), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackToHeight", reflect.TypeOf((*MockStateModifier)(nil).RollbackToHeight), height) } -// StartProvidingExtendedApi mocks base method +// StartProvidingExtendedApi mocks base method. func (m *MockStateModifier) StartProvidingExtendedApi() error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StartProvidingExtendedApi") @@ -1095,64 +1067,64 @@ func (m *MockStateModifier) StartProvidingExtendedApi() error { return ret0 } -// StartProvidingExtendedApi indicates an expected call of StartProvidingExtendedApi +// StartProvidingExtendedApi indicates an expected call of StartProvidingExtendedApi. func (mr *MockStateModifierMockRecorder) StartProvidingExtendedApi() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartProvidingExtendedApi", reflect.TypeOf((*MockStateModifier)(nil).StartProvidingExtendedApi)) } -// PersistAddressTransactions mocks base method -func (m *MockStateModifier) PersistAddressTransactions() error { +// TxValidation mocks base method. +func (m *MockStateModifier) TxValidation(arg0 func(state.TxValidation) error) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistAddressTransactions") + ret := m.ctrl.Call(m, "TxValidation", arg0) ret0, _ := ret[0].(error) return ret0 } -// PersistAddressTransactions indicates an expected call of PersistAddressTransactions -func (mr *MockStateModifierMockRecorder) PersistAddressTransactions() *gomock.Call { +// TxValidation indicates an expected call of TxValidation. +func (mr *MockStateModifierMockRecorder) TxValidation(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistAddressTransactions", reflect.TypeOf((*MockStateModifier)(nil).PersistAddressTransactions)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxValidation", reflect.TypeOf((*MockStateModifier)(nil).TxValidation), arg0) } -// Close mocks base method -func (m *MockStateModifier) Close() error { +// ValidateNextTx mocks base method. +func (m *MockStateModifier) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, blockVersion proto.BlockVersion, acceptFailed bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Close") + ret := m.ctrl.Call(m, "ValidateNextTx", tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) ret0, _ := ret[0].(error) return ret0 } -// Close indicates an expected call of Close -func (mr *MockStateModifierMockRecorder) Close() *gomock.Call { +// ValidateNextTx indicates an expected call of ValidateNextTx. +func (mr *MockStateModifierMockRecorder) ValidateNextTx(tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockStateModifier)(nil).Close)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateNextTx", reflect.TypeOf((*MockStateModifier)(nil).ValidateNextTx), tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) } -// MockTxValidation is a mock of TxValidation interface +// MockTxValidation is a mock of TxValidation interface. type MockTxValidation struct { ctrl *gomock.Controller recorder *MockTxValidationMockRecorder } -// MockTxValidationMockRecorder is the mock recorder for MockTxValidation +// MockTxValidationMockRecorder is the mock recorder for MockTxValidation. type MockTxValidationMockRecorder struct { mock *MockTxValidation } -// NewMockTxValidation creates a new mock instance +// NewMockTxValidation creates a new mock instance. func NewMockTxValidation(ctrl *gomock.Controller) *MockTxValidation { mock := &MockTxValidation{ctrl: ctrl} mock.recorder = &MockTxValidationMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockTxValidation) EXPECT() *MockTxValidationMockRecorder { return m.recorder } -// ValidateNextTx mocks base method +// ValidateNextTx mocks base method. func (m *MockTxValidation) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, blockVersion proto.BlockVersion, acceptFailed bool) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ValidateNextTx", tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) @@ -1160,245 +1132,273 @@ func (m *MockTxValidation) ValidateNextTx(tx proto.Transaction, currentTimestamp return ret0 } -// ValidateNextTx indicates an expected call of ValidateNextTx +// ValidateNextTx indicates an expected call of ValidateNextTx. func (mr *MockTxValidationMockRecorder) ValidateNextTx(tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateNextTx", reflect.TypeOf((*MockTxValidation)(nil).ValidateNextTx), tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) } -// MockState is a mock of State interface +// MockState is a mock of State interface. type MockState struct { ctrl *gomock.Controller recorder *MockStateMockRecorder } -// MockStateMockRecorder is the mock recorder for MockState +// MockStateMockRecorder is the mock recorder for MockState. type MockStateMockRecorder struct { mock *MockState } -// NewMockState creates a new mock instance +// NewMockState creates a new mock instance. func NewMockState(ctrl *gomock.Controller) *MockState { mock := &MockState{ctrl: ctrl} mock.recorder = &MockStateMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockState) EXPECT() *MockStateMockRecorder { return m.recorder } -// TopBlock mocks base method -func (m *MockState) TopBlock() *proto.Block { +// AccountBalance mocks base method. +func (m *MockState) AccountBalance(account proto.Recipient, asset []byte) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TopBlock") - ret0, _ := ret[0].(*proto.Block) - return ret0 + ret := m.ctrl.Call(m, "AccountBalance", account, asset) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// TopBlock indicates an expected call of TopBlock -func (mr *MockStateMockRecorder) TopBlock() *gomock.Call { +// AccountBalance indicates an expected call of AccountBalance. +func (mr *MockStateMockRecorder) AccountBalance(account, asset interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopBlock", reflect.TypeOf((*MockState)(nil).TopBlock)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountBalance", reflect.TypeOf((*MockState)(nil).AccountBalance), account, asset) } -// Block mocks base method -func (m *MockState) Block(blockID proto.BlockID) (*proto.Block, error) { +// ActivationHeight mocks base method. +func (m *MockState) ActivationHeight(featureID int16) (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Block", blockID) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "ActivationHeight", featureID) + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// Block indicates an expected call of Block -func (mr *MockStateMockRecorder) Block(blockID interface{}) *gomock.Call { +// ActivationHeight indicates an expected call of ActivationHeight. +func (mr *MockStateMockRecorder) ActivationHeight(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Block", reflect.TypeOf((*MockState)(nil).Block), blockID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivationHeight", reflect.TypeOf((*MockState)(nil).ActivationHeight), featureID) } -// BlockByHeight mocks base method -func (m *MockState) BlockByHeight(height proto.Height) (*proto.Block, error) { +// AddBlock mocks base method. +func (m *MockState) AddBlock(block []byte) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockByHeight", height) + ret := m.ctrl.Call(m, "AddBlock", block) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// BlockByHeight indicates an expected call of BlockByHeight -func (mr *MockStateMockRecorder) BlockByHeight(height interface{}) *gomock.Call { +// AddBlock indicates an expected call of AddBlock. +func (mr *MockStateMockRecorder) AddBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHeight", reflect.TypeOf((*MockState)(nil).BlockByHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlock", reflect.TypeOf((*MockState)(nil).AddBlock), block) } -// Header mocks base method -func (m *MockState) Header(blockID proto.BlockID) (*proto.BlockHeader, error) { +// AddDeserializedBlock mocks base method. +func (m *MockState) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Header", blockID) - ret0, _ := ret[0].(*proto.BlockHeader) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// Header indicates an expected call of Header -func (mr *MockStateMockRecorder) Header(blockID interface{}) *gomock.Call { +// AddDeserializedBlock indicates an expected call of AddDeserializedBlock. +func (mr *MockStateMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockState)(nil).Header), blockID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block) } -// HeaderByHeight mocks base method -func (m *MockState) HeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { +// AddNewBlocks mocks base method. +func (m *MockState) AddNewBlocks(blocks [][]byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeaderByHeight", height) - ret0, _ := ret[0].(*proto.BlockHeader) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "AddNewBlocks", blocks) + ret0, _ := ret[0].(error) + return ret0 } -// HeaderByHeight indicates an expected call of HeaderByHeight -func (mr *MockStateMockRecorder) HeaderByHeight(height interface{}) *gomock.Call { +// AddNewBlocks indicates an expected call of AddNewBlocks. +func (mr *MockStateMockRecorder) AddNewBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHeight", reflect.TypeOf((*MockState)(nil).HeaderByHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewBlocks", reflect.TypeOf((*MockState)(nil).AddNewBlocks), blocks) } -// Height mocks base method -func (m *MockState) Height() (proto.Height, error) { +// AddNewDeserializedBlocks mocks base method. +func (m *MockState) AddNewDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Height") - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "AddNewDeserializedBlocks", blocks) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// Height indicates an expected call of Height -func (mr *MockStateMockRecorder) Height() *gomock.Call { +// AddNewDeserializedBlocks indicates an expected call of AddNewDeserializedBlocks. +func (mr *MockStateMockRecorder) AddNewDeserializedBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Height", reflect.TypeOf((*MockState)(nil).Height)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddNewDeserializedBlocks), blocks) } -// BlockIDToHeight mocks base method -func (m *MockState) BlockIDToHeight(blockID proto.BlockID) (proto.Height, error) { +// AddOldBlocks mocks base method. +func (m *MockState) AddOldBlocks(blocks [][]byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockIDToHeight", blockID) - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "AddOldBlocks", blocks) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddOldBlocks indicates an expected call of AddOldBlocks. +func (mr *MockStateMockRecorder) AddOldBlocks(blocks interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldBlocks", reflect.TypeOf((*MockState)(nil).AddOldBlocks), blocks) +} + +// AddOldDeserializedBlocks mocks base method. +func (m *MockState) AddOldDeserializedBlocks(blocks []*proto.Block) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddOldDeserializedBlocks", blocks) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddOldDeserializedBlocks indicates an expected call of AddOldDeserializedBlocks. +func (mr *MockStateMockRecorder) AddOldDeserializedBlocks(blocks interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddOldDeserializedBlocks), blocks) +} + +// AddrByAlias mocks base method. +func (m *MockState) AddrByAlias(alias proto.Alias) (proto.Address, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddrByAlias", alias) + ret0, _ := ret[0].(proto.Address) ret1, _ := ret[1].(error) return ret0, ret1 } -// BlockIDToHeight indicates an expected call of BlockIDToHeight -func (mr *MockStateMockRecorder) BlockIDToHeight(blockID interface{}) *gomock.Call { +// AddrByAlias indicates an expected call of AddrByAlias. +func (mr *MockStateMockRecorder) AddrByAlias(alias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockIDToHeight", reflect.TypeOf((*MockState)(nil).BlockIDToHeight), blockID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrByAlias", reflect.TypeOf((*MockState)(nil).AddrByAlias), alias) } -// HeightToBlockID mocks base method -func (m *MockState) HeightToBlockID(height proto.Height) (proto.BlockID, error) { +// AllFeatures mocks base method. +func (m *MockState) AllFeatures() ([]int16, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeightToBlockID", height) - ret0, _ := ret[0].(proto.BlockID) + ret := m.ctrl.Call(m, "AllFeatures") + ret0, _ := ret[0].([]int16) ret1, _ := ret[1].(error) return ret0, ret1 } -// HeightToBlockID indicates an expected call of HeightToBlockID -func (mr *MockStateMockRecorder) HeightToBlockID(height interface{}) *gomock.Call { +// AllFeatures indicates an expected call of AllFeatures. +func (mr *MockStateMockRecorder) AllFeatures() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeightToBlockID", reflect.TypeOf((*MockState)(nil).HeightToBlockID), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllFeatures", reflect.TypeOf((*MockState)(nil).AllFeatures)) } -// FullWavesBalance mocks base method -func (m *MockState) FullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { +// ApprovalHeight mocks base method. +func (m *MockState) ApprovalHeight(featureID int16) (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FullWavesBalance", account) - ret0, _ := ret[0].(*proto.FullWavesBalance) + ret := m.ctrl.Call(m, "ApprovalHeight", featureID) + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// FullWavesBalance indicates an expected call of FullWavesBalance -func (mr *MockStateMockRecorder) FullWavesBalance(account interface{}) *gomock.Call { +// ApprovalHeight indicates an expected call of ApprovalHeight. +func (mr *MockStateMockRecorder) ApprovalHeight(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullWavesBalance", reflect.TypeOf((*MockState)(nil).FullWavesBalance), account) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApprovalHeight", reflect.TypeOf((*MockState)(nil).ApprovalHeight), featureID) } -// EffectiveBalance mocks base method -func (m *MockState) EffectiveBalance(account proto.Recipient, startHeight, endHeight proto.Height) (uint64, error) { +// AssetInfo mocks base method. +func (m *MockState) AssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EffectiveBalance", account, startHeight, endHeight) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "AssetInfo", assetID) + ret0, _ := ret[0].(*proto.AssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// EffectiveBalance indicates an expected call of EffectiveBalance -func (mr *MockStateMockRecorder) EffectiveBalance(account, startHeight, endHeight interface{}) *gomock.Call { +// AssetInfo indicates an expected call of AssetInfo. +func (mr *MockStateMockRecorder) AssetInfo(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EffectiveBalance", reflect.TypeOf((*MockState)(nil).EffectiveBalance), account, startHeight, endHeight) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetInfo", reflect.TypeOf((*MockState)(nil).AssetInfo), assetID) } -// AccountBalance mocks base method -func (m *MockState) AccountBalance(account proto.Recipient, asset []byte) (uint64, error) { +// AssetIsSponsored mocks base method. +func (m *MockState) AssetIsSponsored(assetID crypto.Digest) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AccountBalance", account, asset) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "AssetIsSponsored", assetID) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// AccountBalance indicates an expected call of AccountBalance -func (mr *MockStateMockRecorder) AccountBalance(account, asset interface{}) *gomock.Call { +// AssetIsSponsored indicates an expected call of AssetIsSponsored. +func (mr *MockStateMockRecorder) AssetIsSponsored(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountBalance", reflect.TypeOf((*MockState)(nil).AccountBalance), account, asset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetIsSponsored", reflect.TypeOf((*MockState)(nil).AssetIsSponsored), assetID) } -// WavesAddressesNumber mocks base method -func (m *MockState) WavesAddressesNumber() (uint64, error) { +// Block mocks base method. +func (m *MockState) Block(blockID proto.BlockID) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WavesAddressesNumber") - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "Block", blockID) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// WavesAddressesNumber indicates an expected call of WavesAddressesNumber -func (mr *MockStateMockRecorder) WavesAddressesNumber() *gomock.Call { +// Block indicates an expected call of Block. +func (mr *MockStateMockRecorder) Block(blockID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WavesAddressesNumber", reflect.TypeOf((*MockState)(nil).WavesAddressesNumber)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Block", reflect.TypeOf((*MockState)(nil).Block), blockID) } -// ScoreAtHeight mocks base method -func (m *MockState) ScoreAtHeight(height proto.Height) (*big.Int, error) { +// BlockByHeight mocks base method. +func (m *MockState) BlockByHeight(height proto.Height) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScoreAtHeight", height) - ret0, _ := ret[0].(*big.Int) + ret := m.ctrl.Call(m, "BlockByHeight", height) + ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScoreAtHeight indicates an expected call of ScoreAtHeight -func (mr *MockStateMockRecorder) ScoreAtHeight(height interface{}) *gomock.Call { +// BlockByHeight indicates an expected call of BlockByHeight. +func (mr *MockStateMockRecorder) BlockByHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScoreAtHeight", reflect.TypeOf((*MockState)(nil).ScoreAtHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHeight", reflect.TypeOf((*MockState)(nil).BlockByHeight), height) } -// CurrentScore mocks base method -func (m *MockState) CurrentScore() (*big.Int, error) { +// BlockIDToHeight mocks base method. +func (m *MockState) BlockIDToHeight(blockID proto.BlockID) (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CurrentScore") - ret0, _ := ret[0].(*big.Int) + ret := m.ctrl.Call(m, "BlockIDToHeight", blockID) + ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// CurrentScore indicates an expected call of CurrentScore -func (mr *MockStateMockRecorder) CurrentScore() *gomock.Call { +// BlockIDToHeight indicates an expected call of BlockIDToHeight. +func (mr *MockStateMockRecorder) BlockIDToHeight(blockID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentScore", reflect.TypeOf((*MockState)(nil).CurrentScore)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockIDToHeight", reflect.TypeOf((*MockState)(nil).BlockIDToHeight), blockID) } -// BlockchainSettings mocks base method +// BlockchainSettings mocks base method. func (m *MockState) BlockchainSettings() (*settings.BlockchainSettings, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockchainSettings") @@ -1407,329 +1407,311 @@ func (m *MockState) BlockchainSettings() (*settings.BlockchainSettings, error) { return ret0, ret1 } -// BlockchainSettings indicates an expected call of BlockchainSettings +// BlockchainSettings indicates an expected call of BlockchainSettings. func (mr *MockStateMockRecorder) BlockchainSettings() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockchainSettings", reflect.TypeOf((*MockState)(nil).BlockchainSettings)) } -// Peers mocks base method -func (m *MockState) Peers() ([]proto.TCPAddr, error) { +// Close mocks base method. +func (m *MockState) Close() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Peers") - ret0, _ := ret[0].([]proto.TCPAddr) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 } -// Peers indicates an expected call of Peers -func (mr *MockStateMockRecorder) Peers() *gomock.Call { +// Close indicates an expected call of Close. +func (mr *MockStateMockRecorder) Close() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Peers", reflect.TypeOf((*MockState)(nil).Peers)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockState)(nil).Close)) } -// VotesNum mocks base method -func (m *MockState) VotesNum(featureID int16) (uint64, error) { +// CurrentScore mocks base method. +func (m *MockState) CurrentScore() (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VotesNum", featureID) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "CurrentScore") + ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } -// VotesNum indicates an expected call of VotesNum -func (mr *MockStateMockRecorder) VotesNum(featureID interface{}) *gomock.Call { +// CurrentScore indicates an expected call of CurrentScore. +func (mr *MockStateMockRecorder) CurrentScore() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNum", reflect.TypeOf((*MockState)(nil).VotesNum), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentScore", reflect.TypeOf((*MockState)(nil).CurrentScore)) } -// VotesNumAtHeight mocks base method -func (m *MockState) VotesNumAtHeight(featureID int16, height proto.Height) (uint64, error) { +// EffectiveBalance mocks base method. +func (m *MockState) EffectiveBalance(account proto.Recipient, startHeight, endHeight proto.Height) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VotesNumAtHeight", featureID, height) + ret := m.ctrl.Call(m, "EffectiveBalance", account, startHeight, endHeight) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// VotesNumAtHeight indicates an expected call of VotesNumAtHeight -func (mr *MockStateMockRecorder) VotesNumAtHeight(featureID, height interface{}) *gomock.Call { +// EffectiveBalance indicates an expected call of EffectiveBalance. +func (mr *MockStateMockRecorder) EffectiveBalance(account, startHeight, endHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNumAtHeight", reflect.TypeOf((*MockState)(nil).VotesNumAtHeight), featureID, height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EffectiveBalance", reflect.TypeOf((*MockState)(nil).EffectiveBalance), account, startHeight, endHeight) } -// IsActivated mocks base method -func (m *MockState) IsActivated(featureID int16) (bool, error) { +// EstimatorVersion mocks base method. +func (m *MockState) EstimatorVersion() (int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsActivated", featureID) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "EstimatorVersion") + ret0, _ := ret[0].(int) ret1, _ := ret[1].(error) return ret0, ret1 } -// IsActivated indicates an expected call of IsActivated -func (mr *MockStateMockRecorder) IsActivated(featureID interface{}) *gomock.Call { +// EstimatorVersion indicates an expected call of EstimatorVersion. +func (mr *MockStateMockRecorder) EstimatorVersion() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActivated", reflect.TypeOf((*MockState)(nil).IsActivated), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimatorVersion", reflect.TypeOf((*MockState)(nil).EstimatorVersion)) } -// IsActiveAtHeight mocks base method -func (m *MockState) IsActiveAtHeight(featureID int16, height proto.Height) (bool, error) { +// FullAssetInfo mocks base method. +func (m *MockState) FullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsActiveAtHeight", featureID, height) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "FullAssetInfo", assetID) + ret0, _ := ret[0].(*proto.FullAssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// IsActiveAtHeight indicates an expected call of IsActiveAtHeight -func (mr *MockStateMockRecorder) IsActiveAtHeight(featureID, height interface{}) *gomock.Call { +// FullAssetInfo indicates an expected call of FullAssetInfo. +func (mr *MockStateMockRecorder) FullAssetInfo(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveAtHeight", reflect.TypeOf((*MockState)(nil).IsActiveAtHeight), featureID, height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullAssetInfo", reflect.TypeOf((*MockState)(nil).FullAssetInfo), assetID) } -// ActivationHeight mocks base method -func (m *MockState) ActivationHeight(featureID int16) (proto.Height, error) { +// FullWavesBalance mocks base method. +func (m *MockState) FullWavesBalance(account proto.Recipient) (*proto.FullWavesBalance, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ActivationHeight", featureID) - ret0, _ := ret[0].(proto.Height) + ret := m.ctrl.Call(m, "FullWavesBalance", account) + ret0, _ := ret[0].(*proto.FullWavesBalance) ret1, _ := ret[1].(error) return ret0, ret1 } -// ActivationHeight indicates an expected call of ActivationHeight -func (mr *MockStateMockRecorder) ActivationHeight(featureID interface{}) *gomock.Call { +// FullWavesBalance indicates an expected call of FullWavesBalance. +func (mr *MockStateMockRecorder) FullWavesBalance(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivationHeight", reflect.TypeOf((*MockState)(nil).ActivationHeight), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullWavesBalance", reflect.TypeOf((*MockState)(nil).FullWavesBalance), account) } -// IsApproved mocks base method -func (m *MockState) IsApproved(featureID int16) (bool, error) { +// Header mocks base method. +func (m *MockState) Header(blockID proto.BlockID) (*proto.BlockHeader, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsApproved", featureID) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "Header", blockID) + ret0, _ := ret[0].(*proto.BlockHeader) ret1, _ := ret[1].(error) return ret0, ret1 } -// IsApproved indicates an expected call of IsApproved -func (mr *MockStateMockRecorder) IsApproved(featureID interface{}) *gomock.Call { +// Header indicates an expected call of Header. +func (mr *MockStateMockRecorder) Header(blockID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApproved", reflect.TypeOf((*MockState)(nil).IsApproved), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockState)(nil).Header), blockID) } -// IsApprovedAtHeight mocks base method -func (m *MockState) IsApprovedAtHeight(featureID int16, height proto.Height) (bool, error) { +// HeaderByHeight mocks base method. +func (m *MockState) HeaderByHeight(height proto.Height) (*proto.BlockHeader, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsApprovedAtHeight", featureID, height) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "HeaderByHeight", height) + ret0, _ := ret[0].(*proto.BlockHeader) ret1, _ := ret[1].(error) return ret0, ret1 } -// IsApprovedAtHeight indicates an expected call of IsApprovedAtHeight -func (mr *MockStateMockRecorder) IsApprovedAtHeight(featureID, height interface{}) *gomock.Call { +// HeaderByHeight indicates an expected call of HeaderByHeight. +func (mr *MockStateMockRecorder) HeaderByHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApprovedAtHeight", reflect.TypeOf((*MockState)(nil).IsApprovedAtHeight), featureID, height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHeight", reflect.TypeOf((*MockState)(nil).HeaderByHeight), height) } -// ApprovalHeight mocks base method -func (m *MockState) ApprovalHeight(featureID int16) (proto.Height, error) { +// Height mocks base method. +func (m *MockState) Height() (proto.Height, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ApprovalHeight", featureID) + ret := m.ctrl.Call(m, "Height") ret0, _ := ret[0].(proto.Height) ret1, _ := ret[1].(error) return ret0, ret1 } -// ApprovalHeight indicates an expected call of ApprovalHeight -func (mr *MockStateMockRecorder) ApprovalHeight(featureID interface{}) *gomock.Call { +// Height indicates an expected call of Height. +func (mr *MockStateMockRecorder) Height() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApprovalHeight", reflect.TypeOf((*MockState)(nil).ApprovalHeight), featureID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Height", reflect.TypeOf((*MockState)(nil).Height)) } -// AllFeatures mocks base method -func (m *MockState) AllFeatures() ([]int16, error) { +// HeightToBlockID mocks base method. +func (m *MockState) HeightToBlockID(height proto.Height) (proto.BlockID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AllFeatures") - ret0, _ := ret[0].([]int16) + ret := m.ctrl.Call(m, "HeightToBlockID", height) + ret0, _ := ret[0].(proto.BlockID) ret1, _ := ret[1].(error) return ret0, ret1 } -// AllFeatures indicates an expected call of AllFeatures -func (mr *MockStateMockRecorder) AllFeatures() *gomock.Call { +// HeightToBlockID indicates an expected call of HeightToBlockID. +func (mr *MockStateMockRecorder) HeightToBlockID(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllFeatures", reflect.TypeOf((*MockState)(nil).AllFeatures)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeightToBlockID", reflect.TypeOf((*MockState)(nil).HeightToBlockID), height) } -// EstimatorVersion mocks base method -func (m *MockState) EstimatorVersion() (int, error) { +// HitSourceAtHeight mocks base method. +func (m *MockState) HitSourceAtHeight(height proto.Height) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EstimatorVersion") - ret0, _ := ret[0].(int) + ret := m.ctrl.Call(m, "HitSourceAtHeight", height) + ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } -// EstimatorVersion indicates an expected call of EstimatorVersion -func (mr *MockStateMockRecorder) EstimatorVersion() *gomock.Call { +// HitSourceAtHeight indicates an expected call of HitSourceAtHeight. +func (mr *MockStateMockRecorder) HitSourceAtHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimatorVersion", reflect.TypeOf((*MockState)(nil).EstimatorVersion)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HitSourceAtHeight", reflect.TypeOf((*MockState)(nil).HitSourceAtHeight), height) } -// AddrByAlias mocks base method -func (m *MockState) AddrByAlias(alias proto.Alias) (proto.Address, error) { +// InvokeResultByID mocks base method. +func (m *MockState) InvokeResultByID(invokeID crypto.Digest) (*proto.ScriptResult, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddrByAlias", alias) - ret0, _ := ret[0].(proto.Address) + ret := m.ctrl.Call(m, "InvokeResultByID", invokeID) + ret0, _ := ret[0].(*proto.ScriptResult) ret1, _ := ret[1].(error) return ret0, ret1 } -// AddrByAlias indicates an expected call of AddrByAlias -func (mr *MockStateMockRecorder) AddrByAlias(alias interface{}) *gomock.Call { +// InvokeResultByID indicates an expected call of InvokeResultByID. +func (mr *MockStateMockRecorder) InvokeResultByID(invokeID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrByAlias", reflect.TypeOf((*MockState)(nil).AddrByAlias), alias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeResultByID", reflect.TypeOf((*MockState)(nil).InvokeResultByID), invokeID) } -// RetrieveEntries mocks base method -func (m *MockState) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { +// IsActivated mocks base method. +func (m *MockState) IsActivated(featureID int16) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveEntries", account) - ret0, _ := ret[0].([]proto.DataEntry) + ret := m.ctrl.Call(m, "IsActivated", featureID) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveEntries indicates an expected call of RetrieveEntries -func (mr *MockStateMockRecorder) RetrieveEntries(account interface{}) *gomock.Call { +// IsActivated indicates an expected call of IsActivated. +func (mr *MockStateMockRecorder) IsActivated(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntries", reflect.TypeOf((*MockState)(nil).RetrieveEntries), account) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActivated", reflect.TypeOf((*MockState)(nil).IsActivated), featureID) } -// RetrieveEntry mocks base method -func (m *MockState) RetrieveEntry(account proto.Recipient, key string) (proto.DataEntry, error) { +// IsActiveAtHeight mocks base method. +func (m *MockState) IsActiveAtHeight(featureID int16, height proto.Height) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveEntry", account, key) - ret0, _ := ret[0].(proto.DataEntry) + ret := m.ctrl.Call(m, "IsActiveAtHeight", featureID, height) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveEntry indicates an expected call of RetrieveEntry -func (mr *MockStateMockRecorder) RetrieveEntry(account, key interface{}) *gomock.Call { +// IsActiveAtHeight indicates an expected call of IsActiveAtHeight. +func (mr *MockStateMockRecorder) IsActiveAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntry", reflect.TypeOf((*MockState)(nil).RetrieveEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveAtHeight", reflect.TypeOf((*MockState)(nil).IsActiveAtHeight), featureID, height) } -// RetrieveIntegerEntry mocks base method -func (m *MockState) RetrieveIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { +// IsActiveLeasing mocks base method. +func (m *MockState) IsActiveLeasing(leaseID crypto.Digest) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveIntegerEntry", account, key) - ret0, _ := ret[0].(*proto.IntegerDataEntry) + ret := m.ctrl.Call(m, "IsActiveLeasing", leaseID) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveIntegerEntry indicates an expected call of RetrieveIntegerEntry -func (mr *MockStateMockRecorder) RetrieveIntegerEntry(account, key interface{}) *gomock.Call { +// IsActiveLeasing indicates an expected call of IsActiveLeasing. +func (mr *MockStateMockRecorder) IsActiveLeasing(leaseID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveIntegerEntry", reflect.TypeOf((*MockState)(nil).RetrieveIntegerEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveLeasing", reflect.TypeOf((*MockState)(nil).IsActiveLeasing), leaseID) } -// RetrieveBooleanEntry mocks base method -func (m *MockState) RetrieveBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { +// IsApproved mocks base method. +func (m *MockState) IsApproved(featureID int16) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveBooleanEntry", account, key) - ret0, _ := ret[0].(*proto.BooleanDataEntry) + ret := m.ctrl.Call(m, "IsApproved", featureID) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveBooleanEntry indicates an expected call of RetrieveBooleanEntry -func (mr *MockStateMockRecorder) RetrieveBooleanEntry(account, key interface{}) *gomock.Call { +// IsApproved indicates an expected call of IsApproved. +func (mr *MockStateMockRecorder) IsApproved(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBooleanEntry", reflect.TypeOf((*MockState)(nil).RetrieveBooleanEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApproved", reflect.TypeOf((*MockState)(nil).IsApproved), featureID) } -// RetrieveStringEntry mocks base method -func (m *MockState) RetrieveStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { +// IsApprovedAtHeight mocks base method. +func (m *MockState) IsApprovedAtHeight(featureID int16, height proto.Height) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveStringEntry", account, key) - ret0, _ := ret[0].(*proto.StringDataEntry) + ret := m.ctrl.Call(m, "IsApprovedAtHeight", featureID, height) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveStringEntry indicates an expected call of RetrieveStringEntry -func (mr *MockStateMockRecorder) RetrieveStringEntry(account, key interface{}) *gomock.Call { +// IsApprovedAtHeight indicates an expected call of IsApprovedAtHeight. +func (mr *MockStateMockRecorder) IsApprovedAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveStringEntry", reflect.TypeOf((*MockState)(nil).RetrieveStringEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApprovedAtHeight", reflect.TypeOf((*MockState)(nil).IsApprovedAtHeight), featureID, height) } -// RetrieveBinaryEntry mocks base method -func (m *MockState) RetrieveBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { +// Map mocks base method. +func (m *MockState) Map(arg0 func(state.NonThreadSafeState) error) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RetrieveBinaryEntry", account, key) - ret0, _ := ret[0].(*proto.BinaryDataEntry) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "Map", arg0) + ret0, _ := ret[0].(error) + return ret0 } -// RetrieveBinaryEntry indicates an expected call of RetrieveBinaryEntry -func (mr *MockStateMockRecorder) RetrieveBinaryEntry(account, key interface{}) *gomock.Call { +// Map indicates an expected call of Map. +func (mr *MockStateMockRecorder) Map(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBinaryEntry", reflect.TypeOf((*MockState)(nil).RetrieveBinaryEntry), account, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Map", reflect.TypeOf((*MockState)(nil).Map), arg0) } -// TransactionByID mocks base method -func (m *MockState) TransactionByID(id []byte) (proto.Transaction, error) { +// MapR mocks base method. +func (m *MockState) MapR(arg0 func(state.StateInfo) (interface{}, error)) (interface{}, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransactionByID", id) - ret0, _ := ret[0].(proto.Transaction) + ret := m.ctrl.Call(m, "MapR", arg0) + ret0, _ := ret[0].(interface{}) ret1, _ := ret[1].(error) return ret0, ret1 } -// TransactionByID indicates an expected call of TransactionByID -func (mr *MockStateMockRecorder) TransactionByID(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByID", reflect.TypeOf((*MockState)(nil).TransactionByID), id) -} - -// TransactionByIDWithStatus mocks base method -func (m *MockState) TransactionByIDWithStatus(id []byte) (proto.Transaction, bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransactionByIDWithStatus", id) - ret0, _ := ret[0].(proto.Transaction) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// TransactionByIDWithStatus indicates an expected call of TransactionByIDWithStatus -func (mr *MockStateMockRecorder) TransactionByIDWithStatus(id interface{}) *gomock.Call { +// MapR indicates an expected call of MapR. +func (mr *MockStateMockRecorder) MapR(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByIDWithStatus", reflect.TypeOf((*MockState)(nil).TransactionByIDWithStatus), id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MapR", reflect.TypeOf((*MockState)(nil).MapR), arg0) } -// TransactionHeightByID mocks base method -func (m *MockState) TransactionHeightByID(id []byte) (uint64, error) { +// NFTList mocks base method. +func (m *MockState) NFTList(account proto.Recipient, limit uint64, afterAssetID []byte) ([]*proto.FullAssetInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransactionHeightByID", id) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "NFTList", account, limit, afterAssetID) + ret0, _ := ret[0].([]*proto.FullAssetInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// TransactionHeightByID indicates an expected call of TransactionHeightByID -func (mr *MockStateMockRecorder) TransactionHeightByID(id interface{}) *gomock.Call { +// NFTList indicates an expected call of NFTList. +func (mr *MockStateMockRecorder) NFTList(account, limit, afterAssetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionHeightByID", reflect.TypeOf((*MockState)(nil).TransactionHeightByID), id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NFTList", reflect.TypeOf((*MockState)(nil).NFTList), account, limit, afterAssetID) } -// NewAddrTransactionsIterator mocks base method +// NewAddrTransactionsIterator mocks base method. func (m *MockState) NewAddrTransactionsIterator(addr proto.Address) (state.TransactionIterator, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NewAddrTransactionsIterator", addr) @@ -1738,364 +1720,336 @@ func (m *MockState) NewAddrTransactionsIterator(addr proto.Address) (state.Trans return ret0, ret1 } -// NewAddrTransactionsIterator indicates an expected call of NewAddrTransactionsIterator +// NewAddrTransactionsIterator indicates an expected call of NewAddrTransactionsIterator. func (mr *MockStateMockRecorder) NewAddrTransactionsIterator(addr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddrTransactionsIterator", reflect.TypeOf((*MockState)(nil).NewAddrTransactionsIterator), addr) } -// AssetIsSponsored mocks base method -func (m *MockState) AssetIsSponsored(assetID crypto.Digest) (bool, error) { +// PersistAddressTransactions mocks base method. +func (m *MockState) PersistAddressTransactions() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssetIsSponsored", assetID) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "PersistAddressTransactions") + ret0, _ := ret[0].(error) + return ret0 } -// AssetIsSponsored indicates an expected call of AssetIsSponsored -func (mr *MockStateMockRecorder) AssetIsSponsored(assetID interface{}) *gomock.Call { +// PersistAddressTransactions indicates an expected call of PersistAddressTransactions. +func (mr *MockStateMockRecorder) PersistAddressTransactions() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetIsSponsored", reflect.TypeOf((*MockState)(nil).AssetIsSponsored), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistAddressTransactions", reflect.TypeOf((*MockState)(nil).PersistAddressTransactions)) } -// AssetInfo mocks base method -func (m *MockState) AssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) { +// ProvidesExtendedApi mocks base method. +func (m *MockState) ProvidesExtendedApi() (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssetInfo", assetID) - ret0, _ := ret[0].(*proto.AssetInfo) + ret := m.ctrl.Call(m, "ProvidesExtendedApi") + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// AssetInfo indicates an expected call of AssetInfo -func (mr *MockStateMockRecorder) AssetInfo(assetID interface{}) *gomock.Call { +// ProvidesExtendedApi indicates an expected call of ProvidesExtendedApi. +func (mr *MockStateMockRecorder) ProvidesExtendedApi() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssetInfo", reflect.TypeOf((*MockState)(nil).AssetInfo), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesExtendedApi", reflect.TypeOf((*MockState)(nil).ProvidesExtendedApi)) } -// FullAssetInfo mocks base method -func (m *MockState) FullAssetInfo(assetID crypto.Digest) (*proto.FullAssetInfo, error) { +// ProvidesStateHashes mocks base method. +func (m *MockState) ProvidesStateHashes() (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FullAssetInfo", assetID) - ret0, _ := ret[0].(*proto.FullAssetInfo) + ret := m.ctrl.Call(m, "ProvidesStateHashes") + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// FullAssetInfo indicates an expected call of FullAssetInfo -func (mr *MockStateMockRecorder) FullAssetInfo(assetID interface{}) *gomock.Call { +// ProvidesStateHashes indicates an expected call of ProvidesStateHashes. +func (mr *MockStateMockRecorder) ProvidesStateHashes() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullAssetInfo", reflect.TypeOf((*MockState)(nil).FullAssetInfo), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesStateHashes", reflect.TypeOf((*MockState)(nil).ProvidesStateHashes)) } -// NFTList mocks base method -func (m *MockState) NFTList(account proto.Recipient, limit uint64, afterAssetID []byte) ([]*proto.FullAssetInfo, error) { +// ResetValidationList mocks base method. +func (m *MockState) ResetValidationList() { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NFTList", account, limit, afterAssetID) - ret0, _ := ret[0].([]*proto.FullAssetInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 + m.ctrl.Call(m, "ResetValidationList") } -// NFTList indicates an expected call of NFTList -func (mr *MockStateMockRecorder) NFTList(account, limit, afterAssetID interface{}) *gomock.Call { +// ResetValidationList indicates an expected call of ResetValidationList. +func (mr *MockStateMockRecorder) ResetValidationList() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NFTList", reflect.TypeOf((*MockState)(nil).NFTList), account, limit, afterAssetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetValidationList", reflect.TypeOf((*MockState)(nil).ResetValidationList)) } -// ScriptInfoByAccount mocks base method -func (m *MockState) ScriptInfoByAccount(account proto.Recipient) (*proto.ScriptInfo, error) { +// RetrieveBinaryEntry mocks base method. +func (m *MockState) RetrieveBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScriptInfoByAccount", account) - ret0, _ := ret[0].(*proto.ScriptInfo) + ret := m.ctrl.Call(m, "RetrieveBinaryEntry", account, key) + ret0, _ := ret[0].(*proto.BinaryDataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScriptInfoByAccount indicates an expected call of ScriptInfoByAccount -func (mr *MockStateMockRecorder) ScriptInfoByAccount(account interface{}) *gomock.Call { +// RetrieveBinaryEntry indicates an expected call of RetrieveBinaryEntry. +func (mr *MockStateMockRecorder) RetrieveBinaryEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAccount", reflect.TypeOf((*MockState)(nil).ScriptInfoByAccount), account) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBinaryEntry", reflect.TypeOf((*MockState)(nil).RetrieveBinaryEntry), account, key) } -// ScriptInfoByAsset mocks base method -func (m *MockState) ScriptInfoByAsset(assetID crypto.Digest) (*proto.ScriptInfo, error) { +// RetrieveBooleanEntry mocks base method. +func (m *MockState) RetrieveBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ScriptInfoByAsset", assetID) - ret0, _ := ret[0].(*proto.ScriptInfo) + ret := m.ctrl.Call(m, "RetrieveBooleanEntry", account, key) + ret0, _ := ret[0].(*proto.BooleanDataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// ScriptInfoByAsset indicates an expected call of ScriptInfoByAsset -func (mr *MockStateMockRecorder) ScriptInfoByAsset(assetID interface{}) *gomock.Call { +// RetrieveBooleanEntry indicates an expected call of RetrieveBooleanEntry. +func (mr *MockStateMockRecorder) RetrieveBooleanEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAsset", reflect.TypeOf((*MockState)(nil).ScriptInfoByAsset), assetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveBooleanEntry", reflect.TypeOf((*MockState)(nil).RetrieveBooleanEntry), account, key) } -// IsActiveLeasing mocks base method -func (m *MockState) IsActiveLeasing(leaseID crypto.Digest) (bool, error) { +// RetrieveEntries mocks base method. +func (m *MockState) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsActiveLeasing", leaseID) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "RetrieveEntries", account) + ret0, _ := ret[0].([]proto.DataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// IsActiveLeasing indicates an expected call of IsActiveLeasing -func (mr *MockStateMockRecorder) IsActiveLeasing(leaseID interface{}) *gomock.Call { +// RetrieveEntries indicates an expected call of RetrieveEntries. +func (mr *MockStateMockRecorder) RetrieveEntries(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsActiveLeasing", reflect.TypeOf((*MockState)(nil).IsActiveLeasing), leaseID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntries", reflect.TypeOf((*MockState)(nil).RetrieveEntries), account) } -// InvokeResultByID mocks base method -func (m *MockState) InvokeResultByID(invokeID crypto.Digest) (*proto.ScriptResult, error) { +// RetrieveEntry mocks base method. +func (m *MockState) RetrieveEntry(account proto.Recipient, key string) (proto.DataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InvokeResultByID", invokeID) - ret0, _ := ret[0].(*proto.ScriptResult) + ret := m.ctrl.Call(m, "RetrieveEntry", account, key) + ret0, _ := ret[0].(proto.DataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// InvokeResultByID indicates an expected call of InvokeResultByID -func (mr *MockStateMockRecorder) InvokeResultByID(invokeID interface{}) *gomock.Call { +// RetrieveEntry indicates an expected call of RetrieveEntry. +func (mr *MockStateMockRecorder) RetrieveEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeResultByID", reflect.TypeOf((*MockState)(nil).InvokeResultByID), invokeID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveEntry", reflect.TypeOf((*MockState)(nil).RetrieveEntry), account, key) } -// ProvidesExtendedApi mocks base method -func (m *MockState) ProvidesExtendedApi() (bool, error) { +// RetrieveIntegerEntry mocks base method. +func (m *MockState) RetrieveIntegerEntry(account proto.Recipient, key string) (*proto.IntegerDataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProvidesExtendedApi") - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "RetrieveIntegerEntry", account, key) + ret0, _ := ret[0].(*proto.IntegerDataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// ProvidesExtendedApi indicates an expected call of ProvidesExtendedApi -func (mr *MockStateMockRecorder) ProvidesExtendedApi() *gomock.Call { +// RetrieveIntegerEntry indicates an expected call of RetrieveIntegerEntry. +func (mr *MockStateMockRecorder) RetrieveIntegerEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesExtendedApi", reflect.TypeOf((*MockState)(nil).ProvidesExtendedApi)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveIntegerEntry", reflect.TypeOf((*MockState)(nil).RetrieveIntegerEntry), account, key) } -// ProvidesStateHashes mocks base method -func (m *MockState) ProvidesStateHashes() (bool, error) { +// RetrieveStringEntry mocks base method. +func (m *MockState) RetrieveStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProvidesStateHashes") - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "RetrieveStringEntry", account, key) + ret0, _ := ret[0].(*proto.StringDataEntry) ret1, _ := ret[1].(error) return ret0, ret1 } -// ProvidesStateHashes indicates an expected call of ProvidesStateHashes -func (mr *MockStateMockRecorder) ProvidesStateHashes() *gomock.Call { +// RetrieveStringEntry indicates an expected call of RetrieveStringEntry. +func (mr *MockStateMockRecorder) RetrieveStringEntry(account, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvidesStateHashes", reflect.TypeOf((*MockState)(nil).ProvidesStateHashes)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveStringEntry", reflect.TypeOf((*MockState)(nil).RetrieveStringEntry), account, key) } -// StateHashAtHeight mocks base method -func (m *MockState) StateHashAtHeight(height uint64) (*proto.StateHash, error) { +// RollbackTo mocks base method. +func (m *MockState) RollbackTo(removalEdge proto.BlockID) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StateHashAtHeight", height) - ret0, _ := ret[0].(*proto.StateHash) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "RollbackTo", removalEdge) + ret0, _ := ret[0].(error) + return ret0 } -// StateHashAtHeight indicates an expected call of StateHashAtHeight -func (mr *MockStateMockRecorder) StateHashAtHeight(height interface{}) *gomock.Call { +// RollbackTo indicates an expected call of RollbackTo. +func (mr *MockStateMockRecorder) RollbackTo(removalEdge interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateHashAtHeight", reflect.TypeOf((*MockState)(nil).StateHashAtHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackTo", reflect.TypeOf((*MockState)(nil).RollbackTo), removalEdge) } -// MapR mocks base method -func (m *MockState) MapR(arg0 func(state.StateInfo) (interface{}, error)) (interface{}, error) { +// RollbackToHeight mocks base method. +func (m *MockState) RollbackToHeight(height proto.Height) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MapR", arg0) - ret0, _ := ret[0].(interface{}) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "RollbackToHeight", height) + ret0, _ := ret[0].(error) + return ret0 } -// MapR indicates an expected call of MapR -func (mr *MockStateMockRecorder) MapR(arg0 interface{}) *gomock.Call { +// RollbackToHeight indicates an expected call of RollbackToHeight. +func (mr *MockStateMockRecorder) RollbackToHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MapR", reflect.TypeOf((*MockState)(nil).MapR), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackToHeight", reflect.TypeOf((*MockState)(nil).RollbackToHeight), height) } -// HitSourceAtHeight mocks base method -func (m *MockState) HitSourceAtHeight(height proto.Height) ([]byte, error) { +// ScoreAtHeight mocks base method. +func (m *MockState) ScoreAtHeight(height proto.Height) (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HitSourceAtHeight", height) - ret0, _ := ret[0].([]byte) + ret := m.ctrl.Call(m, "ScoreAtHeight", height) + ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } -// HitSourceAtHeight indicates an expected call of HitSourceAtHeight -func (mr *MockStateMockRecorder) HitSourceAtHeight(height interface{}) *gomock.Call { +// ScoreAtHeight indicates an expected call of ScoreAtHeight. +func (mr *MockStateMockRecorder) ScoreAtHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HitSourceAtHeight", reflect.TypeOf((*MockState)(nil).HitSourceAtHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScoreAtHeight", reflect.TypeOf((*MockState)(nil).ScoreAtHeight), height) } -// ShouldPersistAddressTransactions mocks base method -func (m *MockState) ShouldPersistAddressTransactions() (bool, error) { +// ScriptInfoByAccount mocks base method. +func (m *MockState) ScriptInfoByAccount(account proto.Recipient) (*proto.ScriptInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ShouldPersistAddressTransactions") - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "ScriptInfoByAccount", account) + ret0, _ := ret[0].(*proto.ScriptInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// ShouldPersistAddressTransactions indicates an expected call of ShouldPersistAddressTransactions -func (mr *MockStateMockRecorder) ShouldPersistAddressTransactions() *gomock.Call { +// ScriptInfoByAccount indicates an expected call of ScriptInfoByAccount. +func (mr *MockStateMockRecorder) ScriptInfoByAccount(account interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockState)(nil).ShouldPersistAddressTransactions)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAccount", reflect.TypeOf((*MockState)(nil).ScriptInfoByAccount), account) } -// AddBlock mocks base method -func (m *MockState) AddBlock(block []byte) (*proto.Block, error) { +// ScriptInfoByAsset mocks base method. +func (m *MockState) ScriptInfoByAsset(assetID crypto.Digest) (*proto.ScriptInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddBlock", block) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "ScriptInfoByAsset", assetID) + ret0, _ := ret[0].(*proto.ScriptInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// AddBlock indicates an expected call of AddBlock -func (mr *MockStateMockRecorder) AddBlock(block interface{}) *gomock.Call { +// ScriptInfoByAsset indicates an expected call of ScriptInfoByAsset. +func (mr *MockStateMockRecorder) ScriptInfoByAsset(assetID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlock", reflect.TypeOf((*MockState)(nil).AddBlock), block) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ScriptInfoByAsset", reflect.TypeOf((*MockState)(nil).ScriptInfoByAsset), assetID) } -// AddDeserializedBlock mocks base method -func (m *MockState) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { +// ShouldPersistAddressTransactions mocks base method. +func (m *MockState) ShouldPersistAddressTransactions() (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "ShouldPersistAddressTransactions") + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// AddDeserializedBlock indicates an expected call of AddDeserializedBlock -func (mr *MockStateMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { +// ShouldPersistAddressTransactions indicates an expected call of ShouldPersistAddressTransactions. +func (mr *MockStateMockRecorder) ShouldPersistAddressTransactions() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockState)(nil).ShouldPersistAddressTransactions)) } -// AddNewBlocks mocks base method -func (m *MockState) AddNewBlocks(blocks [][]byte) error { +// StartProvidingExtendedApi mocks base method. +func (m *MockState) StartProvidingExtendedApi() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddNewBlocks", blocks) + ret := m.ctrl.Call(m, "StartProvidingExtendedApi") ret0, _ := ret[0].(error) return ret0 } -// AddNewBlocks indicates an expected call of AddNewBlocks -func (mr *MockStateMockRecorder) AddNewBlocks(blocks interface{}) *gomock.Call { +// StartProvidingExtendedApi indicates an expected call of StartProvidingExtendedApi. +func (mr *MockStateMockRecorder) StartProvidingExtendedApi() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewBlocks", reflect.TypeOf((*MockState)(nil).AddNewBlocks), blocks) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartProvidingExtendedApi", reflect.TypeOf((*MockState)(nil).StartProvidingExtendedApi)) } -// AddNewDeserializedBlocks mocks base method -func (m *MockState) AddNewDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { +// StateHashAtHeight mocks base method. +func (m *MockState) StateHashAtHeight(height uint64) (*proto.StateHash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddNewDeserializedBlocks", blocks) - ret0, _ := ret[0].(*proto.Block) + ret := m.ctrl.Call(m, "StateHashAtHeight", height) + ret0, _ := ret[0].(*proto.StateHash) ret1, _ := ret[1].(error) return ret0, ret1 } -// AddNewDeserializedBlocks indicates an expected call of AddNewDeserializedBlocks -func (mr *MockStateMockRecorder) AddNewDeserializedBlocks(blocks interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNewDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddNewDeserializedBlocks), blocks) -} - -// AddOldBlocks mocks base method -func (m *MockState) AddOldBlocks(blocks [][]byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddOldBlocks", blocks) - ret0, _ := ret[0].(error) - return ret0 -} - -// AddOldBlocks indicates an expected call of AddOldBlocks -func (mr *MockStateMockRecorder) AddOldBlocks(blocks interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldBlocks", reflect.TypeOf((*MockState)(nil).AddOldBlocks), blocks) -} - -// AddOldDeserializedBlocks mocks base method -func (m *MockState) AddOldDeserializedBlocks(blocks []*proto.Block) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddOldDeserializedBlocks", blocks) - ret0, _ := ret[0].(error) - return ret0 -} - -// AddOldDeserializedBlocks indicates an expected call of AddOldDeserializedBlocks -func (mr *MockStateMockRecorder) AddOldDeserializedBlocks(blocks interface{}) *gomock.Call { +// StateHashAtHeight indicates an expected call of StateHashAtHeight. +func (mr *MockStateMockRecorder) StateHashAtHeight(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddOldDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddOldDeserializedBlocks), blocks) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateHashAtHeight", reflect.TypeOf((*MockState)(nil).StateHashAtHeight), height) } -// RollbackToHeight mocks base method -func (m *MockState) RollbackToHeight(height proto.Height) error { +// TopBlock mocks base method. +func (m *MockState) TopBlock() *proto.Block { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RollbackToHeight", height) - ret0, _ := ret[0].(error) + ret := m.ctrl.Call(m, "TopBlock") + ret0, _ := ret[0].(*proto.Block) return ret0 } -// RollbackToHeight indicates an expected call of RollbackToHeight -func (mr *MockStateMockRecorder) RollbackToHeight(height interface{}) *gomock.Call { +// TopBlock indicates an expected call of TopBlock. +func (mr *MockStateMockRecorder) TopBlock() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackToHeight", reflect.TypeOf((*MockState)(nil).RollbackToHeight), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopBlock", reflect.TypeOf((*MockState)(nil).TopBlock)) } -// RollbackTo mocks base method -func (m *MockState) RollbackTo(removalEdge proto.BlockID) error { +// TransactionByID mocks base method. +func (m *MockState) TransactionByID(id []byte) (proto.Transaction, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RollbackTo", removalEdge) - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "TransactionByID", id) + ret0, _ := ret[0].(proto.Transaction) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// RollbackTo indicates an expected call of RollbackTo -func (mr *MockStateMockRecorder) RollbackTo(removalEdge interface{}) *gomock.Call { +// TransactionByID indicates an expected call of TransactionByID. +func (mr *MockStateMockRecorder) TransactionByID(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackTo", reflect.TypeOf((*MockState)(nil).RollbackTo), removalEdge) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByID", reflect.TypeOf((*MockState)(nil).TransactionByID), id) } -// ValidateNextTx mocks base method -func (m *MockState) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, blockVersion proto.BlockVersion, acceptFailed bool) error { +// TransactionByIDWithStatus mocks base method. +func (m *MockState) TransactionByIDWithStatus(id []byte) (proto.Transaction, bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ValidateNextTx", tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "TransactionByIDWithStatus", id) + ret0, _ := ret[0].(proto.Transaction) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } -// ValidateNextTx indicates an expected call of ValidateNextTx -func (mr *MockStateMockRecorder) ValidateNextTx(tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed interface{}) *gomock.Call { +// TransactionByIDWithStatus indicates an expected call of TransactionByIDWithStatus. +func (mr *MockStateMockRecorder) TransactionByIDWithStatus(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateNextTx", reflect.TypeOf((*MockState)(nil).ValidateNextTx), tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionByIDWithStatus", reflect.TypeOf((*MockState)(nil).TransactionByIDWithStatus), id) } -// ResetValidationList mocks base method -func (m *MockState) ResetValidationList() { +// TransactionHeightByID mocks base method. +func (m *MockState) TransactionHeightByID(id []byte) (uint64, error) { m.ctrl.T.Helper() - m.ctrl.Call(m, "ResetValidationList") + ret := m.ctrl.Call(m, "TransactionHeightByID", id) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// ResetValidationList indicates an expected call of ResetValidationList -func (mr *MockStateMockRecorder) ResetValidationList() *gomock.Call { +// TransactionHeightByID indicates an expected call of TransactionHeightByID. +func (mr *MockStateMockRecorder) TransactionHeightByID(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetValidationList", reflect.TypeOf((*MockState)(nil).ResetValidationList)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionHeightByID", reflect.TypeOf((*MockState)(nil).TransactionHeightByID), id) } -// TxValidation mocks base method +// TxValidation mocks base method. func (m *MockState) TxValidation(arg0 func(state.TxValidation) error) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TxValidation", arg0) @@ -2103,78 +2057,67 @@ func (m *MockState) TxValidation(arg0 func(state.TxValidation) error) error { return ret0 } -// TxValidation indicates an expected call of TxValidation +// TxValidation indicates an expected call of TxValidation. func (mr *MockStateMockRecorder) TxValidation(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxValidation", reflect.TypeOf((*MockState)(nil).TxValidation), arg0) } -// Map mocks base method -func (m *MockState) Map(arg0 func(state.NonThreadSafeState) error) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Map", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// Map indicates an expected call of Map -func (mr *MockStateMockRecorder) Map(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Map", reflect.TypeOf((*MockState)(nil).Map), arg0) -} - -// SavePeers mocks base method -func (m *MockState) SavePeers(arg0 []proto.TCPAddr) error { +// ValidateNextTx mocks base method. +func (m *MockState) ValidateNextTx(tx proto.Transaction, currentTimestamp, parentTimestamp uint64, blockVersion proto.BlockVersion, acceptFailed bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SavePeers", arg0) + ret := m.ctrl.Call(m, "ValidateNextTx", tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) ret0, _ := ret[0].(error) return ret0 } -// SavePeers indicates an expected call of SavePeers -func (mr *MockStateMockRecorder) SavePeers(arg0 interface{}) *gomock.Call { +// ValidateNextTx indicates an expected call of ValidateNextTx. +func (mr *MockStateMockRecorder) ValidateNextTx(tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SavePeers", reflect.TypeOf((*MockState)(nil).SavePeers), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateNextTx", reflect.TypeOf((*MockState)(nil).ValidateNextTx), tx, currentTimestamp, parentTimestamp, blockVersion, acceptFailed) } -// StartProvidingExtendedApi mocks base method -func (m *MockState) StartProvidingExtendedApi() error { +// VotesNum mocks base method. +func (m *MockState) VotesNum(featureID int16) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartProvidingExtendedApi") - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "VotesNum", featureID) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// StartProvidingExtendedApi indicates an expected call of StartProvidingExtendedApi -func (mr *MockStateMockRecorder) StartProvidingExtendedApi() *gomock.Call { +// VotesNum indicates an expected call of VotesNum. +func (mr *MockStateMockRecorder) VotesNum(featureID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartProvidingExtendedApi", reflect.TypeOf((*MockState)(nil).StartProvidingExtendedApi)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNum", reflect.TypeOf((*MockState)(nil).VotesNum), featureID) } -// PersistAddressTransactions mocks base method -func (m *MockState) PersistAddressTransactions() error { +// VotesNumAtHeight mocks base method. +func (m *MockState) VotesNumAtHeight(featureID int16, height proto.Height) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistAddressTransactions") - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "VotesNumAtHeight", featureID, height) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// PersistAddressTransactions indicates an expected call of PersistAddressTransactions -func (mr *MockStateMockRecorder) PersistAddressTransactions() *gomock.Call { +// VotesNumAtHeight indicates an expected call of VotesNumAtHeight. +func (mr *MockStateMockRecorder) VotesNumAtHeight(featureID, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistAddressTransactions", reflect.TypeOf((*MockState)(nil).PersistAddressTransactions)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VotesNumAtHeight", reflect.TypeOf((*MockState)(nil).VotesNumAtHeight), featureID, height) } -// Close mocks base method -func (m *MockState) Close() error { +// WavesAddressesNumber mocks base method. +func (m *MockState) WavesAddressesNumber() (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "WavesAddressesNumber") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// Close indicates an expected call of Close -func (mr *MockStateMockRecorder) Close() *gomock.Call { +// WavesAddressesNumber indicates an expected call of WavesAddressesNumber. +func (mr *MockStateMockRecorder) WavesAddressesNumber() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockState)(nil).Close)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WavesAddressesNumber", reflect.TypeOf((*MockState)(nil).WavesAddressesNumber)) } diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index 045a36123..e6ef75a9c 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -1,6 +1,7 @@ package node import ( + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "math/big" "reflect" @@ -24,16 +25,14 @@ func ScoreAction(_ services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) func GetPeersAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { metricGetPeersMessage.Inc() - rs, err := services.Peers.KnownPeers() - if err != nil { - zap.L().Error("failed got known peers", zap.Error(err)) - return fsm, nil, err - } + rs := services.Peers.KnownPeers() + var out []proto.PeerInfo for _, r := range rs { + ipPort := proto.IpPort(r) out = append(out, proto.PeerInfo{ - Addr: r.IP[:], - Port: uint16(r.Port), + Addr: ipPort.Addr(), + Port: uint16(ipPort.Port()), }) } mess.ID.SendMessage(&proto.PeersMessage{Peers: out}) @@ -42,20 +41,15 @@ func GetPeersAction(services services.Services, mess peer.ProtoMessage, fsm stat func PeersAction(services services.Services, mess peer.ProtoMessage, fsm state_fsm.FSM) (state_fsm.FSM, state_fsm.Async, error) { metricPeersMessage.Inc() - rs, err := services.Peers.KnownPeers() - if err != nil { - zap.L().Error("failed got known peers", zap.Error(err)) - return fsm, nil, err - } + rs := services.Peers.KnownPeers() + m := mess.Message.(*proto.PeersMessage).Peers if len(m) == 0 { return fsm, nil, nil } for _, p := range m { - rs = append(rs, proto.TCPAddr{ - IP: p.Addr, - Port: int(p.Port), - }) + known := storage.KnownPeer(proto.NewTCPAddr(p.Addr, int(p.Port)).ToIpPort()) + rs = append(rs, known) } return fsm, nil, services.Peers.UpdateKnownPeers(rs) } diff --git a/pkg/node/actions_by_type_test.go b/pkg/node/actions_by_type_test.go index 42f9d2256..72ed4bc61 100644 --- a/pkg/node/actions_by_type_test.go +++ b/pkg/node/actions_by_type_test.go @@ -1,6 +1,7 @@ package node import ( + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "net" "testing" @@ -16,8 +17,9 @@ func TestPeersAction(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() m := mock.NewMockPeerManager(ctrl) - m.EXPECT().KnownPeers().Return([]proto.TCPAddr{}, nil) - m.EXPECT().UpdateKnownPeers([]proto.TCPAddr{{IP: net.ParseIP("127.0.0.1"), Port: 6868}}) + m.EXPECT().KnownPeers().Return([]storage.KnownPeer{}) + addr := proto.NewTCPAddr(net.ParseIP("127.0.0.1"), 6868).ToIpPort() + m.EXPECT().UpdateKnownPeers([]storage.KnownPeer{storage.KnownPeer(addr)}) _, _, err := PeersAction(services.Services{ Peers: m, diff --git a/pkg/node/peer_manager/memory_peer_storage.go b/pkg/node/peer_manager/memory_peer_storage.go deleted file mode 100644 index 4af8f04f2..000000000 --- a/pkg/node/peer_manager/memory_peer_storage.go +++ /dev/null @@ -1,18 +0,0 @@ -package peer_manager - -import "github.com/wavesplatform/gowaves/pkg/proto" - -type MemoryPeerStorage struct { - peers []proto.TCPAddr -} - -func (a *MemoryPeerStorage) SavePeers(peers []proto.TCPAddr) error { - b := make([]proto.TCPAddr, len(peers)) - copy(b, peers) - a.peers = b - return nil -} - -func (a *MemoryPeerStorage) Peers() ([]proto.TCPAddr, error) { - return a.peers, nil -} diff --git a/pkg/node/peer_manager/peer_manager.go b/pkg/node/peer_manager/peer_manager.go index dba413efe..5688f401a 100644 --- a/pkg/node/peer_manager/peer_manager.go +++ b/pkg/node/peer_manager/peer_manager.go @@ -2,6 +2,7 @@ package peer_manager import ( "context" + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "math/big" "net" "sort" @@ -14,6 +15,8 @@ import ( "go.uber.org/zap" ) +const suspendDuration = 5 * time.Minute + type peerInfo struct { score *big.Int peer peer.Peer @@ -39,13 +42,13 @@ type PeerManager interface { InOutCount() (in int, out int) EachConnected(func(peer.Peer, *proto.Score)) IsSuspended(peer.Peer) bool - Suspend(peer.Peer, string) - Suspended() []string + Suspend(peer peer.Peer, suspendTime time.Time, reason string) + Suspended() []storage.SuspendedPeer AddConnected(peer.Peer) PeerWithHighestScore() (peer.Peer, *big.Int, bool) UpdateScore(p peer.Peer, score *proto.Score) error - UpdateKnownPeers([]proto.TCPAddr) error - KnownPeers() ([]proto.TCPAddr, error) + UpdateKnownPeers([]storage.KnownPeer) error + KnownPeers() []storage.KnownPeer Close() SpawnOutgoingConnections(context.Context) SpawnIncomingConnection(ctx context.Context, conn net.Conn) error @@ -59,73 +62,25 @@ type PeerManager interface { Disconnect(peer.Peer) } -type Ip = [net.IPv6len]byte - -type suspended map[Ip]time.Time - -func (a suspended) Blocked(ipPort proto.IpPort, now time.Time) bool { - ip := Ip{} - copy(ip[:], ipPort[:net.IPv6len]) - v, ok := a[ip] - if !ok { - return false - } - if v.Add(5 * time.Minute).After(now) { //suspended - return true - } else { - return false - } -} - -func (a suspended) AllBlocked() []string { - out := make([]string, 0, len(a)) - for ip := range a { - out = append(out, net.IP(ip[:]).String()) - } - return out -} - -func (a suspended) clear(now time.Time) { - for ip, v := range a { - if v.Add(5 * time.Minute).Before(now) { - delete(a, ip) - } - } -} - -func (a suspended) Block(ip proto.IpPort, d time.Duration) { - a[ipPortToIp(ip)] = time.Now().Add(d) -} - -func ipPortToIp(ipPort proto.IpPort) [net.IPv6len]byte { - ip := Ip{} - copy(ip[:], ipPort[:net.IPv6len]) - return ip -} - -func (a suspended) Len() int { - return len(a) -} - type PeerManagerImpl struct { spawner PeerSpawner active map[peer.Peer]peerInfo mu sync.RWMutex - state PeerStorage + peerStorage PeerStorage spawned map[proto.IpPort]struct{} - suspended suspended connectPeers bool // spawn outgoing limitConnections int version proto.Version } -func NewPeerManager(spawner PeerSpawner, storage PeerStorage, limitConnections int, version proto.Version) *PeerManagerImpl { +func NewPeerManager(spawner PeerSpawner, storage PeerStorage, + limitConnections int, version proto.Version) *PeerManagerImpl { + return &PeerManagerImpl{ spawner: spawner, active: make(map[peer.Peer]peerInfo), - state: storage, + peerStorage: storage, spawned: make(map[proto.IpPort]struct{}), - suspended: suspended{}, connectPeers: true, limitConnections: limitConnections, version: version, @@ -159,11 +114,11 @@ func (a *PeerManagerImpl) Connected(p peer.Peer) (peer.Peer, bool) { func (a *PeerManagerImpl) ConnectedCount() int { a.mu.RLock() defer a.mu.RUnlock() - return a.connectedCount() + return a.unsafeConnectedCount() } // non thread safe -func (a *PeerManagerImpl) connectedCount() int { +func (a *PeerManagerImpl) unsafeConnectedCount() int { return len(a.active) } @@ -183,7 +138,7 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { a.version.String(), p.Handshake().Version.String(), ) - a.Suspend(p, err.Error()) + a.Suspend(p, time.Now(), err.Error()) _ = p.Close() return proto.NewInfoMsg(err) } @@ -197,7 +152,9 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { } case peer.Outgoing: if !p.Handshake().DeclaredAddr.Empty() { - _ = a.state.AddKnown(proto.TCPAddr(p.Handshake().DeclaredAddr)) + known := storage.KnownPeer(proto.TCPAddr(p.Handshake().DeclaredAddr).ToIpPort()) + // TODO(nickeskov): maybe log error? + _ = a.peerStorage.AddKnown([]storage.KnownPeer{known}) } if out >= a.limitConnections { _ = p.Close() @@ -211,15 +168,21 @@ func (a *PeerManagerImpl) NewConnection(p peer.Peer) error { return nil } +func (a *PeerManagerImpl) ClearSuspended(now time.Time) { + a.mu.Lock() + defer a.mu.Unlock() + if err := a.peerStorage.RefreshSuspended(now); err != nil { + zap.S().Errorf("failed to clear suspended peers: %v", err) + } +} + func (a *PeerManagerImpl) Run(ctx context.Context) { for { select { case <-ctx.Done(): return case <-time.After(1 * time.Minute): - a.mu.Lock() - a.suspended.clear(time.Now()) - a.mu.Unlock() + a.ClearSuspended(time.Now()) } } } @@ -263,7 +226,8 @@ func (a *PeerManagerImpl) UpdateScore(p peer.Peer, score *big.Int) error { func (a *PeerManagerImpl) IsSuspended(p peer.Peer) bool { a.mu.RLock() defer a.mu.RUnlock() - return a.suspended.Blocked(p.RemoteAddr().ToIpPort(), time.Now()) + ip := storage.IpFromIpPort(p.RemoteAddr().ToIpPort()) + return a.peerStorage.IsSuspendedIP(ip, time.Now()) } // InOutCount counts connected peers, @@ -282,53 +246,74 @@ func (a *PeerManagerImpl) InOutCount() (in int, out int) { return in, out } -func (a *PeerManagerImpl) Suspend(p peer.Peer, reason string) { +func (a *PeerManagerImpl) Suspend(p peer.Peer, suspendTime time.Time, reason string) { a.Disconnect(p) a.mu.Lock() - a.suspended.Block(p.RemoteAddr().ToIpPort(), 5*time.Minute) - a.mu.Unlock() - zap.S().Debugf("[%s] Suspend peer, reason: %s ", p.ID(), reason) + defer a.mu.Unlock() + suspended := storage.SuspendedPeer{ + IP: storage.IpFromIpPort(p.RemoteAddr().ToIpPort()), + SuspendTimestampMillis: unixMillis(suspendTime), + SuspendDuration: suspendDuration, + Reason: reason, + } + if err := a.peerStorage.AddSuspended([]storage.SuspendedPeer{suspended}); err != nil { + zap.S().Errorf("[%s] Failed to suspend peer, reason %q: %v", p.ID(), reason, err) + } else { + zap.S().Debugf("[%s] Suspend peer, reason: %s ", p.ID(), reason) + } } -func (a *PeerManagerImpl) Suspended() []string { +func (a *PeerManagerImpl) Suspended() []storage.SuspendedPeer { a.mu.RLock() defer a.mu.RUnlock() - return a.suspended.AllBlocked() + return a.peerStorage.Suspended(time.Now()) } -func (a *PeerManagerImpl) AddAddress(ctx context.Context, addr string) { - _ = a.state.Add([]proto.TCPAddr{proto.NewTCPAddrFromString(addr)}) +func (a *PeerManagerImpl) AddAddress(ctx context.Context, addr proto.TCPAddr) error { + known := storage.KnownPeer(addr.ToIpPort()) + if err := a.peerStorage.AddKnown([]storage.KnownPeer{known}); err != nil { + return errors.Wrapf(err, "failed to add addr %q into known peers storage", addr.String()) + } go func() { - if err := a.spawner.SpawnOutgoing(ctx, proto.NewTCPAddrFromString(addr)); err != nil { + if err := a.spawner.SpawnOutgoing(ctx, addr); err != nil { + // TODO(nickeskov): maybe don't remove from known peers in this case? + if removeErr := a.peerStorage.DeleteKnown([]storage.KnownPeer{known}); removeErr != nil { + zap.S().Errorf("Failed to remove peer %q from known peers storage", known.String()) + } zap.S().Debug(err) } }() + return nil } -func (a *PeerManagerImpl) UpdateKnownPeers(known []proto.TCPAddr) error { +func (a *PeerManagerImpl) UpdateKnownPeers(known []storage.KnownPeer) error { if len(known) == 0 { return nil } - return a.state.Add(known) + + if err := a.peerStorage.AddKnown(known); err != nil { + return errors.Wrap(err, "failed to update known peers") + } + return nil } -func (a *PeerManagerImpl) KnownPeers() ([]proto.TCPAddr, error) { - return a.state.Known() +func (a *PeerManagerImpl) KnownPeers() []storage.KnownPeer { + return a.peerStorage.Known() } func (a *PeerManagerImpl) Close() { a.mu.Lock() + defer a.mu.Unlock() for _, v := range a.active { _ = v.peer.Close() } - a.mu.Unlock() } func (a *PeerManagerImpl) SpawnOutgoingConnections(ctx context.Context) { a.mu.Lock() defer a.mu.Unlock() - if a.connectedCount() > a.limitConnections*2 { + if a.unsafeConnectedCount() > a.limitConnections*2 { return } var outCnt int @@ -346,11 +331,7 @@ func (a *PeerManagerImpl) SpawnOutgoingConnections(ctx context.Context) { return } - known, err := a.KnownPeers() - if err != nil { - zap.S().Error(err) - return - } + known := a.KnownPeers() active := map[proto.IpPort]struct{}{} for _, p := range a.active { @@ -363,24 +344,26 @@ func (a *PeerManagerImpl) SpawnOutgoingConnections(ctx context.Context) { } } - for _, addr := range known { - addrIpPort := addr.ToIpPort() - if _, ok := active[addrIpPort]; ok { + for _, knowPeer := range known { + ipPort := knowPeer.IpPort() + if _, ok := active[ipPort]; ok { continue } - if _, ok := a.spawned[addrIpPort]; ok { + if _, ok := a.spawned[ipPort]; ok { continue } - if a.suspended.Blocked(addrIpPort, time.Now()) { + if a.peerStorage.IsSuspendedIP(knowPeer.IP(), time.Now()) { continue } - a.spawned[addr.ToIpPort()] = struct{}{} + a.spawned[ipPort] = struct{}{} - go func(addr proto.TCPAddr) { + go func(ipPort proto.IpPort) { + addr := proto.NewTCPAddr(ipPort.Addr(), ipPort.Port()) defer a.RemoveSpawned(addr) + // TODO(nickeskov): maybe log error? _ = a.spawner.SpawnOutgoing(ctx, addr) - }(addr) + }(ipPort) } } @@ -465,3 +448,7 @@ func (a *PeerManagerImpl) Connect(ctx context.Context, addr proto.TCPAddr) error return nil } + +func unixMillis(now time.Time) int64 { + return now.UnixNano() / 1_000_000 +} diff --git a/pkg/node/peer_manager/peer_manager_test.go b/pkg/node/peer_manager/peer_manager_test.go deleted file mode 100644 index bd8d3f0de..000000000 --- a/pkg/node/peer_manager/peer_manager_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package peer_manager - -import ( - "net" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -func TestSuspended_Block(t *testing.T) { - addr := proto.NewTCPAddr(net.IPv4(8, 8, 8, 8), 80).ToIpPort() - - t.Run("check with same port", func(t *testing.T) { - b := suspended{} - require.False(t, b.Blocked(addr, time.Now())) - - b.Block(addr, 5*time.Minute) - - require.True(t, b.Blocked(addr, time.Now())) - require.False(t, b.Blocked(addr, time.Now().Add(10*time.Minute))) - - require.Equal(t, 1, b.Len()) - - b.clear(time.Now().Add(10 * time.Minute)) - require.Equal(t, 0, b.Len()) - }) - - t.Run("check with different ports", func(t *testing.T) { - b := suspended{} - addr2 := proto.NewTCPAddr(net.IPv4(8, 8, 8, 8), 180).ToIpPort() - - b.Block(addr, 5*time.Minute) - - require.True(t, b.Blocked(addr2, time.Now()), "should be suspended, ignore port") - }) -} diff --git a/pkg/node/peer_manager/peer_storage.go b/pkg/node/peer_manager/peer_storage.go index 82f113714..cb909fe58 100644 --- a/pkg/node/peer_manager/peer_storage.go +++ b/pkg/node/peer_manager/peer_storage.go @@ -1,12 +1,23 @@ package peer_manager import ( - "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + "time" ) type PeerStorage interface { - All() ([]proto.TCPAddr, error) - Known() ([]proto.TCPAddr, error) - AddKnown(proto.TCPAddr) error - Add([]proto.TCPAddr) error + Known() []storage.KnownPeer + AddKnown(known []storage.KnownPeer) error + DeleteKnown(known []storage.KnownPeer) error + DropKnown() error + + Suspended(now time.Time) []storage.SuspendedPeer + AddSuspended(suspended []storage.SuspendedPeer) error + IsSuspendedIP(ip storage.IP, now time.Time) bool + IsSuspendedIPs(ips []storage.IP, now time.Time) []bool + DeleteSuspendedByIP(suspended []storage.SuspendedPeer) error + RefreshSuspended(now time.Time) error + DropSuspended() error + + DropStorage() error } diff --git a/pkg/node/peer_manager/peer_storage_test.go b/pkg/node/peer_manager/peer_storage_test.go new file mode 100644 index 000000000..c1bc4268f --- /dev/null +++ b/pkg/node/peer_manager/peer_storage_test.go @@ -0,0 +1,40 @@ +package peer_manager + +import ( + "github.com/golang/mock/gomock" + "github.com/wavesplatform/gowaves/pkg/mock" + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + "github.com/wavesplatform/gowaves/pkg/proto" + "testing" + "time" +) + +func TestPeerManagerImpl_Suspend(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + now := time.Now() + tcpAddr := proto.NewTCPAddrFromString("32.34.46.1:4535") + reason := "some-reason" + + p := mock.NewMockPeer(ctrl) + gomock.InOrder( + p.EXPECT().Close(), + p.EXPECT().RemoteAddr().Return(tcpAddr), + p.EXPECT().ID().Return("some-id"), + ) + + peerStorage := mock.NewMockPeerStorage(ctrl) + peerStorage.EXPECT().AddSuspended([]storage.SuspendedPeer{{ + IP: storage.IpFromIpPort(tcpAddr.ToIpPort()), + SuspendTimestampMillis: unixMillis(now), + SuspendDuration: suspendDuration, + Reason: reason, + }}) + + manager := PeerManagerImpl{ + peerStorage: peerStorage, + } + + manager.Suspend(p, now, reason) +} diff --git a/pkg/node/peer_manager/storage/binary.go b/pkg/node/peer_manager/storage/binary.go deleted file mode 100644 index a90b4431d..000000000 --- a/pkg/node/peer_manager/storage/binary.go +++ /dev/null @@ -1,138 +0,0 @@ -package storage - -import ( - "bytes" - "encoding/binary" - "io/ioutil" - "os" - "path" - "sort" - "sync" - - "github.com/wavesplatform/gowaves/pkg/proto" -) - -type Peers []proto.TCPAddr - -func (a Peers) Len() int { return len(a) } -func (a Peers) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a Peers) Less(i, j int) bool { return a[i].ToUint64() < a[j].ToUint64() } - -type BinaryStorage struct { - lock sync.Mutex - statePath string - allCache Peers - knownCache Peers -} - -func (a *BinaryStorage) all() string { - known := path.Join(a.statePath, "blocks_storage", "peers_all.dat") - return known -} - -func (a *BinaryStorage) known() string { - known := path.Join(a.statePath, "blocks_storage", "peers_known.dat") - return known -} - -func (a *BinaryStorage) All() ([]proto.TCPAddr, error) { - a.lock.Lock() - defer a.lock.Unlock() - err := a.loadCache(&a.allCache, a.all()) - if err != nil { - return nil, err - } - out := make([]proto.TCPAddr, len(a.allCache)) - copy(out, a.allCache) - return out, nil -} - -func (a *BinaryStorage) loadCache(cache *Peers, file string) error { - if len(*cache) > 0 { - return nil - } - bts, err := ioutil.ReadFile(file) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - var peers Peers - for len(bts) >= 8 { - val := binary.BigEndian.Uint64(bts[:8]) - peers = append(peers, proto.NewTcpAddrFromUint64(val)) - bts = bts[8:] - } - *cache = peers - return nil -} - -func (a *BinaryStorage) Known() ([]proto.TCPAddr, error) { - a.lock.Lock() - defer a.lock.Unlock() - err := a.loadCache(&a.knownCache, a.known()) - if err != nil { - return nil, err - } - out := make([]proto.TCPAddr, len(a.knownCache)) - copy(out, a.knownCache) - return out, nil -} - -func (a *BinaryStorage) AddKnown(new proto.TCPAddr) error { - a.lock.Lock() - defer a.lock.Unlock() - err := a.loadCache(&a.knownCache, a.known()) - if err != nil { - return err - } - a.knownCache = append(a.knownCache, new) - sort.Sort(a.knownCache) - err = a.save(a.known(), a.knownCache) - if err != nil { - return err - } - a.knownCache = nil - return nil -} - -func (a *BinaryStorage) Add(addrs []proto.TCPAddr) error { - a.lock.Lock() - defer a.lock.Unlock() - err := a.loadCache(&a.allCache, a.all()) - if err != nil { - return err - } - a.allCache = append(a.allCache, addrs...) - sort.Sort(a.allCache) - err = a.save(a.all(), a.allCache) - if err != nil { - return err - } - a.allCache = nil - return nil -} - -func (a *BinaryStorage) save(file string, peers Peers) error { - buf := bytes.Buffer{} - prev := uint64(0) - for _, peer := range peers { - cur := peer.ToUint64() - if cur == prev { - continue - } - prev = cur - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, cur) - buf.Write(b) - } - return ioutil.WriteFile(file, buf.Bytes(), 0644) -} - -func NewBinaryStorage(statePath string) *BinaryStorage { - return &BinaryStorage{ - statePath: statePath, - lock: sync.Mutex{}, - } -} diff --git a/pkg/node/peer_manager/storage/binary_test.go b/pkg/node/peer_manager/storage/binary_test.go deleted file mode 100644 index e1f19b114..000000000 --- a/pkg/node/peer_manager/storage/binary_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package storage_test - -import ( - "io/ioutil" - "os" - "path" - "testing" - - "github.com/stretchr/testify/require" - "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -func TestBinaryStorage_Known(t *testing.T) { - d, err := ioutil.TempDir("", "abc") - require.NoError(t, err) - defer os.RemoveAll(d) - - err = os.Mkdir(path.Join(d, "blocks_storage"), 0755) - require.NoError(t, err) - - s := storage.NewBinaryStorage(d) - known, err := s.Known() - require.NoError(t, err) - require.Len(t, known, 0) - - err = s.AddKnown(proto.NewTCPAddrFromString("127.0.0.1:6868")) - require.NoError(t, err) - - // should return 1 peer - known, err = s.Known() - require.NoError(t, err) - require.Len(t, known, 1) - - // add duplicate peer - err = s.AddKnown(proto.NewTCPAddrFromString("127.0.0.1:6868")) - require.NoError(t, err) - - // should return 1 peer too - known, err = s.Known() - require.NoError(t, err) - require.Len(t, known, 1) -} - -func TestBinaryStorage_All(t *testing.T) { - d, err := ioutil.TempDir("", "all") - require.NoError(t, err) - defer os.RemoveAll(d) - - err = os.Mkdir(path.Join(d, "blocks_storage"), 0755) - require.NoError(t, err) - - s := storage.NewBinaryStorage(d) - known, err := s.All() - require.NoError(t, err) - require.Len(t, known, 0) - - err = s.Add([]proto.TCPAddr{proto.NewTCPAddrFromString("127.0.0.1:6868")}) - require.NoError(t, err) - - // should return 1 peer - known, err = s.All() - require.NoError(t, err) - require.Len(t, known, 1) - - // add duplicate peer - err = s.Add([]proto.TCPAddr{proto.NewTCPAddrFromString("127.0.0.1:6868")}) - require.NoError(t, err) - - // should return 1 peer too - known, err = s.All() - require.NoError(t, err) - require.Len(t, known, 1) -} diff --git a/pkg/node/peer_manager/storage/cbor.go b/pkg/node/peer_manager/storage/cbor.go new file mode 100644 index 000000000..c2aad3779 --- /dev/null +++ b/pkg/node/peer_manager/storage/cbor.go @@ -0,0 +1,411 @@ +package storage + +import ( + "github.com/fxamacker/cbor/v2" + "github.com/pkg/errors" + "io" + "io/ioutil" + "os" + "path/filepath" + "sync" + "time" +) + +const ( + peersStorageDir = "peers_storage" +) + +type CBORStorage struct { + rwMutex sync.RWMutex + storageDir string + suspended suspendedPeers + suspendedFilePath string + known knownPeers // nickeskov: list of all ever known peers with a publicly available declared address + knownFilePath string +} + +func NewCBORStorage(baseDir string, now time.Time) (*CBORStorage, error) { + storageDir := filepath.Join(baseDir, peersStorageDir) + return newCBORStorageInDir(storageDir, now) +} + +func newCBORStorageInDir(storageDir string, now time.Time) (*CBORStorage, error) { + if err := os.MkdirAll(storageDir, os.ModePerm); err != nil { + return nil, errors.Wrapf(err, "failed to create peers storage directory %q", storageDir) + } + + knownFile := knownFilePath(storageDir) + if err := createFileIfNotExist(knownFile); err != nil { + return nil, errors.Wrap(err, "failed to create known peers storage file") + } + + suspendedFile := suspendedFilePath(storageDir) + if err := createFileIfNotExist(suspendedFile); err != nil { + return nil, errors.Wrap(err, "failed to create suspended peers storage file") + } + + known := knownPeers{} + if err := unmarshalCborFromFile(knownFile, &known); err != nil && err != io.EOF { + return nil, errors.Wrapf(err, "failed to load known peers from file %q", knownFile) + } + + suspended := suspendedPeers{} + if err := unmarshalCborFromFile(suspendedFile, &suspended); err != nil && err != io.EOF { + return nil, errors.Wrapf(err, "failed to load suspended peers from file %q", suspendedFile) + } + + storage := &CBORStorage{ + storageDir: storageDir, + suspended: suspended, + suspendedFilePath: suspendedFile, + known: known, + knownFilePath: knownFile, + } + + if len(storage.suspended) != 0 { + // nickeskov: remove expired peers + if err := storage.RefreshSuspended(now); err != nil { + return nil, errors.Wrapf(err, + "failed to refresh suspended peers while opening peers storage with path %q", storageDir) + } + } + return storage, nil +} + +func (bs *CBORStorage) Known() []KnownPeer { + bs.rwMutex.RLock() + defer bs.rwMutex.RUnlock() + + known := make([]KnownPeer, 0, len(bs.known)) + for k := range bs.known { + known = append(known, k) + } + return known +} + +// AddKnown adds known peers into peers storage with strong error guarantees. +func (bs *CBORStorage) AddKnown(known []KnownPeer) error { + if len(known) == 0 { + return nil + } + + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + // nickeskov: save old values in backup + backup := bs.unsafeKnownIntersection(known) + // nickeskov: fast path if all known peers already in storage + if len(backup) == len(known) { + return nil + } + + // nickeskov: add new values into known map + for _, k := range known { + bs.known[k] = struct{}{} + } + + if err := bs.unsafeSyncKnown(known, backup); err != nil { + return errors.Wrapf(err, "failed to add known peers") + } + return nil +} + +// DeleteKnown removes known peers from peers storage with strong error guarantees. +func (bs *CBORStorage) DeleteKnown(known []KnownPeer) error { + if len(known) == 0 { + return nil + } + + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + // nickeskov: save old values in backup + backup := bs.unsafeKnownIntersection(known) + // nickeskov: delete entries from known map + for _, k := range known { + delete(bs.known, k) + } + + // nickeskov: newEntries is nil because there no new entries + if err := bs.unsafeSyncKnown(nil, backup); err != nil { + return errors.Wrap(err, "failed to delete known peers") + } + return nil +} + +// DropKnown clear known in memory cache and truncates known peers storage file with strong error guarantee. +func (bs *CBORStorage) DropKnown() error { + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + return bs.unsafeDropKnown() +} + +func (bs *CBORStorage) Suspended(now time.Time) []SuspendedPeer { + bs.rwMutex.RLock() + defer bs.rwMutex.RUnlock() + + suspended := make([]SuspendedPeer, 0, len(bs.suspended)) + for _, s := range bs.suspended { + if s.IsSuspended(now) { + suspended = append(suspended, s) + } + } + return suspended +} + +// AddSuspended adds suspended peers into peers storage with strong error guarantees. +func (bs *CBORStorage) AddSuspended(suspended []SuspendedPeer) error { + if len(suspended) == 0 { + return nil + } + + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + // nickeskov: save old values in backup + backup := bs.unsafeSuspendedIntersection(suspended) + // nickeskov: add new values into suspended map + for _, s := range suspended { + bs.suspended[s.IP] = s + } + + if err := bs.unsafeSyncSuspended(suspended, backup); err != nil { + return errors.Wrap(err, "failed to add suspended peers") + } + return nil +} + +func (bs *CBORStorage) IsSuspendedIP(ip IP, now time.Time) bool { + bs.rwMutex.RLock() + defer bs.rwMutex.RUnlock() + return bs.unsafeIsSuspendedIP(ip, now) +} + +func (bs *CBORStorage) IsSuspendedIPs(ips []IP, now time.Time) []bool { + if len(ips) == 0 { + return nil + } + + bs.rwMutex.RLock() + defer bs.rwMutex.RUnlock() + + isSuspended := make([]bool, 0, len(ips)) + for _, ip := range ips { + isSuspended = append(isSuspended, bs.unsafeIsSuspendedIP(ip, now)) + } + return isSuspended +} + +// DeleteSuspendedByIP removes suspended peers from peers storage with strong error guarantees. +// Note, that only IP field in input parameter will be used. +func (bs *CBORStorage) DeleteSuspendedByIP(suspended []SuspendedPeer) error { + if len(suspended) == 0 { + return nil + } + + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + // nickeskov: save old values in backup + backup := bs.unsafeSuspendedIntersection(suspended) + // nickeskov: delete entries from known map + for _, s := range suspended { + delete(bs.suspended, s.IP) + } + + // nickeskov: newEntries is nil because there no new entries + if err := bs.unsafeSyncSuspended(nil, backup); err != nil { + return errors.Wrap(err, "failed to delete suspended peers") + } + return nil +} + +// RefreshSuspended removes expired peers from suspended peers storage with strong error guarantee. +func (bs *CBORStorage) RefreshSuspended(now time.Time) error { + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + var backup []SuspendedPeer + for _, s := range bs.suspended { + if !s.IsSuspended(now) { + backup = append(backup, s) + delete(bs.suspended, s.IP) + } + } + if len(backup) == 0 { + // nickeskov: peers don't expired + return nil + } + + if err := marshalToCborAndSyncToFile(bs.suspendedFilePath, bs.suspended); err != nil { + // nickeskov: restore previous values into map to eliminate side effects + for _, b := range backup { + bs.suspended[b.IP] = b + } + return errors.Wrap(err, "failed to refresh suspended peers and sync storage") + } + return nil +} + +// DropSuspended clear suspended in memory cache and truncates suspended peers storage file with strong error guarantee. +func (bs *CBORStorage) DropSuspended() error { + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + return bs.unsafeDropSuspended() +} + +// DropStorage clear storage memory cache and truncates storage files. +// In case of error we can loose suspended peers storage file, but honestly it's almost impossible case. +func (bs *CBORStorage) DropStorage() error { + bs.rwMutex.Lock() + defer bs.rwMutex.Unlock() + + suspendedBackup := bs.suspended + if err := bs.unsafeDropSuspended(); err != nil { + return errors.Wrap(err, "failed to drop suspended peers storage") + } + + if err := bs.unsafeDropKnown(); err != nil { + bs.suspended = suspendedBackup + // nickeskov: it's almost impossible case, but if it happens we have inconsistency in suspended peers + // but honestly it's not fatal error + if syncErr := marshalToCborAndSyncToFile(bs.suspendedFilePath, bs.suspended); syncErr != nil { + return errors.Wrapf(err, "failed to sync suspended peers storage from backup: %v", syncErr) + } + return errors.Wrap(err, "failed to drop known peers storage") + } + return nil +} + +func (bs *CBORStorage) unsafeSyncKnown(newEntries, backup []KnownPeer) error { + err := marshalToCborAndSyncToFile(bs.knownFilePath, bs.known) + if err == nil { + return nil + } + // nickeskov: remove known from map to eliminate side effects + for _, k := range newEntries { + delete(bs.known, k) + } + // nickeskov: restore from backup + for _, b := range backup { + bs.known[b] = struct{}{} + } + return errors.Wrap(err, "failed to marshal known peers and sync storage") +} + +func (bs *CBORStorage) unsafeDropKnown() error { + // nickeskov: truncate suspendedStorageFile to zero size + if err := os.Truncate(bs.knownFilePath, 0); err != nil { + return errors.Wrapf(err, "failed to drop known storage file %q", bs.knownFilePath) + } + // nickeskov: clear map + bs.known = knownPeers{} + return nil +} + +func (bs *CBORStorage) unsafeSyncSuspended(newEntries, backup []SuspendedPeer) error { + err := marshalToCborAndSyncToFile(bs.suspendedFilePath, bs.suspended) + if err == nil { + return nil + } + // nickeskov: remove suspended from map to eliminate side effects + for _, s := range newEntries { + delete(bs.suspended, s.IP) + } + // nickeskov: restore from backup + for _, s := range backup { + bs.suspended[s.IP] = s + } + return errors.Wrap(err, "failed to marshal suspended peers and sync storage") +} + +func (bs *CBORStorage) unsafeDropSuspended() error { + // nickeskov: truncate suspendedStorageFile to zero size + if err := os.Truncate(bs.suspendedFilePath, 0); err != nil { + return errors.Wrapf(err, "failed to drop suspended storage file %q", bs.suspendedFilePath) + } + // nickeskov: clear map + bs.suspended = suspendedPeers{} + return nil +} + +// unsafeKnownIntersection returns values from known map which intersects with input values +func (bs *CBORStorage) unsafeKnownIntersection(known []KnownPeer) []KnownPeer { + var intersection []KnownPeer + for _, k := range known { + if _, in := bs.known[k]; in { + intersection = append(intersection, k) + } + } + return intersection +} + +// unsafeSuspendedIntersection returns values from suspended map which intersects with input values +func (bs *CBORStorage) unsafeSuspendedIntersection(suspended []SuspendedPeer) []SuspendedPeer { + var intersection []SuspendedPeer + for _, newSuspended := range suspended { + if storedPeer, in := bs.suspended[newSuspended.IP]; in { + intersection = append(intersection, storedPeer) + } + bs.suspended[newSuspended.IP] = newSuspended + } + return intersection +} + +func (bs *CBORStorage) unsafeIsSuspendedIP(ip IP, now time.Time) bool { + s, in := bs.suspended[ip] + if !in { + return false + } + return s.IsSuspended(now) +} + +func marshalToCborAndSyncToFile(filePath string, value interface{}) error { + data, err := cbor.Marshal(value) + if err != nil { + return errors.Wrapf(err, "failed to marshal %T to CBOR", value) + } + + if err := ioutil.WriteFile(filePath, data, 0644); err != nil { + return errors.Wrapf(err, "failed to write %T in file %q", value, filePath) + } + return nil +} + +// unmarshalCborFromFile read file content and trying unmarshall it into out parameter. It also +// returns error if file is empty. +func unmarshalCborFromFile(filePath string, out interface{}) error { + data, err := ioutil.ReadFile(filePath) + if err != nil { + return errors.Wrapf(err, "failed to read from file with name %q", filePath) + } + + switch err := cbor.Unmarshal(data, out); { + case err == io.EOF: + return io.EOF + case err != nil: + return errors.Wrapf(err, "failed to unmarshall CBOR into %T from file %q", out, filePath) + } + return nil +} + +func knownFilePath(storageDir string) string { + return filepath.Join(storageDir, "peers_known.cbor") +} + +func suspendedFilePath(storageDir string) string { + return filepath.Join(storageDir, "peers_suspended.cbor") +} + +func createFileIfNotExist(path string) (err error) { + knownFile, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0644) + if err != nil { + return errors.Wrapf(err, "failed to create if not exist file %q", path) + } + defer func() { + if closeErr := knownFile.Close(); closeErr != nil { + err = errors.Wrapf(err, "failed to close file %q", path) + } + }() + return nil +} diff --git a/pkg/node/peer_manager/storage/cbor_test.go b/pkg/node/peer_manager/storage/cbor_test.go new file mode 100644 index 000000000..81ba0e9bd --- /dev/null +++ b/pkg/node/peer_manager/storage/cbor_test.go @@ -0,0 +1,424 @@ +package storage + +import ( + "github.com/fxamacker/cbor/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "github.com/wavesplatform/gowaves/pkg/proto" + "io" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" +) + +func TestMarshalUnmarshalCborFromFile(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "test_marshal_to_cbor_*.cbor") + require.NoError(t, err) + defer func() { + filename := tmpFile.Name() + assert.NoError(t, tmpFile.Close()) + require.NoError(t, os.Remove(filename)) + }() + + expected := SuspendedPeer{ + IP: IPFromString("13.3.4.1"), + SuspendTimestampMillis: time.Now().UnixNano() / 1_000_000, + SuspendDuration: time.Minute * 5, + Reason: "some reason", + } + + err = marshalToCborAndSyncToFile(tmpFile.Name(), &expected) + require.NoError(t, err) + err = tmpFile.Sync() + require.NoError(t, err) + + // nickeskov: check marshalling + actual := SuspendedPeer{} + err = cbor.NewDecoder(tmpFile).Decode(&actual) + require.NoError(t, err) + require.Equal(t, expected, actual) + + // nickeskov: check unmarshalling + err = unmarshalCborFromFile(tmpFile.Name(), &actual) + require.NoError(t, err) + require.Equal(t, expected, actual) + + // nickeskov: check error when file not exist + err = unmarshalCborFromFile(tmpFile.Name()+"_not_exist_", &actual) + assert.Error(t, err) +} + +func TestUnmarshalCborFromEmptyFile(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "peers_storage_test_*.cbor") + require.NoError(t, err) + defer func() { + filename := tmpFile.Name() + assert.NoError(t, tmpFile.Close()) + require.NoError(t, os.Remove(filename)) + }() + + dummy := SuspendedPeer{} + err = unmarshalCborFromFile(tmpFile.Name(), &dummy) + assert.Equal(t, io.EOF, err) +} + +func TestCborMarshalUnmarshalWithEmptyData(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "*.cbor") + require.NoError(t, err) + defer func() { + filename := tmpFile.Name() + assert.NoError(t, tmpFile.Close()) + require.NoError(t, os.Remove(filename)) + }() + + dummy := suspendedPeers{} + err = marshalToCborAndSyncToFile(tmpFile.Name(), dummy) + require.NoError(t, err) + + err = unmarshalCborFromFile(tmpFile.Name(), &dummy) + require.NoError(t, err) +} + +type binaryStorageCborSuite struct { + suite.Suite + storage *CBORStorage + now time.Time +} + +func (s *binaryStorageCborSuite) SetupTest() { + tmpdir, err := ioutil.TempDir("", "peers_storage_test_suite_*") + require.NoError(s.T(), err) + defer func() { + if err != nil { + assert.NoError(s.T(), os.Remove(tmpdir)) + } + }() + now := time.Now() + storage, err := newCBORStorageInDir(tmpdir, now) + require.NoError(s.T(), err) + + s.storage = storage + s.now = now +} + +func (s *binaryStorageCborSuite) TearDownTest() { + tmpdir := s.storage.storageDir + s.storage = nil + require.NoError(s.T(), os.RemoveAll(tmpdir)) +} + +func TestBinaryStorageCborTestSuite(t *testing.T) { + suite.Run(t, new(binaryStorageCborSuite)) +} + +func (s *binaryStorageCborSuite) TestCBORStorageKnown() { + known := []KnownPeer{ + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.3.4.1:2345"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("3.54.1.9:1454"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("23.43.7.43:4234"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("42.54.1.6:54356"))), + } + + check := func(known []KnownPeer) { + var unmarshalled knownPeers + require.NoError(s.T(), unmarshalCborFromFile(s.storage.knownFilePath, &unmarshalled)) + assert.Equal(s.T(), len(known), len(unmarshalled)) + // nickeskov: check that all marshaled data saved in file + for _, expected := range known { + _, in := unmarshalled[expected] + require.True(s.T(), in) + } + + // nickeskov: check that all data saved in cache + cachedKnown := make(knownPeers) + for _, k := range s.storage.Known() { + cachedKnown[k] = struct{}{} + } + + for k := range cachedKnown { + _, in := unmarshalled[k] + require.True(s.T(), in) + } + } + + s.Run("add and get known peers", func() { + // nickeskov: check empty input + require.NoError(s.T(), s.storage.AddKnown(nil)) + // nickeskov: check same input + require.NoError(s.T(), s.storage.AddKnown(known)) + + err := s.storage.AddKnown(known) + require.NoError(s.T(), err) + check(known) + }) + + s.Run("delete and get known peers", func() { + // nickeskov: check empty input + require.NoError(s.T(), s.storage.DeleteKnown(nil)) + + // nickeskov: remove first entry + err := s.storage.DeleteKnown(known[:1]) + require.NoError(s.T(), err) + check(known[1:]) + }) + + s.Run("unsafe sync known peers bad storage file", func() { + defer func(knownStorageFile string) { + require.NoError(s.T(), os.Remove(s.storage.knownFilePath)) + s.storage.knownFilePath = knownStorageFile + }(s.storage.knownFilePath) + + badFilePath := filepath.Join(s.storage.storageDir, "test_invalid_known_storage_file") + f, err := os.OpenFile(badFilePath, os.O_CREATE, 0100) + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), f.Chmod(0644)) + require.NoError(s.T(), f.Close()) + }() + + s.storage.knownFilePath = badFilePath + err = s.storage.unsafeSyncKnown(nil, nil) + require.Error(s.T(), err) + }) +} + +func (s *binaryStorageCborSuite) TestCBORStorageSuspended() { + suspendDuration := time.Minute * 5 + now := s.now.Truncate(time.Millisecond) + suspended := []SuspendedPeer{ + { + IP: IPFromString("13.3.4.1"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration, + Reason: "some reason #1", + }, + { + IP: IPFromString("3.54.1.9"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration, + Reason: "some reason #2", + }, + { + IP: IPFromString("23.43.7.43"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration + time.Minute*2, + Reason: "some reason #3", + }, + { + IP: IPFromString("42.54.1.6"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration + time.Minute*2, + Reason: "some reason #4", + }, + } + + check := func(suspended []SuspendedPeer) { + var unmarshalled suspendedPeers + require.NoError(s.T(), unmarshalCborFromFile(s.storage.suspendedFilePath, &unmarshalled)) + assert.Equal(s.T(), len(suspended), len(unmarshalled)) + // nickeskov: check that all marshaled data saved in file + for _, expected := range suspended { + _, in := unmarshalled[expected.IP] + require.True(s.T(), in) + } + + // nickeskov: check that all data saved in cache + cachedSuspended := make(suspendedPeers) + for _, suspendedPeer := range s.storage.Suspended(now) { + cachedSuspended[suspendedPeer.IP] = suspendedPeer + } + + for k := range cachedSuspended { + _, in := unmarshalled[k] + require.True(s.T(), in) + } + } + + s.Run("add and get suspended peers", func() { + // nickeskov: check empty input + require.NoError(s.T(), s.storage.AddSuspended(nil)) + + err := s.storage.AddSuspended(suspended) + require.NoError(s.T(), err) + check(suspended) + }) + + s.Run("ip is suspended", func() { + for _, peer := range suspended { + require.True(s.T(), s.storage.IsSuspendedIP(peer.IP, now)) + } + }) + + s.Run("ips is suspended", func() { + // nickeskov: check empty input + empty := s.storage.IsSuspendedIPs(nil, now) + assert.Empty(s.T(), empty) + + ips := make([]IP, 0, len(suspended)) + for _, peer := range suspended { + ips = append(ips, peer.IP) + } + res := s.storage.IsSuspendedIPs(ips, now.Add(suspendDuration)) + assert.False(s.T(), res[0]) + assert.False(s.T(), res[1]) + assert.True(s.T(), res[2]) + assert.True(s.T(), res[3]) + }) + + s.Run("delete and get suspended peers", func() { + defer func() { + // nickeskov: set previous values + require.NoError(s.T(), s.storage.AddSuspended(suspended)) + }() + + // nickeskov: check empty input + require.NoError(s.T(), s.storage.DeleteSuspendedByIP(nil)) + + // nickeskov: remove first entry + err := s.storage.DeleteSuspendedByIP(suspended[:1]) + require.NoError(s.T(), err) + check(suspended[1:]) + }) + + s.Run("refresh suspended peers", func() { + err := s.storage.RefreshSuspended(now.Add(suspendDuration)) + require.NoError(s.T(), err) + check(suspended[2:]) + }) + + s.Run("new cbor storage with suspended refreshing", func() { + defer func() { + // nickeskov: set previous values + require.NoError(s.T(), s.storage.AddSuspended(suspended)) + }() + + newNow := now.Add(suspendDuration) + storage, err := newCBORStorageInDir(s.storage.storageDir, newNow) + require.NoError(s.T(), err) + s.storage = storage + + testMap := make(suspendedPeers) + for _, peer := range s.storage.Suspended(newNow) { + testMap[peer.IP] = peer + } + + for _, peer := range suspended[2:] { + inMapPeer, in := testMap[peer.IP] + assert.True(s.T(), in) + assert.Equal(s.T(), peer, inMapPeer) + } + }) + + s.Run("unsafe sync suspended peers bad storage file", func() { + defer func(suspendedStorageFile string) { + require.NoError(s.T(), os.Remove(s.storage.suspendedFilePath)) + s.storage.suspendedFilePath = suspendedStorageFile + }(s.storage.suspendedFilePath) + + badFilePath := filepath.Join(s.storage.storageDir, "test_invalid_suspended_storage_file") + f, err := os.OpenFile(badFilePath, os.O_CREATE, 0100) + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), f.Chmod(0644)) + require.NoError(s.T(), f.Close()) + }() + + s.storage.suspendedFilePath = badFilePath + err = s.storage.unsafeSyncSuspended(nil, nil) + require.Error(s.T(), err) + }) +} + +func (s *binaryStorageCborSuite) TestCBORStorageDrops() { + suspendDuration := time.Minute * 5 + now := s.now.Truncate(time.Millisecond) + suspended := []SuspendedPeer{ + { + IP: IPFromString("13.3.4.1"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration, + Reason: "some reason #1", + }, + { + IP: IPFromString("3.54.1.9"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration, + Reason: "some reason #2", + }, + { + IP: IPFromString("23.43.7.43"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration + time.Minute*2, + Reason: "some reason #3", + }, + { + IP: IPFromString("42.54.1.6"), + SuspendTimestampMillis: now.UnixNano() / 1_000_000, + SuspendDuration: suspendDuration + time.Minute*2, + Reason: "some reason #4", + }, + } + + known := []KnownPeer{ + // nickeskov: this peers can be found in suspended peers + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.3.4.1:2345"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("3.54.1.9:1454"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("23.43.7.43:4234"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("42.54.1.6:54356"))), + + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.8.4.1:2334"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("3.5.13.91:14554"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("3.43.7.47:4234"))), + KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("4.54.1.65:5356"))), + } + + checkSuspendedStorageFile := func() { + var unmarshalled suspendedPeers + require.Equal(s.T(), io.EOF, unmarshalCborFromFile(s.storage.suspendedFilePath, &unmarshalled)) + require.Empty(s.T(), s.storage.Suspended(now)) + } + + checkKnownStorageFile := func() { + var unmarshalled knownPeers + require.Equal(s.T(), io.EOF, unmarshalCborFromFile(s.storage.knownFilePath, &unmarshalled)) + require.Empty(s.T(), s.storage.Known()) + } + + s.Run("drop suspended peers", func() { + defer func() { + require.NoError(s.T(), s.storage.AddSuspended(suspended)) + }() + + err := s.storage.DropSuspended() + require.NoError(s.T(), err) + + checkSuspendedStorageFile() + }) + + s.Run("drop known peers", func() { + defer func() { + require.NoError(s.T(), s.storage.AddKnown(known)) + }() + + err := s.storage.DropKnown() + require.NoError(s.T(), err) + + checkKnownStorageFile() + }) + + s.Run("drop peers storage", func() { + defer func() { + require.NoError(s.T(), s.storage.AddSuspended(suspended)) + require.NoError(s.T(), s.storage.AddKnown(known)) + }() + + err := s.storage.DropStorage() + require.NoError(s.T(), err) + + checkSuspendedStorageFile() + checkKnownStorageFile() + }) +} diff --git a/pkg/node/peer_manager/storage/types.go b/pkg/node/peer_manager/storage/types.go new file mode 100644 index 000000000..2fbd44001 --- /dev/null +++ b/pkg/node/peer_manager/storage/types.go @@ -0,0 +1,70 @@ +package storage + +import ( + "github.com/wavesplatform/gowaves/pkg/proto" + "net" + "time" +) + +type IP [net.IPv6len]byte + +func (i *IP) String() string { + return net.IP(i[:]).String() +} + +func IPFromString(s string) IP { + parsed := net.ParseIP(s) + ip := IP{} + copy(ip[:], parsed[:net.IPv6len]) + return ip +} + +func IpFromIpPort(ipPort proto.IpPort) IP { + ip := IP{} + copy(ip[:], ipPort[:net.IPv6len]) + return ip +} + +type KnownPeer proto.IpPort + +func (kp *KnownPeer) IP() IP { + return IpFromIpPort(proto.IpPort(*kp)) +} + +func (kp *KnownPeer) IpPort() proto.IpPort { + return proto.IpPort(*kp) +} + +func (kp *KnownPeer) String() string { + ipPort := kp.IpPort() + return ipPort.String() +} + +type SuspendedPeer struct { + IP IP `cbor:"0,keyasint,omitemtpy"` + SuspendTimestampMillis int64 `cbor:"1,keyasint,omitemtpy"` + SuspendDuration time.Duration `cbor:"2,keyasint,omitemtpy"` + Reason string `cbor:"3,keyasint,omitemtpy"` +} + +func (sp *SuspendedPeer) SuspendTime() time.Time { + return fromUnixMillis(sp.SuspendTimestampMillis) +} + +func (sp *SuspendedPeer) AwakeTime() time.Time { + return sp.SuspendTime().Add(sp.SuspendDuration) +} + +func (sp *SuspendedPeer) IsSuspended(now time.Time) bool { + awakeTime := sp.AwakeTime() + return awakeTime.After(now) +} + +type suspendedPeers map[IP]SuspendedPeer +type knownPeers map[KnownPeer]struct{} + +func fromUnixMillis(timestampMillis int64) time.Time { + sec := timestampMillis / 1_000 + nsec := (timestampMillis % 1_000) * 1_000_000 + return time.Unix(sec, nsec) +} diff --git a/pkg/node/peer_manager/storage/types_test.go b/pkg/node/peer_manager/storage/types_test.go new file mode 100644 index 000000000..eb2786c59 --- /dev/null +++ b/pkg/node/peer_manager/storage/types_test.go @@ -0,0 +1,37 @@ +package storage + +import ( + "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/proto" + "testing" + "time" +) + +func TestFromUnixMillis(t *testing.T) { + ts := time.Now().Truncate(time.Millisecond) + tsMillis := ts.UnixNano() / 1_000_000 + + require.Equal(t, ts.String(), fromUnixMillis(tsMillis).String()) +} + +func TestIpFromIpPort(t *testing.T) { + ip := IpFromIpPort(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.3.4.1:2345"))) + require.Equal(t, "13.3.4.1", ip.String()) +} + +func TestIPFromString(t *testing.T) { + ip := IPFromString("13.3.4.1") + require.Equal(t, "13.3.4.1", ip.String()) +} + +func TestKnownPeerIP(t *testing.T) { + k := KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.3.4.1:2345"))) + ip := k.IP() + require.Equal(t, "13.3.4.1", ip.String()) +} + +func TestKnownPeer_IpPort(t *testing.T) { + k := KnownPeer(proto.NewIpPortFromTcpAddr(proto.NewTCPAddrFromString("13.3.4.1:2345"))) + ipPort := k.IpPort() + require.Equal(t, ipPort.String(), k.String()) +} diff --git a/pkg/node/state_fsm/fsm_sync.go b/pkg/node/state_fsm/fsm_sync.go index 84267f895..fc6d227fa 100644 --- a/pkg/node/state_fsm/fsm_sync.go +++ b/pkg/node/state_fsm/fsm_sync.go @@ -184,7 +184,7 @@ func (a *SyncFsm) applyBlocks(baseInfo BaseInfo, conf conf, internal sync_intern }) if err != nil { if errs.IsValidationError(err) || errs.IsValidationError(errors.Cause(err)) { - a.baseInfo.peers.Suspend(conf.peerSyncWith, err.Error()) + a.baseInfo.peers.Suspend(conf.peerSyncWith, time.Now(), err.Error()) } for _, b := range blocks { metrics.FSMKeyBlockDeclined("sync", b, err) diff --git a/pkg/state/api.go b/pkg/state/api.go index 3cf065327..27a96356e 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -59,8 +59,6 @@ type StateInfo interface { // Retrieve current blockchain settings. BlockchainSettings() (*settings.BlockchainSettings, error) - Peers() ([]proto.TCPAddr, error) - // Features. VotesNum(featureID int16) (uint64, error) VotesNumAtHeight(featureID int16, height proto.Height) (uint64, error) @@ -169,9 +167,6 @@ type StateModifier interface { // Way to call multiple operations under same lock. Map(func(state NonThreadSafeState) error) error - // Create or replace Peers. - SavePeers([]proto.TCPAddr) error - // State will provide extended API data after returning. StartProvidingExtendedApi() error diff --git a/pkg/state/keys.go b/pkg/state/keys.go index d74c7071e..2faac5307 100644 --- a/pkg/state/keys.go +++ b/pkg/state/keys.go @@ -58,8 +58,8 @@ const ( // Leases. leaseKeyPrefix - // Known peers. - knownPeersPrefix + // nickeskov: In legacy code this is `knownPeersPrefix` constant. We skip this value for compatibility. + _ // Aliases. aliasKeyPrefix diff --git a/pkg/state/known_peer.go b/pkg/state/known_peer.go deleted file mode 100644 index 4f9461bde..000000000 --- a/pkg/state/known_peer.go +++ /dev/null @@ -1,25 +0,0 @@ -package state - -import ( - "github.com/pkg/errors" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -const KnownPeerKeyLength = proto.IpPortLength + 1 - -func intoBytes(p proto.TCPAddr) []byte { - out := make([]byte, KnownPeerKeyLength) - out[0] = knownPeersPrefix - ipPort := p.ToIpPort() - copy(out[1:], ipPort[:]) - return out -} - -func fromBytes(b []byte) (proto.TCPAddr, error) { - i := proto.IpPort{} - if len(b) < KnownPeerKeyLength { - return i.ToTcpAddr(), errors.Errorf("not enough bytes to decode to KnownPeerKey") - } - copy(i[:], b[1:]) - return i.ToTcpAddr(), nil -} diff --git a/pkg/state/known_peer_test.go b/pkg/state/known_peer_test.go deleted file mode 100644 index 47e5d2469..000000000 --- a/pkg/state/known_peer_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package state - -import ( - "github.com/stretchr/testify/require" - "github.com/wavesplatform/gowaves/pkg/proto" - "net" - "testing" -) - -func TestKnownPeer(t *testing.T) { - p := proto.NewTCPAddr(net.IPv4(127, 0, 0, 1), 65535) - k := intoBytes(p) - p2, _ := fromBytes(k) - require.Equal(t, p, p2) -} diff --git a/pkg/state/peer_storage.go b/pkg/state/peer_storage.go deleted file mode 100644 index e64e13be4..000000000 --- a/pkg/state/peer_storage.go +++ /dev/null @@ -1,60 +0,0 @@ -package state - -import ( - "github.com/wavesplatform/gowaves/pkg/keyvalue" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -type peerStorage struct { - db keyvalue.IterableKeyVal -} - -func newPeerStorage(db keyvalue.IterableKeyVal) *peerStorage { - return &peerStorage{ - db: db, - } -} - -func (a *peerStorage) savePeers(peers []proto.TCPAddr) error { - if len(peers) == 0 { - return nil - } - - batch, err := a.db.NewBatch() - if err != nil { - return StateError{errorType: ModificationError, originalError: err} - } - - for _, p := range peers { - k := intoBytes(p) - batch.Put(k[:], nil) - } - - err = a.db.Flush(batch) - if err != nil { - return err - } - return nil -} - -func (a *peerStorage) peers() ([]proto.TCPAddr, error) { - iter, err := a.db.NewKeyIterator([]byte{knownPeersPrefix}) - if err != nil { - return nil, err - } - defer iter.Release() - - var peers []proto.TCPAddr - for iter.Next() { - p, err := fromBytes(iter.Key()) - if err != nil { - return nil, err - } - - peers = append(peers, p) - } - if err := iter.Error(); err != nil { - return nil, err - } - return peers, nil -} diff --git a/pkg/state/state.go b/pkg/state/state.go index dcc39a1a8..090c4b571 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -338,9 +338,8 @@ type stateManager struct { genesis proto.Block stateDB *stateDB - stor *blockchainEntitiesStorage - rw *blockReadWriter - peers *peerStorage + stor *blockchainEntitiesStorage + rw *blockReadWriter // BlockchainSettings: general info about the blockchain type, constants etc. settings *settings.BlockchainSettings @@ -435,7 +434,6 @@ func newStateManager(dataDir string, params StateParams, settings *settings.Bloc rw: rw, settings: settings, atx: atx, - peers: newPeerStorage(db), verificationGoroutinesNum: params.VerificationGoroutinesNum, newBlocks: newNewBlocks(rw, settings), } @@ -502,10 +500,6 @@ func (s *stateManager) Mutex() *lock.RwMutex { return lock.NewRwMutex(s.mu) } -func (s *stateManager) Peers() ([]proto.TCPAddr, error) { - return s.peers.peers() -} - func (s *stateManager) setGenesisBlock(genesisBlock proto.Block) error { s.genesis = genesisBlock return nil @@ -1555,11 +1549,6 @@ func (s *stateManager) BlockchainSettings() (*settings.BlockchainSettings, error return &cp, nil } -func (s *stateManager) SavePeers(peers []proto.TCPAddr) error { - return s.peers.savePeers(peers) - -} - func (s *stateManager) ResetValidationList() { s.reset() if err := s.stor.scriptsStorage.clear(); err != nil { diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 275b7e7ed..55bfe1688 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -4,7 +4,6 @@ import ( "fmt" "io/ioutil" "math/big" - "net" "os" "path/filepath" "testing" @@ -288,41 +287,6 @@ func TestStateIntegrated(t *testing.T) { } } -func TestStateManager_SavePeers(t *testing.T) { - dataDir, err := ioutil.TempDir(os.TempDir(), "dataDir") - if err != nil { - t.Fatalf("Failed to create temp dir for data: %v\n", err) - } - defer func() { - err = os.RemoveAll(dataDir) - require.NoError(t, err) - }() - - manager, err := newStateManager(dataDir, DefaultTestingStateParams(), settings.MainNetSettings) - if err != nil { - t.Fatalf("Failed to create state manager: %v.\n", err) - } - defer func() { - err := manager.Close() - require.NoError(t, err) - }() - - peers, err := manager.Peers() - require.NoError(t, err) - assert.Len(t, peers, 0) - - peers = []proto.TCPAddr{ - proto.NewTCPAddr(net.IPv4(127, 0, 0, 1), 65535), - proto.NewTCPAddr(net.IPv4(83, 127, 1, 254).To4(), 80), - } - require.NoError(t, manager.SavePeers(peers)) - - // check that peers saved - peers2, err := manager.Peers() - require.NoError(t, err) - assert.Len(t, peers2, 2) -} - func TestPreactivatedFeatures(t *testing.T) { blocksPath, err := blocksPath() assert.NoError(t, err) diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index 0fd4cffd1..217150867 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -115,12 +115,6 @@ func (a *ThreadSafeReadWrapper) BlockchainSettings() (*settings.BlockchainSettin return a.s.BlockchainSettings() } -func (a *ThreadSafeReadWrapper) Peers() ([]proto.TCPAddr, error) { - a.mu.RLock() - defer a.mu.RUnlock() - return a.s.Peers() -} - func (a *ThreadSafeReadWrapper) VotesNum(featureID int16) (uint64, error) { a.mu.RLock() defer a.mu.RUnlock() @@ -407,12 +401,6 @@ func (a *ThreadSafeWriteWrapper) TxValidation(f func(validation TxValidation) er return f(a.s) } -func (a *ThreadSafeWriteWrapper) SavePeers(peers []proto.TCPAddr) error { - a.lock() - defer a.unlock() - return a.s.SavePeers(peers) -} - func (a *ThreadSafeWriteWrapper) StartProvidingExtendedApi() error { a.lock() defer a.unlock() From ffe37e678a17255befb213826cab77a76aa8b016 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Wed, 9 Jun 2021 12:58:00 +0300 Subject: [PATCH 48/52] Fixed sender address handling in LeaseScriptAction (#487) --- pkg/state/invoke_applier.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index bff57df8f..2ef906b6b 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -529,23 +529,23 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in ia.stor.sponsoredAssets.sponsorAssetUncertain(a.AssetID, uint64(a.MinFee)) case *proto.LeaseScriptAction: - recipientAddress := a.Recipient.Address - if recipientAddress == nil { + if a.Recipient.Address == nil { return proto.DAppError, info.failedChanges, errors.New("transfer has unresolved aliases") } - if info.scriptAddr == recipientAddress { + recipientAddress := *a.Recipient.Address + if senderAddress == recipientAddress { return proto.DAppError, info.failedChanges, errors.New("leasing to itself is not allowed") } if a.Amount <= 0 { return proto.DAppError, info.failedChanges, errors.New("non-positive leasing amount") } - totalChanges.appendAddr(*recipientAddress) + totalChanges.appendAddr(recipientAddress) // Add new leasing info - l := &leasing{true, uint64(a.Amount), *recipientAddress, *info.scriptAddr} + l := &leasing{true, uint64(a.Amount), recipientAddress, senderAddress} ia.stor.leases.addLeasingUncertain(a.ID, l) - txDiff, err := ia.newTxDiffFromScriptLease(senderAddress, *recipientAddress, a) + txDiff, err := ia.newTxDiffFromScriptLease(senderAddress, recipientAddress, a) if err != nil { return proto.DAppError, info.failedChanges, err } @@ -564,7 +564,7 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in return proto.DAppError, info.failedChanges, err } if senderAddress != li.sender { - return proto.DAppError, info.failedChanges, errors.Errorf("attempt to cancel leasing that was created by other account") //TODO: Create a scala compatible error in errs package and use it here + return proto.DAppError, info.failedChanges, errors.Errorf("attempt to cancel leasing that was created by other account; leaser '%s'; canceller '%s'; leasing: %s", li.sender.String(), senderAddress.String(), a.LeaseID.String()) //TODO: Create a scala compatible error in errs package and use it here } // Update leasing info if err := ia.stor.leases.cancelLeasingUncertain(a.LeaseID, !info.initialisation); err != nil { From 480a02acd5dc99dcf50a7f70d447b75a07d1bcab Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Wed, 9 Jun 2021 14:33:52 +0300 Subject: [PATCH 49/52] Cancel leases to stolen aliases (#486) * WIP: Attempt to collect leases to stolen aliases. * Leasing info in state expanded, new fields added. Tests restored. * Collection of leases on stolen aliases reimplemented. * OriginalTransactionID field in leasing made optional. * Fixed state hash generation for leases statuses * Fixed sender address handling in LeaseScriptAction * Moved closing of iterator to defer. --- go.mod | 2 +- go.sum | 4 +- pkg/state/aliases.go | 24 ++++ pkg/state/aliases_test.go | 2 +- pkg/state/constants.go | 2 +- pkg/state/history_storage.go | 3 +- pkg/state/invoke_applier.go | 26 ++-- pkg/state/keys.go | 15 +++ pkg/state/leases.go | 159 ++++++++++++++---------- pkg/state/leases_test.go | 37 +++--- pkg/state/state.go | 37 +++++- pkg/state/threadsafe_wrapper.go | 8 +- pkg/state/transaction_checker.go | 4 +- pkg/state/transaction_checker_test.go | 14 +-- pkg/state/transaction_differ.go | 8 +- pkg/state/transaction_differ_test.go | 4 +- pkg/state/transaction_performer.go | 17 ++- pkg/state/transaction_performer_test.go | 90 +++++++------- 18 files changed, 288 insertions(+), 168 deletions(-) diff --git a/go.mod b/go.mod index 1596a28bc..f84213682 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/coocood/freecache v1.1.0 github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // indirect github.com/ericlagergren/decimal v0.0.0-20190912144844-2c3e3e1ef942 - github.com/fxamacker/cbor/v2 v2.2.0 + github.com/fxamacker/cbor/v2 v2.3.0 github.com/go-chi/chi v4.0.3+incompatible github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.2 diff --git a/go.sum b/go.sum index 9d1041c36..926a746d1 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= -github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.3.0 h1:aM45YGMctNakddNNAezPxDUpv38j44Abh+hifNuqXik= +github.com/fxamacker/cbor/v2 v2.3.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= diff --git a/pkg/state/aliases.go b/pkg/state/aliases.go index 8eeaba9b9..adcb1d40f 100644 --- a/pkg/state/aliases.go +++ b/pkg/state/aliases.go @@ -231,3 +231,27 @@ func (a *aliases) reset() { a.disabled = make(map[string]bool) a.hasher.reset() } + +func (a *aliases) disabledAliases() (map[string]struct{}, error) { + iter, err := a.db.NewKeyIterator([]byte{disabledAliasKeyPrefix}) + if err != nil { + return nil, err + } + defer func() { + iter.Release() + if err := iter.Error(); err != nil { + zap.S().Fatalf("Iterator error: %v", err) + } + }() + als := make(map[string]struct{}) + for iter.Next() { + keyBytes := iter.Key() + var key disabledAliasKey + err := key.unmarshal(keyBytes) + if err != nil { + return nil, err + } + als[key.alias] = struct{}{} + } + return als, nil +} diff --git a/pkg/state/aliases_test.go b/pkg/state/aliases_test.go index ac2ad3ee7..071d48e61 100644 --- a/pkg/state/aliases_test.go +++ b/pkg/state/aliases_test.go @@ -56,7 +56,7 @@ func TestDisableStolenAliases(t *testing.T) { to.flush(t) err = to.entities.aliases.disableStolenAliases() - assert.NoError(t, err, "disableStolenAlises() failed") + assert.NoError(t, err, "disableStolenAliases() failed") to.flush(t) disabled, err := to.entities.aliases.isDisabled(aliasStr) assert.NoError(t, err, "isDisabled() failed") diff --git a/pkg/state/constants.go b/pkg/state/constants.go index a5e35f063..5147d0cd9 100644 --- a/pkg/state/constants.go +++ b/pkg/state/constants.go @@ -25,7 +25,7 @@ const ( // StateVersion is current version of state internal storage formats. // It increases when backward compatibility with previous storage version is lost. - StateVersion = 7 + StateVersion = 8 // Memory limit for address transactions. flush() is called when this // limit is exceeded. diff --git a/pkg/state/history_storage.go b/pkg/state/history_storage.go index c89a054c6..27758f975 100644 --- a/pkg/state/history_storage.go +++ b/pkg/state/history_storage.go @@ -63,8 +63,7 @@ var properties = map[blockchainEntity]blockchainEntityProperties{ lease: { needToFilter: true, needToCut: true, - fixedSize: true, - recordSize: leasingRecordSize + 4, + fixedSize: false, }, wavesBalance: { needToFilter: true, diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 2ef906b6b..81c98962d 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -148,12 +148,12 @@ func (ia *invokeApplier) newTxDiffFromScriptLease(senderAddress, recipientAddres func (ia *invokeApplier) newTxDiffFromScriptLeaseCancel(senderAddress proto.Address, leaseInfo *leasing) (txDiff, error) { diff := newTxDiff() senderKey := wavesBalanceKey{address: senderAddress} - senderLeaseOutDiff := -int64(leaseInfo.leaseAmount) + senderLeaseOutDiff := -int64(leaseInfo.Amount) if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, senderLeaseOutDiff, false)); err != nil { return nil, err } - receiverKey := wavesBalanceKey{address: leaseInfo.recipient} - receiverLeaseInDiff := -int64(leaseInfo.leaseAmount) + receiverKey := wavesBalanceKey{address: leaseInfo.Recipient} + receiverLeaseInDiff := -int64(leaseInfo.Amount) if err := diff.appendBalanceDiff(receiverKey.bytes(), newBalanceDiff(0, receiverLeaseInDiff, 0, false)); err != nil { return nil, err } @@ -542,7 +542,15 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in totalChanges.appendAddr(recipientAddress) // Add new leasing info - l := &leasing{true, uint64(a.Amount), recipientAddress, senderAddress} + l := &leasing{ + OriginTransactionID: tx.ID, + Sender: senderAddress, + Recipient: recipientAddress, + Amount: uint64(a.Amount), + Height: info.blockInfo.Height, + Status: LeaseActive, + RecipientAlias: a.Recipient.Alias, + } ia.stor.leases.addLeasingUncertain(a.ID, l) txDiff, err := ia.newTxDiffFromScriptLease(senderAddress, recipientAddress, a) @@ -563,16 +571,16 @@ func (ia *invokeApplier) fallibleValidation(tx *proto.InvokeScriptWithProofs, in if err != nil { return proto.DAppError, info.failedChanges, err } - if senderAddress != li.sender { - return proto.DAppError, info.failedChanges, errors.Errorf("attempt to cancel leasing that was created by other account; leaser '%s'; canceller '%s'; leasing: %s", li.sender.String(), senderAddress.String(), a.LeaseID.String()) //TODO: Create a scala compatible error in errs package and use it here + if senderAddress != li.Sender { + return proto.DAppError, info.failedChanges, errors.Errorf("attempt to cancel leasing that was created by other account; leaser '%s'; canceller '%s'; leasing: %s", li.Sender.String(), senderAddress.String(), a.LeaseID.String()) //TODO: Create a scala compatible error in errs package and use it here } // Update leasing info - if err := ia.stor.leases.cancelLeasingUncertain(a.LeaseID, !info.initialisation); err != nil { + if err := ia.stor.leases.cancelLeasingUncertain(a.LeaseID, info.blockInfo.Height, tx.ID, !info.initialisation); err != nil { return proto.DAppError, info.failedChanges, errors.Wrap(err, "failed to cancel leasing") } - totalChanges.appendAddr(li.sender) - totalChanges.appendAddr(li.recipient) + totalChanges.appendAddr(li.Sender) + totalChanges.appendAddr(li.Recipient) txDiff, err := ia.newTxDiffFromScriptLeaseCancel(senderAddress, li) if err != nil { return proto.DAppError, info.failedChanges, err diff --git a/pkg/state/keys.go b/pkg/state/keys.go index 2faac5307..f25a43db1 100644 --- a/pkg/state/keys.go +++ b/pkg/state/keys.go @@ -390,6 +390,21 @@ func (k *disabledAliasKey) bytes() []byte { return buf } +func (k *disabledAliasKey) unmarshal(data []byte) error { + if len(data) != disabledAliasKeySize { + return errInvalidDataSize + } + if data[0] != disabledAliasKeyPrefix { + return errInvalidPrefix + } + var err error + k.alias, err = proto.StringWithUInt16Len(data[1:]) + if err != nil { + return errors.Wrap(err, "StringWithUInt16Len() failed") + } + return nil +} + type activatedFeaturesKey struct { featureID int16 } diff --git a/pkg/state/leases.go b/pkg/state/leases.go index d8e20ed45..faaf46528 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -2,9 +2,9 @@ package state import ( "bytes" - "encoding/binary" "io" + "github.com/fxamacker/cbor/v2" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/keyvalue" @@ -12,8 +12,12 @@ import ( "go.uber.org/zap" ) +type LeaseStatus byte + const ( - leasingRecordSize = 1 + 8 + proto.AddressSize*2 + LeaseActive LeaseStatus = iota + LeaseCanceled + LeaseExpired ) type leaseRecordForStateHashes struct { @@ -37,38 +41,19 @@ func (lr *leaseRecordForStateHashes) less(other stateComponent) bool { } type leasing struct { - isActive bool - leaseAmount uint64 - recipient proto.Address - sender proto.Address -} - -type leasingRecord struct { - leasing -} - -func (l *leasingRecord) marshalBinary() ([]byte, error) { - res := make([]byte, leasingRecordSize) - proto.PutBool(res[0:1], l.isActive) - binary.BigEndian.PutUint64(res[1:9], l.leaseAmount) - copy(res[9:9+proto.AddressSize], l.recipient[:]) - copy(res[9+proto.AddressSize:9+proto.AddressSize*2], l.sender[:]) - return res, nil + Sender proto.Address `cbor:"0,keyasint"` + Recipient proto.Address `cbor:"1,keyasint"` + Amount uint64 `cbor:"2,keyasint"` + Height uint64 `cbor:"3,keyasint"` + Status LeaseStatus `cbor:"4,keyasint"` + OriginTransactionID *crypto.Digest `cbor:"5,keyasint,omitempty"` + RecipientAlias *proto.Alias `cbor:"6,keyasint,omitempty"` + CancelHeight uint64 `cbor:"7,keyasint,omitempty"` + CancelTransactionID *crypto.Digest `cbor:"8,keyasint,omitempty"` } -func (l *leasingRecord) unmarshalBinary(data []byte) error { - if len(data) != leasingRecordSize { - return errInvalidDataSize - } - var err error - l.isActive, err = proto.Bool(data[0:1]) - if err != nil { - return err - } - l.leaseAmount = binary.BigEndian.Uint64(data[1:9]) - copy(l.recipient[:], data[9:9+proto.AddressSize]) - copy(l.sender[:], data[9+proto.AddressSize:9+proto.AddressSize*2]) - return nil +func (l leasing) isActive() bool { + return l.Status == LeaseActive } type leases struct { @@ -106,24 +91,24 @@ func (l *leases) cancelLeases(bySenders map[proto.Address]struct{}, blockID prot for leaseIter.Next() { key := keyvalue.SafeKey(leaseIter) leaseBytes := keyvalue.SafeValue(leaseIter) - var leaseRecord leasingRecord - if err := leaseRecord.unmarshalBinary(leaseBytes); err != nil { - return errors.Errorf("failed to unmarshal lease: %v", err) + record := new(leasing) + if err := cbor.Unmarshal(leaseBytes, record); err != nil { + return errors.Wrap(err, "failed to unmarshal lease") } toCancel := true if bySenders != nil { - _, toCancel = bySenders[leaseRecord.sender] + _, toCancel = bySenders[record.Sender] } - if leaseRecord.isActive && toCancel { + if record.isActive() && toCancel { // Cancel lease. var k leaseKey if err := k.unmarshal(key); err != nil { - return errors.Errorf("failed to unmarshal lease key: %v", err) + return errors.Wrap(err, "failed to unmarshal lease key") } zap.S().Infof("State: cancelling lease %s", k.leaseID.String()) - leaseRecord.isActive = false - if err := l.addLeasing(k.leaseID, &leaseRecord.leasing, blockID); err != nil { - return errors.Errorf("failed to save lease to storage: %v", err) + record.Status = LeaseCanceled + if err := l.addLeasing(k.leaseID, record, blockID); err != nil { + return errors.Wrap(err, "failed to save lease to storage") } } } @@ -131,6 +116,45 @@ func (l *leases) cancelLeases(bySenders map[proto.Address]struct{}, blockID prot return nil } +func (l *leases) cancelLeasesToAliases(aliases map[string]struct{}, blockID proto.BlockID) error { + leaseIter, err := l.hs.newNewestTopEntryIterator(lease, true) + if err != nil { + return errors.Wrap(err, "failed to create key iterator to cancel leases to stolen aliases") + } + defer func() { + leaseIter.Release() + if err := leaseIter.Error(); err != nil { + zap.S().Fatalf("Iterator error: %v", err) + } + }() + + // Iterate all the leases. + zap.S().Info("Started collecting leases") + for leaseIter.Next() { + keyBytes := keyvalue.SafeKey(leaseIter) + var key leaseKey + if err := key.unmarshal(keyBytes); err != nil { + return errors.Wrap(err, "failed ot unmarshal leasing key") + } + leaseBytes := keyvalue.SafeValue(leaseIter) + record := new(leasing) + if err := cbor.Unmarshal(leaseBytes, record); err != nil { + return errors.Wrap(err, "failed to unmarshal lease") + } + if record.isActive() && record.RecipientAlias != nil { + if _, ok := aliases[record.RecipientAlias.Alias]; ok { + zap.S().Infof("State: canceling lease %s", key.leaseID.String()) + record.Status = LeaseCanceled + if err := l.addLeasing(key.leaseID, record, blockID); err != nil { + return errors.Wrap(err, "failed to save lease to storage") + } + } + } + } + zap.S().Info("Finished collecting leases") + return nil +} + func (l *leases) validLeaseIns() (map[proto.Address]int64, error) { leaseIter, err := l.hs.newNewestTopEntryIterator(lease, true) if err != nil { @@ -148,12 +172,12 @@ func (l *leases) validLeaseIns() (map[proto.Address]int64, error) { zap.S().Info("Started collecting leases") for leaseIter.Next() { leaseBytes := keyvalue.SafeValue(leaseIter) - var lease leasingRecord - if err := lease.unmarshalBinary(leaseBytes); err != nil { - return nil, errors.Errorf("failed to unmarshal lease: %v", err) + record := new(leasing) + if err := cbor.Unmarshal(leaseBytes, record); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal lease") } - if lease.isActive { - leaseIns[lease.recipient] += int64(lease.leaseAmount) + if record.isActive() { + leaseIns[record.Recipient] += int64(record.Amount) } } zap.S().Info("Finished collecting leases") @@ -171,11 +195,14 @@ func (l *leases) newestLeasingInfo(id crypto.Digest, filter bool) (*leasing, err if err != nil { return nil, err } - var record leasingRecord - if err := record.unmarshalBinary(recordBytes); err != nil { - return nil, errors.Errorf("failed to unmarshal record: %v", err) + record := new(leasing) + if err := cbor.Unmarshal(recordBytes, record); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal record") } - return &record.leasing, nil + if record.OriginTransactionID == nil { + record.OriginTransactionID = &id + } + return record, nil } // Stable leasing info from DB. @@ -185,11 +212,14 @@ func (l *leases) leasingInfo(id crypto.Digest, filter bool) (*leasing, error) { if err != nil { return nil, err } - var record leasingRecord - if err := record.unmarshalBinary(recordBytes); err != nil { - return nil, errors.Errorf("failed to unmarshal record: %v", err) + record := new(leasing) + if err := cbor.Unmarshal(recordBytes, record); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal record") + } + if record.OriginTransactionID == nil { + record.OriginTransactionID = &id } - return &record.leasing, nil + return record, nil } func (l *leases) isActive(id crypto.Digest, filter bool) (bool, error) { @@ -197,21 +227,20 @@ func (l *leases) isActive(id crypto.Digest, filter bool) (bool, error) { if err != nil { return false, err } - return info.isActive, nil + return info.isActive(), nil } func (l *leases) addLeasing(id crypto.Digest, leasing *leasing, blockID proto.BlockID) error { key := leaseKey{leaseID: id} keyBytes := key.bytes() keyStr := string(keyBytes) - r := &leasingRecord{*leasing} - recordBytes, err := r.marshalBinary() + recordBytes, err := cbor.Marshal(leasing) if err != nil { - return errors.Errorf("failed to marshal record: %v", err) + return errors.Wrap(err, "failed to marshal record") } if l.calculateHashes { active := byte(0) - if leasing.isActive { + if leasing.isActive() { active = byte(1) } lr := &leaseRecordForStateHashes{ @@ -232,21 +261,25 @@ func (l *leases) addLeasingUncertain(id crypto.Digest, leasing *leasing) { l.uncertainLeases[id] = leasing } -func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, filter bool) error { +func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, height uint64, txID *crypto.Digest, filter bool) error { leasing, err := l.newestLeasingInfo(id, filter) if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.isActive = false + leasing.Status = LeaseCanceled + leasing.CancelHeight = height + leasing.CancelTransactionID = txID return l.addLeasing(id, leasing, blockID) } -func (l *leases) cancelLeasingUncertain(id crypto.Digest, filter bool) error { +func (l *leases) cancelLeasingUncertain(id crypto.Digest, height uint64, txID *crypto.Digest, filter bool) error { leasing, err := l.newestLeasingInfo(id, filter) if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.isActive = false + leasing.Status = LeaseCanceled + leasing.CancelTransactionID = txID + leasing.CancelHeight = height l.addLeasingUncertain(id, leasing) return nil } diff --git a/pkg/state/leases_test.go b/pkg/state/leases_test.go index 63e0a251f..f890f3dc2 100644 --- a/pkg/state/leases_test.go +++ b/pkg/state/leases_test.go @@ -24,16 +24,17 @@ func createLeases() (*leasesTestObjects, []string, error) { return &leasesTestObjects{stor, leases}, path, nil } -func createLease(t *testing.T, sender string) *leasing { +func createLease(t *testing.T, sender string, id crypto.Digest) *leasing { senderAddr, err := proto.NewAddressFromString(sender) assert.NoError(t, err, "failed to create address from string") recipientAddr, err := proto.NewAddressFromString("3PDdGex1meSUf4Yq5bjPBpyAbx6us9PaLfo") assert.NoError(t, err, "failed to create address from string") return &leasing{ - isActive: true, - leaseAmount: 10, - recipient: recipientAddr, - sender: senderAddr, + OriginTransactionID: &id, + Recipient: recipientAddr, + Sender: senderAddr, + Amount: 10, + Status: LeaseActive, } } @@ -59,7 +60,7 @@ func TestCancelLeases(t *testing.T) { for _, l := range leasings { leaseID, err := crypto.NewDigestFromBytes(bytes.Repeat([]byte{l.leaseIDByte}, crypto.DigestSize)) assert.NoError(t, err, "failed to create digest from bytes") - r := createLease(t, l.sender) + r := createLease(t, l.sender, leaseID) err = to.leases.addLeasing(leaseID, r, blockID0) assert.NoError(t, err, "failed to add leasing") } @@ -82,10 +83,10 @@ func TestCancelLeases(t *testing.T) { assert.NoError(t, err) if l.sender == badSenderStr { assert.Equal(t, false, active) - assert.Equal(t, leasing.isActive, false, "did not cancel leasing by sender") + assert.Equal(t, leasing.isActive(), false, "did not cancel leasing by sender") } else { assert.Equal(t, true, active) - assert.Equal(t, leasing.isActive, true, "cancelled leasing with different sender") + assert.Equal(t, leasing.isActive(), true, "cancelled leasing with different sender") } } // Cancel all the leases and check. @@ -97,7 +98,7 @@ func TestCancelLeases(t *testing.T) { assert.NoError(t, err, "failed to create digest from bytes") leasing, err := to.leases.leasingInfo(leaseID, true) assert.NoError(t, err, "failed to get leasing") - assert.Equal(t, leasing.isActive, false, "did not cancel all the leasings") + assert.Equal(t, leasing.isActive(), false, "did not cancel all the leasings") active, err := to.leases.isActive(leaseID, true) assert.NoError(t, err) assert.Equal(t, false, active) @@ -127,10 +128,10 @@ func TestValidLeaseIns(t *testing.T) { for _, l := range leasings { leaseID, err := crypto.NewDigestFromBytes(bytes.Repeat([]byte{l.leaseIDByte}, crypto.DigestSize)) assert.NoError(t, err, "failed to create digest from bytes") - r := createLease(t, l.sender) + r := createLease(t, l.sender, leaseID) err = to.leases.addLeasing(leaseID, r, blockID0) assert.NoError(t, err, "failed to add leasing") - properLeaseIns[r.recipient] += int64(r.leaseAmount) + properLeaseIns[r.Recipient] += int64(r.Amount) } leaseIns, err := to.leases.validLeaseIns() assert.NoError(t, err, "validLeaseIns() failed") @@ -156,7 +157,7 @@ func TestAddLeasing(t *testing.T) { leaseID, err := crypto.NewDigestFromBytes(bytes.Repeat([]byte{0xff}, crypto.DigestSize)) assert.NoError(t, err, "failed to create digest from bytes") senderStr := "3PNXHYoWp83VaWudq9ds9LpS5xykWuJHiHp" - r := createLease(t, senderStr) + r := createLease(t, senderStr, leaseID) err = to.leases.addLeasing(leaseID, r, blockID0) assert.NoError(t, err, "failed to add leasing") l, err := to.leases.newestLeasingInfo(leaseID, true) @@ -182,15 +183,19 @@ func TestCancelLeasing(t *testing.T) { to.stor.addBlock(t, blockID0) leaseID, err := crypto.NewDigestFromBytes(bytes.Repeat([]byte{0xff}, crypto.DigestSize)) assert.NoError(t, err, "failed to create digest from bytes") + txID, err := crypto.NewDigestFromBytes(bytes.Repeat([]byte{0xfe}, crypto.DigestSize)) + assert.NoError(t, err, "failed to create digest from bytes") senderStr := "3PNXHYoWp83VaWudq9ds9LpS5xykWuJHiHp" - r := createLease(t, senderStr) + r := createLease(t, senderStr, leaseID) err = to.leases.addLeasing(leaseID, r, blockID0) assert.NoError(t, err, "failed to add leasing") - err = to.leases.cancelLeasing(leaseID, blockID0, true) + err = to.leases.cancelLeasing(leaseID, blockID0, to.stor.rw.height, &txID, true) assert.NoError(t, err, "failed to cancel leasing") - r.isActive = false + r.Status = LeaseCanceled + r.CancelHeight = 1 + r.CancelTransactionID = &txID to.stor.flush(t) resLeasing, err := to.leases.leasingInfo(leaseID, true) assert.NoError(t, err, "failed to get leasing info") - assert.Equal(t, resLeasing, r, "invalid leasing record after cancelation") + assert.Equal(t, resLeasing, r, "invalid leasing record after cancellation") } diff --git a/pkg/state/state.go b/pkg/state/state.go index 090c4b571..fd4059109 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -690,10 +690,10 @@ func (s *stateManager) NewestLeasingInfo(id crypto.Digest) (*proto.LeaseInfo, er return nil, err } leaseInfo := proto.LeaseInfo{ - Sender: leaseFromStore.sender, - Recipient: leaseFromStore.recipient, - IsActive: leaseFromStore.isActive, - LeaseAmount: leaseFromStore.leaseAmount, + Sender: leaseFromStore.Sender, + Recipient: leaseFromStore.Recipient, + IsActive: leaseFromStore.isActive(), + LeaseAmount: leaseFromStore.Amount, } return &leaseInfo, nil } @@ -1157,6 +1157,15 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } dataTxHeight = approvalHeight + s.settings.ActivationWindowSize(blockchainHeight) } + rideV5Activated := s.stor.features.newestIsActivatedAtHeight(int16(settings.RideV5), blockchainHeight) + var rideV5Height uint64 = 0 + if rideV5Activated { + approvalHeight, err := s.stor.features.newestApprovalHeight(int16(settings.RideV5)) + if err != nil { + return false, err + } + rideV5Height = approvalHeight + s.settings.ActivationWindowSize(blockchainHeight) + } switch blockchainHeight { case s.settings.ResetEffectiveBalanceAtHeight: return true, nil @@ -1166,6 +1175,9 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) case dataTxHeight: // Only needed for MainNet. return s.settings.Type == settings.MainNet, nil + case rideV5Height: + // Cancellation of leasings to stolen aliases only required for MainNet + return s.settings.Type == settings.MainNet, nil default: return false, nil } @@ -1248,6 +1260,15 @@ func (s *stateManager) cancelLeases(height uint64, blockID proto.BlockID, initia } dataTxHeight = approvalHeight + s.settings.ActivationWindowSize(height) } + rideV5Activated := s.stor.features.newestIsActivatedAtHeight(int16(settings.RideV5), height) + var rideV5Height uint64 = 0 + if rideV5Activated { + approvalHeight, err := s.stor.features.newestApprovalHeight(int16(settings.RideV5)) + if err != nil { + return err + } + rideV5Height = approvalHeight + s.settings.ActivationWindowSize(height) + } if height == s.settings.ResetEffectiveBalanceAtHeight { if err := s.stor.leases.cancelLeases(nil, blockID); err != nil { return err @@ -1271,6 +1292,14 @@ func (s *stateManager) cancelLeases(height uint64, blockID proto.BlockID, initia if err := s.stor.balances.cancelInvalidLeaseIns(leaseIns, blockID); err != nil { return err } + } else if rideV5Activated && height == rideV5Height { + disabledAliases, err := s.stor.aliases.disabledAliases() + if err != nil { + return err + } + if err = s.stor.leases.cancelLeasesToAliases(disabledAliases, blockID); err != nil { + return err + } } return nil } diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index 217150867..474e4ad0e 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -332,13 +332,7 @@ func (a *ThreadSafeWriteWrapper) Map(f func(state NonThreadSafeState) error) err return f(a.s) } -func (a *ThreadSafeWriteWrapper) ValidateNextTx( - tx proto.Transaction, - currentTimestamp uint64, - parentTimestamp uint64, - blockVersion proto.BlockVersion, - checkScripts bool, -) error { +func (a *ThreadSafeWriteWrapper) ValidateNextTx(_ proto.Transaction, _, _ uint64, _ proto.BlockVersion, _ bool) error { panic("Invalid ValidateNextTx usage on thread safe wrapper. Should call TxValidation") } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 58be3db49..9fbd38627 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -810,14 +810,14 @@ func (tc *transactionChecker) checkLeaseCancel(tx *proto.LeaseCancel, info *chec if err != nil { return errs.Extend(err, "no leasing info found for this leaseID") } - if !l.isActive && (info.currentTimestamp > tc.settings.AllowMultipleLeaseCancelUntilTime) { + if !l.isActive() && (info.currentTimestamp > tc.settings.AllowMultipleLeaseCancelUntilTime) { return errs.NewTxValidationError("Reason: Cannot cancel already cancelled lease") } senderAddr, err := proto.NewAddressFromPublicKey(tc.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return err } - if (l.sender != senderAddr) && (info.currentTimestamp > tc.settings.AllowMultipleLeaseCancelUntilTime) { + if (l.Sender != senderAddr) && (info.currentTimestamp > tc.settings.AllowMultipleLeaseCancelUntilTime) { return errs.NewTxValidationError("LeaseTransaction was leased by other sender") } return nil diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 52c8bb129..30d44e8b4 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -286,7 +286,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(t)) + err = to.tp.performReissueWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -340,7 +340,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(t)) + err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -722,7 +722,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(t)) + err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -757,7 +757,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(t)) + err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -773,7 +773,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(t)) + err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -797,7 +797,7 @@ func TestCheckCreateAliasWithSig(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(t)) + err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -832,7 +832,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(t)) + err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) diff --git a/pkg/state/transaction_differ.go b/pkg/state/transaction_differ.go index e37c02f0f..05b4340d6 100644 --- a/pkg/state/transaction_differ.go +++ b/pkg/state/transaction_differ.go @@ -971,7 +971,7 @@ func (td *transactionDiffer) createDiffLeaseCancel(tx *proto.LeaseCancel, info * return txBalanceChanges{}, err } senderKey := wavesBalanceKey{address: senderAddr} - senderLeaseOutDiff := -int64(l.leaseAmount) + senderLeaseOutDiff := -int64(l.Amount) if err := diff.appendBalanceDiff(senderKey.bytes(), newBalanceDiff(0, 0, senderLeaseOutDiff, false)); err != nil { return txBalanceChanges{}, err } @@ -980,8 +980,8 @@ func (td *transactionDiffer) createDiffLeaseCancel(tx *proto.LeaseCancel, info * return txBalanceChanges{}, err } // Append receiver diff. - receiverKey := wavesBalanceKey{address: l.recipient} - receiverLeaseInDiff := -int64(l.leaseAmount) + receiverKey := wavesBalanceKey{address: l.Recipient} + receiverLeaseInDiff := -int64(l.Amount) if err := diff.appendBalanceDiff(receiverKey.bytes(), newBalanceDiff(0, receiverLeaseInDiff, 0, false)); err != nil { return txBalanceChanges{}, err } @@ -990,7 +990,7 @@ func (td *transactionDiffer) createDiffLeaseCancel(tx *proto.LeaseCancel, info * return txBalanceChanges{}, errors.Wrap(err, "failed to append miner payout") } } - addresses := []proto.Address{senderAddr, l.recipient} + addresses := []proto.Address{senderAddr, l.Recipient} changes := newTxBalanceChanges(addresses, diff) return changes, nil } diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index cc36945e4..3a2debf50 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -825,7 +825,7 @@ func TestCreateDiffLeaseCancelWithSig(t *testing.T) { }() leaseTx := createLeaseWithSig(t) - info := defaultPerformerInfo(t) + info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) err := to.tp.performLeaseWithSig(leaseTx, info) assert.NoError(t, err, "performLeaseWithSig failed") @@ -865,7 +865,7 @@ func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { }() leaseTx := createLeaseWithProofs(t) - info := defaultPerformerInfo(t) + info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) err := to.tp.performLeaseWithProofs(leaseTx, info) assert.NoError(t, err, "performLeaseWithProofs failed") diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d4e9216f2..d4c70bcbb 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -194,7 +194,14 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, recipientAddr = tx.Recipient.Address } // Add leasing to lease state. - l := &leasing{true, tx.Amount, *recipientAddr, senderAddr} + l := &leasing{ + Sender: senderAddr, + Recipient: *recipientAddr, + Amount: tx.Amount, + Height: info.height, + Status: LeaseActive, + RecipientAlias: tx.Recipient.Alias, + } if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { return errors.Wrap(err, "failed to add leasing") } @@ -217,8 +224,8 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac return tp.performLease(&tx.Lease, tx.ID, info) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, info *performerInfo) error { - if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, !info.initialisation); err != nil { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo) error { + if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID, !info.initialisation); err != nil { return errors.Wrap(err, "failed to cancel leasing") } return nil @@ -229,7 +236,7 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran if !ok { return errors.New("failed to convert interface to LeaseCancelWithSig transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, info) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) } func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo) error { @@ -237,7 +244,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T if !ok { return errors.New("failed to convert interface to LeaseCancelWithProofs transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, info) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) } func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo) error { diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 3966be521..0832945ce 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -24,7 +24,7 @@ func createPerformerTestObjects(t *testing.T) (*performerTestObjects, []string) return &performerTestObjects{stor, tp}, path } -func defaultPerformerInfo(t *testing.T) *performerInfo { +func defaultPerformerInfo() *performerInfo { return &performerInfo{false, 0, blockID0} } @@ -40,7 +40,7 @@ func TestPerformIssueWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(t)) + err := to.tp.performIssueWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) assetInfo := assetInfo{ @@ -75,7 +75,7 @@ func TestPerformIssueWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) assetInfo := assetInfo{ @@ -110,7 +110,7 @@ func TestPerformReissueWithSig(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(t)) + err := to.tp.performReissueWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -134,7 +134,7 @@ func TestPerformReissueWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -158,7 +158,7 @@ func TestPerformBurnWithSig(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(t)) + err := to.tp.performBurnWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -181,7 +181,7 @@ func TestPerformBurnWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -204,7 +204,7 @@ func TestPerformExchange(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - err := to.tp.performExchange(tx, defaultPerformerInfo(t)) + err := to.tp.performExchange(tx, defaultPerformerInfo()) assert.NoError(t, err, "performExchange() failed") sellOrderId, err := tx.GetOrder2().GetID() @@ -260,14 +260,15 @@ func TestPerformLeaseWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(t)) + err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ - isActive: true, - leaseAmount: tx.Amount, - recipient: *tx.Recipient.Address, - sender: testGlobal.senderInfo.addr, + OriginTransactionID: tx.ID, + Status: LeaseActive, + Amount: tx.Amount, + Recipient: *tx.Recipient.Address, + Sender: testGlobal.senderInfo.addr, } info, err := to.stor.entities.leases.leasingInfo(*tx.ID, true) @@ -287,14 +288,15 @@ func TestPerformLeaseWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ - isActive: true, - leaseAmount: tx.Amount, - recipient: *tx.Recipient.Address, - sender: testGlobal.senderInfo.addr, + OriginTransactionID: tx.ID, + Status: LeaseActive, + Amount: tx.Amount, + Recipient: *tx.Recipient.Address, + Sender: testGlobal.senderInfo.addr, } info, err := to.stor.entities.leases.leasingInfo(*tx.ID, true) @@ -314,17 +316,19 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(t)) + err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) + tx := createLeaseCancelWithSig(t, *leaseTx.ID) leasingInfo := &leasing{ - isActive: false, - leaseAmount: leaseTx.Amount, - recipient: *leaseTx.Recipient.Address, - sender: testGlobal.senderInfo.addr, + OriginTransactionID: leaseTx.ID, + Status: LeaseCanceled, + Amount: leaseTx.Amount, + Recipient: *leaseTx.Recipient.Address, + Sender: testGlobal.senderInfo.addr, + CancelTransactionID: tx.ID, } - tx := createLeaseCancelWithSig(t, *leaseTx.ID) - err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(t)) + err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID, true) @@ -344,17 +348,19 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(t)) + err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) + tx := createLeaseCancelWithProofs(t, *leaseTx.ID) leasingInfo := &leasing{ - isActive: false, - leaseAmount: leaseTx.Amount, - recipient: *leaseTx.Recipient.Address, - sender: testGlobal.senderInfo.addr, + OriginTransactionID: leaseTx.ID, + Status: LeaseCanceled, + Amount: leaseTx.Amount, + Recipient: *leaseTx.Recipient.Address, + Sender: testGlobal.senderInfo.addr, + CancelTransactionID: tx.ID, } - tx := createLeaseCancelWithProofs(t, *leaseTx.ID) - err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(t)) + err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID, true) @@ -374,7 +380,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(t)) + err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias, true) @@ -382,7 +388,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, *addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(t)) + err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases() @@ -404,7 +410,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias, true) @@ -412,7 +418,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, *addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(t)) + err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases() @@ -436,9 +442,9 @@ func TestPerformDataWithProofs(t *testing.T) { tx := createDataWithProofs(t, 1) entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} - tx.Entries = proto.DataEntries([]proto.DataEntry{entry}) + tx.Entries = []proto.DataEntry{entry} - err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performDataWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -460,7 +466,7 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performSponsorshipWithProofs() failed") isSponsored, err := to.stor.entities.sponsoredAssets.newestIsSponsored(tx.AssetID, true) @@ -507,7 +513,7 @@ func TestPerformSetScriptWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSetScriptWithProofs(t) - err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performSetScriptWithProofs() failed") addr := testGlobal.senderInfo.addr @@ -571,7 +577,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") assetID := tx.AssetID @@ -653,7 +659,7 @@ func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(t)) + err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo()) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name From 8409bf5f8a4882dd1049a5b79ec1e04bbffb953a Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 10 Jun 2021 11:44:18 +0300 Subject: [PATCH 50/52] Fix block complexity (#488) * Block ID added to error message about exceeding the block complexity limit. * WIP: Use actual complexity to count block complexity * WIP: For asset srcipts we store only one estimation made by estimator version that was active at the time of script installation * Storing of original estimator version added, for account verifiers new function newestOriginalScriptEstiomationByAddr is used to get estimation. * Keys reordered * Redundant type conversion removed --- pkg/state/address_transactions.go | 9 ++- pkg/state/appender.go | 6 +- pkg/state/constraints.go | 19 +++--- pkg/state/history_storage.go | 6 ++ pkg/state/keys.go | 25 +++++--- pkg/state/script_caller.go | 88 +++++++++++++++------------- pkg/state/scripts_complexity.go | 69 +++++++++++++++++----- pkg/state/scripts_complexity_test.go | 33 ++++------- pkg/state/state.go | 12 +--- pkg/state/transaction_checker.go | 32 +++++++--- 10 files changed, 182 insertions(+), 117 deletions(-) diff --git a/pkg/state/address_transactions.go b/pkg/state/address_transactions.go index 1ebadcc54..51e73b3aa 100644 --- a/pkg/state/address_transactions.go +++ b/pkg/state/address_transactions.go @@ -26,7 +26,7 @@ const ( ) var ( - fileSizeKeyBytes = []byte{txsByAddrsFileSizeKeyPrefix} + fileSizeKeyBytes = []byte{txsByAddressesFileSizeKeyPrefix} ) type txMeta struct { @@ -297,7 +297,12 @@ func (at *addressTransactions) persist(filter bool) error { if err != nil { return errors.Wrap(err, "failed to create temp file for emsort") } - defer os.Remove(tempFile.Name()) + defer func(name string) { + err := os.Remove(name) + if err != nil { + zap.S().Warnf("Failed to remove temporary file: %v", err) + } + }(tempFile.Name()) sort, err := emsort.NewFixedSize(addrTxRecordSize, maxEmsortMem, tempFile) if err != nil { return errors.Wrap(err, "emsort.NewFixedSize() failed") diff --git a/pkg/state/appender.go b/pkg/state/appender.go index c28ab3bca..f255c33d9 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -243,7 +243,7 @@ func (a *txAppender) checkTransactionScripts(tx proto.Transaction, accountScript return scriptsRuns, nil } -func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { +func (a *txAppender) checkScriptsLimits(scriptsRuns uint64, blockID proto.BlockID) error { smartAccountsActivated, err := a.stor.features.newestIsActivated(int16(settings.SmartAccounts)) if err != nil { return err @@ -260,7 +260,7 @@ func (a *txAppender) checkScriptsLimits(scriptsRuns uint64) error { maxBlockComplexity := NewMaxScriptsComplexityInBlock().GetMaxScriptsComplexityInBlock(rideV5Activated) if a.sc.getTotalComplexity() > uint64(maxBlockComplexity) { // TODO this is definitely an error, should return it - zap.S().Warnf("complexity limit per block is exceeded. total complexity of script is %d, max allowed complexity is %d", int(a.sc.getTotalComplexity()), maxBlockComplexity) + zap.S().Warnf("Complexity of scripts (%d) in block '%s' exceeds limit of %d", a.sc.getTotalComplexity(), blockID.String(), maxBlockComplexity) } return nil } else if smartAccountsActivated { @@ -453,7 +453,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } } // Check complexity limits and scripts runs limits. - if err := a.checkScriptsLimits(a.totalScriptsRuns + applicationRes.totalScriptsRuns); err != nil { + if err := a.checkScriptsLimits(a.totalScriptsRuns+applicationRes.totalScriptsRuns, blockID); err != nil { return errs.Extend(errors.Errorf("%s: %v", blockID.String(), err), "check scripts limits") } // Perform state changes, save balance changes, write tx to storage. diff --git a/pkg/state/constraints.go b/pkg/state/constraints.go index ed3debde1..d9308d8e1 100644 --- a/pkg/state/constraints.go +++ b/pkg/state/constraints.go @@ -1,5 +1,15 @@ package state +const ( + FailFreeInvokeComplexity = 1000 + FreeVerifierComplexity = 200 + MaxVerifierScriptComplexityReduced = 2000 + MaxVerifierScriptComplexity = 4000 + MaxCallableScriptComplexityV12 = 2000 + MaxCallableScriptComplexityV34 = 4000 + MaxCallableScriptComplexityV5 = 10000 +) + type MaxScriptsComplexityInBlock struct { BeforeActivationRideV5Feature int AfterActivationRideV5Feature int @@ -15,12 +25,3 @@ func (a MaxScriptsComplexityInBlock) GetMaxScriptsComplexityInBlock(isRideV5Acti } return a.BeforeActivationRideV5Feature } - -const FreeVerifierComplexity = 200 - -const MaxVerifierScriptComplexityReduced = 2000 -const MaxVerifierScriptComplexity = 4000 - -const MaxCallableScriptComplexityV12 = 2000 -const MaxCallableScriptComplexityV34 = 4000 -const MaxCallableScriptComplexityV5 = 10000 diff --git a/pkg/state/history_storage.go b/pkg/state/history_storage.go index 27758f975..99e6924d4 100644 --- a/pkg/state/history_storage.go +++ b/pkg/state/history_storage.go @@ -37,6 +37,7 @@ const ( stateHash hitSource feeDistr + accountOriginalEstimatorVersion ) type blockchainEntityProperties struct { @@ -170,6 +171,11 @@ var properties = map[blockchainEntity]blockchainEntityProperties{ needToCut: true, fixedSize: false, }, + accountOriginalEstimatorVersion: { + needToFilter: true, + needToCut: true, + fixedSize: false, + }, } type historyEntry struct { diff --git a/pkg/state/keys.go b/pkg/state/keys.go index f25a43db1..5e4d36de9 100644 --- a/pkg/state/keys.go +++ b/pkg/state/keys.go @@ -58,9 +58,6 @@ const ( // Leases. leaseKeyPrefix - // nickeskov: In legacy code this is `knownPeersPrefix` constant. We skip this value for compatibility. - _ - // Aliases. aliasKeyPrefix disabledAliasKeyPrefix @@ -91,6 +88,7 @@ const ( assetScriptKeyPrefix accountScriptComplexityKeyPrefix assetScriptComplexityKeyPrefix + accountOriginalEstimatorVersionKeyPrefix // Block Reward. blockRewardKeyPrefix @@ -108,7 +106,7 @@ const ( stateInfoKeyPrefix // Size of TransactionsByAddresses file. - txsByAddrsFileSizeKeyPrefix + txsByAddressesFileSizeKeyPrefix // Stores protobuf-related info for blockReadWriter. rwProtobufInfoKeyPrefix @@ -171,6 +169,8 @@ func prefixByEntity(entity blockchainEntity) ([]byte, error) { return []byte{hitSourceKeyPrefix}, nil case feeDistr: return []byte{blocksInfoKeyPrefix}, nil + case accountOriginalEstimatorVersion: + return []byte{accountOriginalEstimatorVersionKeyPrefix}, nil default: return nil, errors.New("bad entity type") } @@ -595,15 +595,24 @@ func (k *accountScriptComplexityKey) bytes() []byte { } type assetScriptComplexityKey struct { - ver int asset crypto.Digest } func (k *assetScriptComplexityKey) bytes() []byte { - buf := make([]byte, 2+crypto.DigestSize) + buf := make([]byte, 1+crypto.DigestSize) buf[0] = assetScriptComplexityKeyPrefix - buf[1] = byte(k.ver) - copy(buf[2:], k.asset[:]) + copy(buf[1:], k.asset[:]) + return buf +} + +type accountOriginalEstimatorVersionKey struct { + addr proto.Address +} + +func (k *accountOriginalEstimatorVersionKey) bytes() []byte { + buf := make([]byte, 1+proto.AddressSize) + buf[0] = accountOriginalEstimatorVersionKeyPrefix + copy(buf[1:], k.addr[:]) return buf } diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index 26d8a8897..42c46ad79 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -71,15 +71,16 @@ func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockIn return errors.Errorf("account script on order '%s' returned false result", base58.Encode(id)) } // Increase complexity. - ev, err := a.state.EstimatorVersion() - if err != nil { - return errors.Wrapf(err, "failed to call account script on order '%s'", base58.Encode(id)) - } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(sender, ev, !initialisation) - if err != nil { - return errors.Wrapf(err, "failed to call account script on order '%s'", base58.Encode(id)) + if isRideV5 { // After activation of RideV5 + a.recentTxComplexity += uint64(r.Complexity()) + } else { + // For account script we use original estimation + est, err := a.stor.scriptsComplexity.newestOriginalScriptComplexityByAddr(sender, !initialisation) + if err != nil { + return errors.Wrapf(err, "failed to call account script on order '%s'", base58.Encode(id)) + } + a.recentTxComplexity += uint64(est.Verifier) } - a.recentTxComplexity += uint64(est.Verifier) return nil } @@ -121,15 +122,16 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, params *app return errs.NewTransactionNotAllowedByScript("script failed", id) } // Increase complexity. - ev, err := a.state.EstimatorVersion() - if err != nil { - return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) - } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, ev, !params.initialisation) - if err != nil { - return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) + if params.rideV5Activated { // After activation of RideV5 add actual complexity + a.recentTxComplexity += uint64(r.Complexity()) + } else { + // For account script we use original estimation + est, err := a.stor.scriptsComplexity.newestOriginalScriptComplexityByAddr(senderAddr, !params.initialisation) + if err != nil { + return errors.Wrapf(err, "failed to call account script on transaction '%s'", base58.Encode(id)) + } + a.recentTxComplexity += uint64(est.Verifier) } - a.recentTxComplexity += uint64(est.Verifier) return nil } @@ -165,15 +167,16 @@ func (a *scriptCaller) callAssetScriptCommon(env *ride.EvaluationEnvironment, as return nil, errs.NewTransactionNotAllowedByScript(r.UserError(), assetID.Bytes()) } // Increase complexity. - ev, err := a.state.EstimatorVersion() - if err != nil { - return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) - } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, ev, !params.initialisation) - if err != nil { - return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) + if params.rideV5Activated { // After activation of RideV5 add actual execution complexity + a.recentTxComplexity += uint64(r.Complexity()) + } else { + // For asset script we use original estimation + est, err := a.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, !params.initialisation) + if err != nil { + return nil, errors.Wrapf(err, "failed to call script on asset '%s'", assetID.String()) + } + a.recentTxComplexity += uint64(est.Verifier) } - a.recentTxComplexity += uint64(est.Verifier) return r, nil } @@ -236,23 +239,28 @@ func (a *scriptCaller) invokeFunction(tree *ride.Tree, tx *proto.InvokeScriptWit return false, nil, errors.Errorf("unexpected ScriptResult: %v", sr) } // Increase complexity. - ev, err := a.state.EstimatorVersion() - if err != nil { - return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) - } - est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(scriptAddress, ev, !info.initialisation) - if err != nil { - return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) - } - fn := tx.FunctionCall.Name - if fn == "" && tx.FunctionCall.Default { - fn = "default" - } - c, ok := est.Functions[fn] - if !ok { - return false, nil, errors.Errorf("no estimation for function '%s' on invocation of transaction '%s'", fn, tx.ID.String()) + if info.rideV5Activated { // After activation of RideV5 add actual execution complexity + a.recentTxComplexity += uint64(r.Complexity()) + } else { + // For callable (function) we have to use latest possible estimation + ev, err := a.state.EstimatorVersion() + if err != nil { + return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) + } + est, err := a.stor.scriptsComplexity.newestScriptComplexityByAddr(scriptAddress, ev, !info.initialisation) + if err != nil { + return false, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", tx.ID.String()) + } + fn := tx.FunctionCall.Name + if fn == "" && tx.FunctionCall.Default { + fn = "default" + } + c, ok := est.Functions[fn] + if !ok { + return false, nil, errors.Errorf("no estimation for function '%s' on invocation of transaction '%s'", fn, tx.ID.String()) + } + a.recentTxComplexity += uint64(c) } - a.recentTxComplexity += uint64(c) err = nil if !r.Result() { // Replace failure status with an error err = errors.Errorf("call failed: %s", r.UserError()) diff --git a/pkg/state/scripts_complexity.go b/pkg/state/scripts_complexity.go index 6972a8f93..9ea9478c9 100644 --- a/pkg/state/scripts_complexity.go +++ b/pkg/state/scripts_complexity.go @@ -1,6 +1,8 @@ package state import ( + "math" + "github.com/fxamacker/cbor/v2" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -8,6 +10,10 @@ import ( "github.com/wavesplatform/gowaves/pkg/ride" ) +type estimatorVersionRecord struct { + Version uint8 `cbor:"0,keyasint"` +} + type scriptsComplexity struct { hs *historyStorage } @@ -29,8 +35,29 @@ func (sc *scriptsComplexity) newestScriptComplexityByAddr(addr proto.Address, ev return record, nil } -func (sc *scriptsComplexity) newestScriptComplexityByAsset(asset crypto.Digest, ev int, filter bool) (*ride.TreeEstimation, error) { - key := assetScriptComplexityKey{ev, asset} +func (sc *scriptsComplexity) originalEstimatorVersion(addr proto.Address, filter bool) (int, error) { + key := accountOriginalEstimatorVersionKey{addr} + recordBytes, err := sc.hs.newestTopEntryData(key.bytes(), filter) + if err != nil { + return 0, err + } + record := new(estimatorVersionRecord) + if err := cbor.Unmarshal(recordBytes, record); err != nil { + return 0, errors.Wrap(err, "failed to unmarshal original estimator version record") + } + return int(record.Version), nil +} + +func (sc *scriptsComplexity) newestOriginalScriptComplexityByAddr(addr proto.Address, filter bool) (*ride.TreeEstimation, error) { + ev, err := sc.originalEstimatorVersion(addr, filter) + if err != nil { + return nil, err + } + return sc.newestScriptComplexityByAddr(addr, ev, filter) +} + +func (sc *scriptsComplexity) newestScriptComplexityByAsset(asset crypto.Digest, filter bool) (*ride.TreeEstimation, error) { + key := assetScriptComplexityKey{asset} recordBytes, err := sc.hs.newestTopEntryData(key.bytes(), filter) if err != nil { return nil, err @@ -42,8 +69,8 @@ func (sc *scriptsComplexity) newestScriptComplexityByAsset(asset crypto.Digest, return record, nil } -func (sc *scriptsComplexity) scriptComplexityByAsset(asset crypto.Digest, ev int, filter bool) (*ride.TreeEstimation, error) { - key := assetScriptComplexityKey{ev, asset} +func (sc *scriptsComplexity) scriptComplexityByAsset(asset crypto.Digest, filter bool) (*ride.TreeEstimation, error) { + key := assetScriptComplexityKey{asset} recordBytes, err := sc.hs.topEntryData(key.bytes(), filter) if err != nil { return nil, err @@ -69,7 +96,11 @@ func (sc *scriptsComplexity) scriptComplexityByAddress(addr proto.Address, ev in } func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, estimations map[int]ride.TreeEstimation, blockID proto.BlockID) error { + min := math.MaxUint8 for v, e := range estimations { + if v < min { + min = v + } recordBytes, err := cbor.Marshal(e) if err != nil { return errors.Wrapf(err, "failed to save complexities record for address '%s' in block '%s'", addr.String(), blockID.String()) @@ -80,20 +111,28 @@ func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, estimat return errors.Wrapf(err, "failed to save complexities record for address '%s' in block '%s'", addr.String(), blockID.String()) } } + key := accountOriginalEstimatorVersionKey{addr} + record := estimatorVersionRecord{uint8(min)} + recordBytes, err := cbor.Marshal(record) + if err != nil { + return errors.Wrapf(err, "failed to save original estimator version for address '%s' in block '%s'", addr.String(), blockID.String()) + } + err = sc.hs.addNewEntry(accountOriginalEstimatorVersion, key.bytes(), recordBytes, blockID) + if err != nil { + return errors.Wrapf(err, "failed to save original estimator version for address '%s' in block '%s'", addr.String(), blockID.String()) + } return nil } -func (sc *scriptsComplexity) saveComplexitiesForAsset(asset crypto.Digest, estimations map[int]ride.TreeEstimation, blockID proto.BlockID) error { - for v, e := range estimations { - recordBytes, err := cbor.Marshal(e) - if err != nil { - return errors.Wrapf(err, "failed to save complexities record for asset '%s' in block '%s'", asset.String(), blockID.String()) - } - key := assetScriptComplexityKey{v, asset} - err = sc.hs.addNewEntry(assetScriptComplexity, key.bytes(), recordBytes, blockID) - if err != nil { - return errors.Wrapf(err, "failed to save complexities record for asset '%s' in block '%s'", asset.String(), blockID.String()) - } +func (sc *scriptsComplexity) saveComplexitiesForAsset(asset crypto.Digest, estimation ride.TreeEstimation, blockID proto.BlockID) error { + recordBytes, err := cbor.Marshal(estimation) + if err != nil { + return errors.Wrapf(err, "failed to save complexity record for asset '%s' in block '%s'", asset.String(), blockID.String()) + } + key := assetScriptComplexityKey{asset} + err = sc.hs.addNewEntry(assetScriptComplexity, key.bytes(), recordBytes, blockID) + if err != nil { + return errors.Wrapf(err, "failed to save complexity record for asset '%s' in block '%s'", asset.String(), blockID.String()) } return nil } diff --git a/pkg/state/scripts_complexity_test.go b/pkg/state/scripts_complexity_test.go index 792f28ee7..89ea9797a 100644 --- a/pkg/state/scripts_complexity_test.go +++ b/pkg/state/scripts_complexity_test.go @@ -63,6 +63,9 @@ func TestSaveComplexityForAddr(t *testing.T) { res3, err := to.scriptsComplexity.newestScriptComplexityByAddr(addr, 3, true) require.NoError(t, err) assert.Equal(t, est3, *res3) + res, err := to.scriptsComplexity.newestOriginalScriptComplexityByAddr(addr, true) + require.NoError(t, err) + assert.Equal(t, est1, *res) to.stor.flush(t) @@ -75,6 +78,9 @@ func TestSaveComplexityForAddr(t *testing.T) { res3, err = to.scriptsComplexity.newestScriptComplexityByAddr(addr, 3, true) require.NoError(t, err) assert.Equal(t, est3, *res3) + res, err = to.scriptsComplexity.newestOriginalScriptComplexityByAddr(addr, true) + require.NoError(t, err) + assert.Equal(t, est1, *res) } func TestSaveComplexityForAsset(t *testing.T) { @@ -90,31 +96,16 @@ func TestSaveComplexityForAsset(t *testing.T) { to.stor.addBlock(t, blockID0) asset := testGlobal.asset0.asset.ID - est1 := ride.TreeEstimation{Estimation: 500, Verifier: 500} - est2 := ride.TreeEstimation{Estimation: 600, Verifier: 600} - est3 := ride.TreeEstimation{Estimation: 700, Verifier: 700} - estimations := map[int]ride.TreeEstimation{1: est1, 2: est2, 3: est3} - err = to.scriptsComplexity.saveComplexitiesForAsset(asset, estimations, blockID0) + est := ride.TreeEstimation{Estimation: 500, Verifier: 500} + err = to.scriptsComplexity.saveComplexitiesForAsset(asset, est, blockID0) assert.NoError(t, err) - res1, err := to.scriptsComplexity.newestScriptComplexityByAsset(asset, 1, true) - require.NoError(t, err) - assert.Equal(t, est1, *res1) - res2, err := to.scriptsComplexity.newestScriptComplexityByAsset(asset, 2, true) - require.NoError(t, err) - assert.Equal(t, est2, *res2) - res3, err := to.scriptsComplexity.newestScriptComplexityByAsset(asset, 3, true) + res1, err := to.scriptsComplexity.newestScriptComplexityByAsset(asset, true) require.NoError(t, err) - assert.Equal(t, est3, *res3) + assert.Equal(t, est, *res1) to.stor.flush(t) - res1, err = to.scriptsComplexity.newestScriptComplexityByAsset(asset, 1, true) - require.NoError(t, err) - assert.Equal(t, est1, *res1) - res2, err = to.scriptsComplexity.newestScriptComplexityByAsset(asset, 2, true) + res1, err = to.scriptsComplexity.newestScriptComplexityByAsset(asset, true) require.NoError(t, err) - assert.Equal(t, est2, *res2) - res3, err = to.scriptsComplexity.newestScriptComplexityByAsset(asset, 3, true) - require.NoError(t, err) - assert.Equal(t, est3, *res3) + assert.Equal(t, est, *res1) } diff --git a/pkg/state/state.go b/pkg/state/state.go index fd4059109..0c4041ebd 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2145,11 +2145,7 @@ func (s *stateManager) ScriptInfoByAsset(assetID crypto.Digest) (*proto.ScriptIn return nil, wrapErr(RetrievalError, err) } text := base64.StdEncoding.EncodeToString(scriptBytes) - ev, err := s.EstimatorVersion() - if err != nil { - return nil, wrapErr(Other, err) - } - est, err := s.stor.scriptsComplexity.scriptComplexityByAsset(assetID, ev, true) + est, err := s.stor.scriptsComplexity.scriptComplexityByAsset(assetID, true) if err != nil { return nil, wrapErr(RetrievalError, err) } @@ -2171,11 +2167,7 @@ func (s *stateManager) NewestScriptInfoByAsset(assetID crypto.Digest) (*proto.Sc return nil, wrapErr(RetrievalError, err) } text := base64.StdEncoding.EncodeToString(scriptBytes) - ev, err := s.EstimatorVersion() - if err != nil { - return nil, wrapErr(Other, err) - } - est, err := s.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, ev, true) + est, err := s.stor.scriptsComplexity.newestScriptComplexityByAsset(assetID, true) if err != nil { return nil, wrapErr(RetrievalError, err) } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 9fbd38627..2d7cf4a59 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -129,7 +129,7 @@ func (tc *transactionChecker) checkScriptComplexity(tree *ride.Tree, estimation return nil } -func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity bool) (map[int]ride.TreeEstimation, error) { +func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity, expandEstimations bool) (map[int]ride.TreeEstimation, error) { tree, err := ride.Parse(script) if err != nil { return nil, errs.Extend(err, "failed to build AST") @@ -146,7 +146,11 @@ func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion } estimations := make(map[int]ride.TreeEstimation) - for ev := estimatorVersion; ev <= maxEstimatorVersion; ev++ { + maxVersion := maxEstimatorVersion + if !expandEstimations { + maxVersion = estimatorVersion + } + for ev := estimatorVersion; ev <= maxVersion; ev++ { est, err := ride.EstimateTree(tree, ev) if err != nil { return nil, errs.Extend(err, "failed to estimate script complexity") @@ -412,16 +416,21 @@ func (tc *transactionChecker) checkIssueWithProofs(transaction proto.Transaction // No script checks / actions are needed. return nil, nil } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), false) // For asset scripts do not reduce verifier complexity + // For asset scripts do not reduce verifier complexity and only one estimation is required + currentEstimatorVersion := info.estimatorVersion() + estimations, err := tc.checkScript(tx.Script, currentEstimatorVersion, false, false) if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } assetID := *tx.ID // Save complexities to storage so we won't have to calculate it every time the script is called. - if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, estimations, info.blockID); err != nil { + complexity, ok := estimations[currentEstimatorVersion] + if !ok { + return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", currentEstimatorVersion) + } + if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, complexity, info.blockID); err != nil { return nil, err } - return nil, nil } @@ -1025,7 +1034,7 @@ func (tc *transactionChecker) checkSetScriptWithProofs(transaction proto.Transac } return nil, nil } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), info.blockVersion == proto.ProtobufBlockVersion) + estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), info.blockVersion == proto.ProtobufBlockVersion, true) if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } @@ -1067,15 +1076,20 @@ func (tc *transactionChecker) checkSetAssetScriptWithProofs(transaction proto.Tr if !isSmartAsset { return nil, errs.NewTxValidationError("Reason: Cannot set script on an asset issued without a script. Referenced assetId not found") } - estimations, err := tc.checkScript(tx.Script, info.estimatorVersion(), false) // Do not reduce verifier complexity for asset scripts + currentEstimatorVersion := info.estimatorVersion() + // Do not reduce verifier complexity for asset scripts and only one estimation is required + estimations, err := tc.checkScript(tx.Script, currentEstimatorVersion, false, false) if err != nil { return nil, errors.Errorf("checkScript() tx %s: %v", tx.ID.String(), err) } // Save complexity to storage so we won't have to calculate it every time the script is called. - if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimations, info.blockID); err != nil { + estimation, ok := estimations[currentEstimatorVersion] + if !ok { + return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", currentEstimatorVersion) + } + if err := tc.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { return nil, errs.Extend(err, "saveComplexityForAsset") } - return smartAssets, nil } From 8c5a36e53717ddeee40203fa5fdb4361a0afc3e8 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 11 Jun 2021 09:39:00 +0300 Subject: [PATCH 51/52] Added missed 'iterator.Release()' calls. (#489) --- pkg/grpc/server/server_common.go | 8 +++++++- pkg/state/aliases.go | 11 +++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pkg/grpc/server/server_common.go b/pkg/grpc/server/server_common.go index 4dc5dd2eb..29760f240 100644 --- a/pkg/grpc/server/server_common.go +++ b/pkg/grpc/server/server_common.go @@ -5,6 +5,7 @@ import ( g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/node/grpc" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/state" + "go.uber.org/zap" ) func (s *Server) transactionToTransactionResponse(tx proto.Transaction, confirmed, failed bool) (*g.TransactionResponse, error) { @@ -47,7 +48,12 @@ type filterFunc = func(tx proto.Transaction) bool type handleFunc = func(tx proto.Transaction, failed bool) error func (s *Server) iterateAndHandleTransactions(iter state.TransactionIterator, filter filterFunc, handle handleFunc) error { - defer iter.Release() + defer func() { + iter.Release() + if err := iter.Error(); err != nil { + zap.S().Fatalf("Iterator error: %v", err) + } + }() for iter.Next() { // Get and send transactions one-by-one. tx, failed, err := iter.Transaction() diff --git a/pkg/state/aliases.go b/pkg/state/aliases.go index adcb1d40f..c8a45ba89 100644 --- a/pkg/state/aliases.go +++ b/pkg/state/aliases.go @@ -194,7 +194,12 @@ func (a *aliases) disableStolenAliases() error { if err != nil { return err } - + defer func() { + iter.Release() + if err := iter.Error(); err != nil { + zap.S().Fatalf("Iterator error: %v", err) + } + }() for iter.Next() { keyBytes := iter.Key() recordBytes := iter.Value() @@ -211,9 +216,7 @@ func (a *aliases) disableStolenAliases() error { a.disabled[key.alias] = true } } - - iter.Release() - return iter.Error() + return nil } func (a *aliases) prepareHashes() error { From 6555424c43715bd8bec4de9dc97343fad382af05 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 15 Jun 2021 13:06:02 +0300 Subject: [PATCH 52/52] Merge master into version 0.9 (#491) * Costs of RIDE functions transactionHeightByID and blockInfoByHeight reduced for version 4 of standard library (#406) * Fixed empty senderPublicKey field while asset scritp execution. Fixed an issue then half empty TransferScriptAction produced on invalid asset. (#407) * Fixed calculation of size dependant part of fee of protobuf version of DataTransaction (#409) * RIDE function takeString works with string as UTF-16 string (#418) * Switchable bloom filter. (#424) * Switchable bloom filter. * Fix tests. * Proofs validation added to protobuf and json unmarshaling (#429) * Added error loggs handling (#433) * Added errors handling * Changed function name * Deleted useless struct * Changed errors' logs for shutting down * Changed func name and renamed back a few logs * RIDE function to remove element of list by index implemented and tested. (#435) * Fix microblock signature (#430) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Added block state cache (#434) * Rescheduling on new microblock was removed * Metrics for blocks and microblocks replaced with new one * Metrics improved. * Issue with microblock invalid signature in case of protobuf transactions fixed. Handling of protobuf transactions broadcast messages added. * RIDE function takeString works with string as UTF-16 string * Proofs validation added to protobuf and json unmarshaling * Dependencies updated * Added block state cache * Changed the condition of rollback * Changed position of condition of rollback * Adding block states receiving microblocks * Less logging especially of context cancelation. Naming fixed. * Peer error handling on context cancelation is reverted, but logging is updated. * Block cache cleaning moved to key block application functions. * Functions to check that block already exists added to FSM's block applier. * Cache size debug messages added. Fixed block ID to get from cache. Co-authored-by: Alexey Kiselev * Move error logging to debug (#437) * Log level of errors on appending transaction to UTX set to DEBUG * Network connection errrors moved to DEBUG level * More network log messages moved to DEBUG level. Fixed an issue with invalid blocks added to blocks cache. Naming fixed. * Error on state changing while mining micro block moved to DEBUG level. Handling of micro-block mining task added to Sync FSM. * RIDE function addressToString now accepts invalid address (#444) * Fix block info vrf (#469) * Typo in BlockInfo's field name fixed. VRF calcuation in function blockInfoByHeight replaced by retrieval of hit source at given height. * Function ProtoBlockHitSource doesn't return error but empty slice of bytes. * WIP: Fixed VRF calculation for RIDE, but it fails to retriev actual hit sources for now. * New way to store and precalculate hit sources implemented. BlockVRF is reading not commited hit sources now. * Refactoring of duplicate functions. * Seed peers ports updated. * Fixed error handling * One more error handling fix Co-authored-by: Frozen Co-authored-by: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> --- pkg/api/node_api.go | 5 +++-- pkg/node/actions_by_type.go | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/api/node_api.go b/pkg/api/node_api.go index 8956f64ec..d08b72b9f 100644 --- a/pkg/api/node_api.go +++ b/pkg/api/node_api.go @@ -9,9 +9,10 @@ import ( "net/http" "strconv" + "github.com/pkg/errors" + "github.com/go-chi/chi" "github.com/mr-tron/base58" - "github.com/pkg/errors" apiErrs "github.com/wavesplatform/gowaves/pkg/api/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/node" @@ -34,7 +35,7 @@ func NewNodeApi(app *App, state state.State, node *node.Node) *NodeApi { } } -func (a *NodeApi) TransactionsBroadcast(w http.ResponseWriter, r *http.Request) error { +func (a *NodeApi) TransactionsBroadcast(_ http.ResponseWriter, r *http.Request) error { b, err := ioutil.ReadAll(r.Body) if err != nil { return errors.Wrap(err, "TransactionsBroadcast: failed to read request body") diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index e6ef75a9c..5680d4c25 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -1,10 +1,11 @@ package node import ( - "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" "math/big" "reflect" + "github.com/wavesplatform/gowaves/pkg/node/peer_manager/storage" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/node/state_fsm"